RAMs CLKs and Edges

S

Simon

Guest
Hi all,

I'm using icarus to simulate a CPU using RAMB16_S36_S36 blockram's for
the register file. The Blockram obviously isn't defined for Icarus, so
I'm using a simulation model instead, defined as:

module registerFile(clk,writeEnable,RdstAddr,RsrcAddr,bank,RdstDataIn,
RsrcDataOut,RdstDataOut);
input clk;
input writeEnable;
input [5:0] RdstAddr;
input [5:0] RsrcAddr;
input [3:0] bank;
input [31:0] RdstDataIn;
output [31:0] RsrcDataOut;
output [31:0] RdstDataOut;

// ================================================================================
// Construct the actual addresses for the RAM locations - use the 'bank' address
// if the high-order bit is set in the address register. 'bank' shouldn't be 0.
// ================================================================================
wire [8:0] sa = (RsrcAddr[5] == 1'b1) ? {bank,RsrcAddr[4:0]}
: {3'b0,RsrcAddr};
wire [8:0] da = (RdstAddr[5] == 1'b1) ? {bank,RdstAddr[4:0]}
: {3'b0,RdstAddr};


`ifdef synthesis
RAMB16_S36_S36 regfile1 (
.DOA(RdstDataOut), // Rdst 32-bit Data Output
.DOB(RsrcDataOut), // Rsrc 32-bit Data Output
.ADDRA(da), // Rdst 9-bit Address Input
.ADDRB(sa), // Rsrc 9-bit Address Input
.CLKA(clk), // Rdst Clock
.CLKB(clk), // Rsrc Clock
.DIA(RdstDataIn), // Rdst 32-bit Data Input
.ENA(1'b1), // Rdst RAM Enable Input
.ENB(1'b1), // Rsrc RAM Enable Input
.SSRA(1'b0), // Rdst Sync Set/Reset Input
.SSRB(1'b0), // Rsrc Sync Set/Reset Input
.WEA(writeEnable), // Rdst Write Enable Input
.WEB(1'b0)); // Rsrc Write Enable Input

`else

reg [31:0] mem [0:511]; // The actual memory
reg [31:0] RdstDataOut, RsrcDataOut; // registered outputs
reg [31:0] i; // initialisation...

initial begin
RdstDataOut = 0;
RsrcDataOut = 0;
for (i=0; i<512; i = i+1)
mem = 0;
end

always @(posedge clk) begin
if (writeEnable)
begin
mem[da] <= RdstDataIn;
RdstDataOut <= RdstDataIn;
end
end

always @(negedge clk) begin
if (~writeEnable)
RdstDataOut <= mem[da];
end

always @(negedge clk) begin
RsrcDataOut <= mem[sa];
end

`endif // synthesis

endmodule

[hmm, only seems to appear sensibly if 'paste as quotation' is used in
Mozilla :(]

Anyway, the point is: notice the '@posedge' and '@negedge' parts of the
not-for-synthesis definition. Is this indicative of me getting something
fundamentally wrong elsewere in my code ? If I make them all posedge,
the RAM doesn't work in the testbench, and similarly if I invert the
polarity of the edge detection.

The thing is that I think the Spartan-3 blockrams are asynchronous read
and synchronous write, so really the @negedge(clk) parts ought to be
'assert XXX <= YYY', however if I do that ...

//always @(negedge clk) begin
// if (~writeEnable)
// RdstDataOut <= mem[da];
//end
always @(posedge clk) begin
if (~writeEnable)
assign RdstDataOut = mem[da];
end

//always @(negedge clk) begin
// RsrcDataOut <= mem[sa];
//end
always @(posedge clk) begin
assign RsrcDataOut = mem[sa];
end
.... then the testbench seems to work, but I can't $display the values
written to the RAM until the next clock cycle - they do appear to be
being updated in the correct cycle though. It's pretty useful to be able
to see what gets written to Rdst, so finally, a question [grin] :

Can I assume that the 1st version is actually ok, (even though it uses
weird edge conventions), *because* it matches the behaviour of the 2nd
version, which is how I think the real RAM works ?

Tx for any help

Simon
 

Welcome to EDABoard.com

Sponsor

Back
Top