[ Verilog FAQ  |  Tips  |  Online Books |  Papers  |  Free Stuff |   Tools  | Jobs | What's New  ]

Technical Tidbits

Introduction

This contribution came from a discussion on the comp.lang.verilog bulletin board which was initiated by Farhad Sunavala concerning RAM modelling. Thanks go to t he several people who contributed to the discussion and to Farhad, for summarizing the discussion here.

The question was, "how do you model a RAM in Verilog?" Assume the following:

// d -> data inputs
// q -> RAM output

Solution 1:

input r_wb;
input [7:0 ] d;
ouput [7:0] q;
reg [7:0] q;
reg [7:0] mem_bank [0:255];
always @(r_wb)
always @(d)
endmodule

This works fine since the RAM inputs & outputs are separate. However, consider t he case of a RAM where the input data and output data are one inout port:

input r_wb;
inout [7:0] d_q;

Solution 1 does not work for this case since the bidirectional data bus cannot b e declared as a register in the module.

Solution 2:

Gary Cook (BNR Europe) suggested the following:
inout [7:0] d_q;
reg [7:0] data [0:255];
assign d_q = (r_wb) ? data[addr] : 8'hz ;
always @(r_wb)
if (!r_wb) data[addr] = d_q ;
if (!r_wb) data[addr] = d_q ;
endmodule

The assign puts the stored 'data' onto the d_q bus when r_wb is high, ie indicat ing a read. When d_q is low , the assign tri-states the d_q which can be driven by the driving device.

[Ed. note: This solution has several potential gotchas. What does this model do if addr and r_wb change at the same time?]

Solution 3:

David McGhee (University of Alabama) contributed the following:

Here's an example of how I do memories - tribuf8 is a module that contains 8 tri -state buffers:

`define MEMORIES
`ifdef REGISTERS
`else
`include "registers.v"
`endif
`ifdef DELAYPERGATE
`else
`define DELAYPERGATE 10
`endif
parameter delay = `DELAYPERGATE;
inout [ 7:0] data;
input wr,rd;
// Modeling memory using 4 CMOS
// transistors per bit...yeah right..
reg [7:0] memoryspace [65535:0];
wire [7:0] localdataout;
// The value at the current address is
// always at the input of the buffer
// A rising edge of the write pulse
// actually puts the data into memory
always @(negedge wr)
// Write must be low to prevent
and #delay u1(output enable,rd,~wr);
// If a read occurs then just
// enable the output wires onto
// the bus.
tribuf 8 #delay outbuf(data,localdataout, outputenable);
endmodule

[Ed. note: Check out the use of a non-blocking assign in the write to memoryspac e. Is this correct? Hint: the delay should be an intra-assignment delay. Then, t he assignment can be either blocking or non-blocking.]

Conclusion

Modelling a RAM is a common thing to do in Verilog, and there are a variety of ways to do it. Most all are some variation on using a bidirectional port with a conditional driver, either a conditional continuous assignment or a tri-state buffer.

 [ Verilog FAQ  |  Tips  |  Online Books |  Papers  |  Free Stuff |   Tools  | Jobs | What's New  ] Copyright Rajesh Bawankule  1997-2003