Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

SRAM simultaneous read and write?

Status
Not open for further replies.

Artlav

Full Member level 2
Joined
Nov 26, 2010
Messages
144
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,298
Activity points
2,723
Hello.

In short, how can i read and write to a single-port SRAM at once?

In details, there are three things i have in the design:
-an SRAM that i can either write or read.
-A VGA controller that reads the SRAM and draws the content
-And some logic that writes a pattern into SRAM

At the moment whether the read or write source is uses is being toggled by a register controlled from a switch on board.

The problem is that i can't seem to find a way to have the SRAM written to and read at the same time.

I tried to toggle the source register at every clock, or some fraction of it, with chaotic results on both screen and in memory.


In theory, the proper solution seems to be to use an arbiter.
And here is the main problem - while i think i know what arbiter does and have a working sample of a simple one, i, however, have not a faintest idea how to use it to get the dual-port access i need.

The arbiter have 2 request inputs, a clock, and sets either of the 2 grant outputs.
Just setting the grant to the source register does not work.
Several attempts to link them up in ways that appeared reasonable to me produced nothing but compile errors.

So, can anyone help me figure it out?
I would appreciate a Verilog example, since i appear to miss a concept here.
 

by definition, you cannot. You really want a "simple dual port" RAM, which allows 1 read and 1 write per cycle.

arbiters can be simple or somewhat complex. You also have "mutex" or locking to deal with.

basically, if you want to read the next frame out, you must wait until it has been generated (worst case) or until at least 1 word has been generated (best case). this becomes an issue if either the frame generation takes a variable amount of time for example.

the easiest arbitor is just: s <= not s; s=0 implies "i can read if I want to" and s=1 implies "I can write if I want to". Locking must be done to prevent the read machine from reading a frame that doesn't exist. This "round-robin" arbiter limits the read BW and write BW to 1/2 clk rate.

The next easiest arbitor is a "priority encoder" which works by looking at a signal for "i want to read" and "i want to write", and then favoring reads or writes (often writes are favored).

ping-pong buffers are another concept. you store frame 1 and display it. then you start work on frame 2. frame 1 will be displayed 1 or more times until frame 2 is ready. when frame 2 is ready, it will be displayed. frame 3 will be written to the same space as frame 1. if needed, frame 2 will be displayed more than one time if frame 3 is not ready. then frame 4 will use the space frame 2 used, and frame 3 will be displayed until frame 4 is ready.
 

Thank you for answering,

by definition, you cannot.
I may have poorly defined my intentions. By simultaneous i meant two blocks accessing a shared resource, in this case - SRAM chip.
VGA controller have a precise timing it should follow on reading.
Writing (or another reader) is not time-critical, and can wait a little, but should be able to proceed without interrupting the drawing or delaying for too long.

I would have expected this kind of problem being solved long ago, since there are CPUs accessing graphic memory in linear buffer, or multiple CPUs accessing shared memory, or various memory-mapped I/O things, etc.
That is the kind of simultaneous access i need to get.


As for locking\mutex\arbiter - i get the algorithm, but i have no idea how to implement it.

For example:

The simple writing code:
(*= AT symbol, the forum complains if i use it)
Code:
wire [2:0] sram_select=1+SW[0];

reg [15:0] sram_wr_data;
wire [15:0] sram_write_data;
reg [17:0] wr_sram_addr;

assign sram_write_data=sram_wr_data;

always *(posedge CLOCK_50)
begin
 if(wr_sram_addr>=153600)wr_sram_addr<=0;
                    else wr_sram_addr<=wr_sram_addr+1;
  
 sram_wr_data<=wr_sram_addr
end

SRAM access, whether 1 or 2 is used is selected by sram_select:
Code:
Multi_Sram the_sram(
 //Side 1
 .oAS1_DATA(mSRAM_VGA_DATA),
 .iAS1_ADDR(sram_vga_addr),
 .iAS1_WE_N(1'b1),
 .iAS1_OE_N(1'b0),
 //Side 2
 .iAS2_DATA(sram_write_data),
 .iAS2_ADDR(wr_sram_addr[17:0]),
 .iAS2_WE_N(1'b0),
 .iAS2_OE_N(1'b1),
 //Control Signals
 .iSelect(sram_select),
 //SRAM
 .SRAM_DQ(SRAM_DQ),
 .SRAM_ADDR(SRAM_ADDR),
 .SRAM_UB_N(SRAM_UB_N),
 .SRAM_LB_N(SRAM_LB_N),
 .SRAM_WE_N(SRAM_WE_N),
 .SRAM_CE_N(SRAM_CE_N),
 .SRAM_OE_N(SRAM_OE_N) 
);

The VGA have an output of sram_vga_addr, and it's own clock to set it by.
mSRAM_VGA_DATA is decoded to the VGA output.

Arbiter, based on code in asic-world tutorials, takes (clk,req1,req0,gnt1,gnt0).
So, the code is supposed to set the request, detect the grant, act, unset the request, wait for the next clock.
Same goes for VGA code.

But how to make it do that?
How to link it all up?

I don't understand a few things here - how long should it take for the VGA output and read from memory to take effect?
How long does it take to write to memory?
How and at what moment could i unset request for VGA read?

Is it conceivable to run the writer at twice the clock of VGA, and each second half to write to memory?
How many reads/writes can i hope to get before VGA is disrupted regardless?

All in all, how are such thing done properly?

ping-pong buffers are another concept.
Not really an option, as there is just enough memory for one frame.
In any case, i want to figure out how to access a shared resource.
 

Figured it out, i think.
My problem was thinking more in terms of software rather than in terms of circuits.
So, instead of trying to do a mutex and all, the proper solution was to wire the writer so that it would write while the VGA does not read and block the rest of the time.
How? By waiting until the retrace! Thus, "wire [2:0] sram_select=1+!(VGA_H_SYNC & VGA_V_SYNC);" and similarly at the writer.

Now, does that solution makes sense or am i deceiving myself somewhere?
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top