FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6365 Discussions

IP AltsyncRam -- Read/Write operations issue

Altera_Forum
Honored Contributor II
2,672 Views

Hi all,  

 

I have another issue using the RAM IP core generated with the MegaFunction wizard. 

Here's the entity of my RAM and its instanciation: 

GENERIC( ADDRESS_WIDTH : IN INTEGER ; PIXEL_WIDTH : IN INTEGER ); PORT ( address_a : IN STD_LOGIC_VECTOR (ADDRESS_WIDTH-1 DOWNTO 0); address_b : IN STD_LOGIC_VECTOR (ADDRESS_WIDTH-1 DOWNTO 0); addressstall_a : IN STD_LOGIC; addressstall_b : IN STD_LOGIC; clock : IN STD_LOGIC ; data_a : IN STD_LOGIC_VECTOR (PIXEL_WIDTH-1 DOWNTO 0); data_b : IN STD_LOGIC_VECTOR (PIXEL_WIDTH-1 DOWNTO 0); rden_a : IN STD_LOGIC := '1'; rden_b : IN STD_LOGIC := '1'; wren_a : IN STD_LOGIC := '1'; wren_b : IN STD_LOGIC := '1'; q_a : OUT STD_LOGIC_VECTOR (PIXEL_WIDTH-1 DOWNTO 0); q_b : OUT STD_LOGIC_VECTOR (PIXEL_WIDTH-1 DOWNTO 0) ); altsyncram_component : altsyncram GENERIC MAP ( address_reg_b => "CLOCK0", clock_enable_input_a => "BYPASS", clock_enable_input_b => "BYPASS", clock_enable_output_a => "BYPASS", clock_enable_output_b => "BYPASS", indata_reg_b => "CLOCK0", intended_device_family => "Cyclone III", lpm_type => "altsyncram", numwords_a => 2**ADDRESS_WIDTH, numwords_b => 2**ADDRESS_WIDTH, operation_mode => "BIDIR_DUAL_PORT", outdata_aclr_a => "NONE", outdata_aclr_b => "NONE", outdata_reg_a => "UNREGISTERED", outdata_reg_b => "UNREGISTERED", power_up_uninitialized => "FALSE", read_during_write_mode_mixed_ports => "OLD_DATA",--OLD_DATA read_during_write_mode_port_a => "OLD_DATA", read_during_write_mode_port_b => "OLD_DATA", widthad_a => ADDRESS_WIDTH, widthad_b => ADDRESS_WIDTH, width_a => PIXEL_WIDTH, width_b => PIXEL_WIDTH, width_byteena_a => 4, width_byteena_b => 4, wrcontrol_wraddress_reg_b => "CLOCK0", width_b => PIXEL_WIDTH, width_byteena_a => 4, width_byteena_b => 4, wrcontrol_wraddress_reg_b => "CLOCK0"  

 

ADDRESS_WIDTH equals 10 and PIXEL_WIDTH equals 14. 

The issue is the following:  

 

Port A is used for READ accesses only, and port B for WRITE accesses only. 

These accesses happen through a pipeline that consist in a READ access through port A (1 clock cycle latency), getting the result on q_a port and add 1 to it (1 clock cycle latency), then write (q_a + 1) at the same address. 

 

In other words the address_a and the address_b buses are identical, with a two-clock-cycle latency. 

 

The problem is that, for some reason, an 'X' value appears on the q_a bus after a read cycle. That does not make sense to me since read_address and write address are never identical at the same clock rising edge. 

 

These 'X' values are a problem because they propagate in the pipeline and mess up the whole results. 

 

I join a snapshot of my Modelsim run to illustrate the issue. 

 

Thanks for your help!
0 Kudos
10 Replies
Altera_Forum
Honored Contributor II
507 Views

Without going into details, the memory rule is you first write then read. 

If yoy read a location before it is written to then its content is undefined in the initial stage and may not matter.
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

Thanks kaz for the reply,  

 

I thought the altsyncram contents were initialized at '0' when you tick the "No,leave it blank" box under MegaFunction wizard, in the "Mem Init" tab. 

 

I mean, I 've already run that sequence of operations with an altsyncram (READ, then +1 on q_a, then WRITE) only it wasn't pipelined. It worked like a charm. Only, during the first run, I only got zero's on q_a bus. 

 

Thinking of that, when I did that, my read_enable and write_enable signals were only asserted for the presentation of data and address. After I switch them back to '0'. Whereas here it's not the case, they are always asserted.  

Could this be the issue?
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

When you leave that box blank it means no initialisation.  

You shouldn't worry about 'x' states if your application doesn't care. So you can keep your write/read cycles. 

It will be the first read that causes 'x' which may be too visible or not in simulation depending on pipeline. Once a location is written to then it is readable as many times as you wish. 

 

If you want cosmetic surgery then you can initialise all to zeros with a file.
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

Thanks again kaz, I think I see what you mean know. 

 

And it's pretty much what appears in Altera generated waveforms (which I joined). It takes one dummy read cycle, where outputs are 'X' and after that, one dummy write cycle (read of 000 and 001 addresses) and the outputs become valid. 

 

However, after that dummy write cycle, is it OK to read anywhere in the RAM, or do you need to write everywhere (at every location) before reading everywhere?
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

every Locations will be 'X' untill it is written to, so writing a single '0' into 1 location will not make them all 0.  

 

Co-incidently, in real hardware there is no 'X', just 0 and 1 (and 'z' if its an output pin). If you did a read before any writes to that particular location, you are just going to get back a random number, whatever the memory powered up to, which is usually just noise.
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

Just write/read as required provided you get things in time. This requires that your design expects the first read from every location not to be valid. 

so the x values(0 or 1 ...etc) are going to be discarded by your design.
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

It's RAM. If you don't write anything to an address, then the contents of that address are undefined. That is how RAM has always worked. Modelsim is essentially telling you "Hey nothing has been written to this location!". In which case you'd most certainly better not be using the data. 

 

As far as the dummy read/write cycle thing. That's not the best way to phrase it. There is a one clock latency minimum for reads. Writes are performed on the clock cycle where the command is presented. 

 

Jake
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

Thanks all, I guess I have to think about modifying my pipeline so that no RAM location is read before something has been written to it first. 

 

Or, as kaz said, discard 'x' values I get for every location that I read for the first time. 

 

My RAM has 1024 addresses, 14-bit data, so I have to build a "map" of the locations read at least once and the ones never read. 

 

Any suggestions to achieve that in logic would be much appreciated. 

 

Thanks again to all, I am new to HDL design using RAM blocks, so I am learning here...
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

Hi, 

 

I don't see why you get worried about first set of undefined data. Designs normally wash off initial values and look for some start flags e.g. start of a packet ...etc.  

 

However if your design depends on that initial read then I can add one more bit to each location to flag '1' indicating that data was written and true.  

You will need to initialise mem to zero first using a mif file. 

 

Though this is overkill. You can also use simpler toggle logic if there is a pattern between write/read.
0 Kudos
Altera_Forum
Honored Contributor II
507 Views

OK, when I run a pass of write accesses on every location of my RAM block, every read acces after that works perfectly fine. I don't have no 'X' values under ModelsIm anymore. 

 

Thank you all, problem solved! :)
0 Kudos
Reply