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,ban k,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[i] = 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