UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Observer matthuszagh
Observer
312 Views
Registered: ‎07-16-2018

How to use read-first BRAM to write current value + another value back to same memory location

Jump to solution

I'd like to add a new value to the current value in ram and write that back into the same address in ram. However, I'm not entirely sure how to infer this.

Can I use something like this?

 

always @(posedge clk) begin
   if (we) begin
      mem[addr] <= di + mem[addr];
// mem[addr] <= di + do; // this instead? end do <= mem[addr]; end

I understand that under normal circumstances this is garbage since mem[addr]/do doesn't change until the next clock edge. But from the Xilinx documentation it sounds like maybe it does for read first. Have I misunderstood read first? What's the point of read first if not this?

 

If this is correct, how can I simulate this without it setting the value at the next clock edge?

 

My clock rate is slow, so I could double the clock frequency and add a pipeline register. But it sounds like with 'read first' mode maybe I don't need the pipeline. Is this correct?

0 Kudos
1 Solution

Accepted Solutions
251 Views
Registered: ‎01-08-2012

Re: How to use read-first BRAM to write current value + another value back to same memory location

Jump to solution

You don't get the old value until after the clock that was used to write the new value, so no, you can't perform a read-modify-write in a single clock using a single ported BRAM.

Note that you could do it (for a very small memory) in CLB RAM (aka distributed RAM), because these RAMs have an asynchronous read.

 

This reminds me of a old design of mine that added numbers to a large bank of accumulators in BRAM.  Perhaps there were 512 x 32 bit accumulators.  The module had a 9 bit address input, a 32 bit input number to add (the addend), and an enable signal to tell it to add the addend to the accumulator selected by the address input.

It could accumate a number every clock, and it could do it with an arbitrary sequence of addresses.  It was fully pipelined (including the extra output register on the BRAM), and could run at ... well, I only needed it to go to 322MHz or so but it could probably go faster.

You can do all that by borrowing a technique from pipelined CPUs.  I suggest searching for "pipeline bypass" or perhaps "CPU pipeline bypass" for ideas.  The circuit is actually quite simple.  Basically you keep a history of recent writes to the RAM.  This history must be as long as the RAM read latency (perhaps three clocks).  Each entry in the history contains the address tag and the data value written.  If a new request comes in, scan the history for a matching address, and (if found), substitute the data value from the history in place of the data value read from the RAM.

View solution in original post

2 Replies
252 Views
Registered: ‎01-08-2012

Re: How to use read-first BRAM to write current value + another value back to same memory location

Jump to solution

You don't get the old value until after the clock that was used to write the new value, so no, you can't perform a read-modify-write in a single clock using a single ported BRAM.

Note that you could do it (for a very small memory) in CLB RAM (aka distributed RAM), because these RAMs have an asynchronous read.

 

This reminds me of a old design of mine that added numbers to a large bank of accumulators in BRAM.  Perhaps there were 512 x 32 bit accumulators.  The module had a 9 bit address input, a 32 bit input number to add (the addend), and an enable signal to tell it to add the addend to the accumulator selected by the address input.

It could accumate a number every clock, and it could do it with an arbitrary sequence of addresses.  It was fully pipelined (including the extra output register on the BRAM), and could run at ... well, I only needed it to go to 322MHz or so but it could probably go faster.

You can do all that by borrowing a technique from pipelined CPUs.  I suggest searching for "pipeline bypass" or perhaps "CPU pipeline bypass" for ideas.  The circuit is actually quite simple.  Basically you keep a history of recent writes to the RAM.  This history must be as long as the RAM read latency (perhaps three clocks).  Each entry in the history contains the address tag and the data value written.  If a new request comes in, scan the history for a matching address, and (if found), substitute the data value from the history in place of the data value read from the RAM.

View solution in original post

250 Views
Registered: ‎01-08-2012

Re: How to use read-first BRAM to write current value + another value back to same memory location

Jump to solution

(I can't edit for some reason.)

The history also needs to include a "valid" flag.

0 Kudos