Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20638 Discussions

Stratix V MLAB Byte Enable Issue

Altera_Forum
Honored Contributor II
1,013 Views

Hi, 

 

I am trying to implement a very small memory as a data buffer attached to an Avalon-MM interface. 

 

As the memory is only 16bytes, and I require that the output be unregistered, I am using MLABs to implement this ram using the following altdpram instantiation: 

 

altdpram# ( .byte_size (8), .indata_aclr ("OFF"), .indata_reg ("INCLOCK"), .intended_device_family ("Stratix V"), .lpm_type ("altdpram"), .outdata_aclr ("OFF"), .outdata_reg ("UNREGISTERED"), .ram_block_type ("MLAB"), .rdaddress_aclr ("OFF"), .rdaddress_reg ("UNREGISTERED"), .rdcontrol_aclr ("OFF"), .rdcontrol_reg ("UNREGISTERED"), .read_during_write_mode_mixed_ports("DONT_CARE"), .width (32), .widthad (2), .width_byteena (4), .wraddress_aclr ("OFF"), .wraddress_reg ("INCLOCK"), .wrcontrol_aclr ("OFF"), .wrcontrol_reg ("INCLOCK") ) transferMemRead ( //Write port (from I2C) .inclock (clock), .inclocken (busy), .wraddress (src_address), .byteena (src_byteen), .wren (src_write), .data ({(4){src_data}}), //copy src data to all byte locations //Read port (to AvMM) .rdaddress (csr_address), .q (csr_data), .aclr (1'b0) );  

 

Basically when the busy flag is high, the MLAB contents will be written with data from an I2C read transfer. This transfer is done byte-wise whereas Nios works with 32bit words. As such I am using byte enables to select which byte is written - the byte enable is generated by a one-hot counter which I can see from signaltap is correctly producing the required sequence (4'd1,4'd2,4'd4,4'd8,4'd1,...). 

 

The byte enable is doing its job in that the incoming data byte is not written to all bytes, however, the contents of the non-enabled bytes is being cleared. To explain, I end up with the following sequence: 

 

Byte En | Data In | Mem Contents 0001 | 0x45 | 0xFFFFFF45 0010 | 0x22 | 0xFFFF22FF <- Should be 0xFFFF2245 0100 | 0x55 | 0xFF55FFFF <- Should be 0xFF552245 1000 | 0xAA | 0xAAFFFFFF <- Should be 0xAA552245  

 

Notice how the contents of the memory gets wiped - non-enabled bytes are getting replaced by 0xFF. 

 

I have a second memory going the other direction (from Nios to the I2C controller) which if I do byte-wise writes from Nios (using IOWR_8DIRECT), the same thing happens. If however from Nios I do a 32bit write (IOWR_32DIRECT), then the word is written correctly. 

 

 

So is there a reason for this? Is there something that I am missing about the byte enables that are causing this weird behavior?
0 Kudos
1 Reply
Altera_Forum
Honored Contributor II
289 Views

Never mind. I gave up with altdpram and simply wrote my own module with an inferred RAM. Works perfectly 

 

/* * I2C CSR Zero-Latency RAM * ------------------------ * * This module provides inferred RAM logic with zero read latency * and working byte enables. For some reason the altdpram instances * are failing to use byte enables correctly. * */ module i2c_csr_ram_hw# ( parameter DATA_WIDTH = 32, parameter BYTEEN_WIDTH = 4, parameter ADDR_WIDTH = 2 ) ( input clock, input writeAddress, input writeByteEn, input writeData, input writeEn, input readAddress, output reg readData ); localparam MEM_WORDS = 1 << ADDR_WIDTH; localparam BYTE_WIDTH = DATA_WIDTH / BYTEEN_WIDTH; //For simplicity the memory for each byte is instantiated separately. genvar i; generate for (i = 0; i < BYTEEN_WIDTH; i = i + 1) begin : ram_loop //Offset into data word localparam j = BYTE_WIDTH * i; //Our memory for this byte reg memory ; //Write port always @ (posedge clock) begin if (writeByteEn && writeEn) begin //When this byte is enabled and we are performing a write memory <= writeData; //Store this byte from the writeData word. end end //Read port with zero latency always @ * begin readData <= memory; end end endgenerate endmodule  

 

Just one more Altera IP core to add to my growing list of IP never to use again...
0 Kudos
Reply