I'm trying to write a Verilog module which iterates over elements of an external memory in each cycle. The problem I'm facing right now, is that changing the address of the memory during the cycle will not cause the input data be changed, in that same cycle.i.e: changing the address will not cause the input data to be changed in one cycle.I'll illustrate the problem with some code:
module r(input rst, ..., output reg [MEMORY_ADDR_WIDTH-1:0] addr, input memory_value);
//...
always @(posedge clk) begin
//...
for(addr = 0; addr < MEMORY_SIZE; addr = addr+1) begin
if (memory_value) //...
// PROBLEM: changing addr in this loop doesn't cause memory_value to change
end
end
endmodule
And here is how I instantiate the module
module top;
reg mem[MEMORY_SIZE-1:0];
wire [MEMORY_ADD_WIDTH-1:0] addr;
//...
r r( rst, ..., addr, mem[addr]);
endmodule
I'm using Modelsim to simulate the design. First of all, is this expected behaviour, and if it is what's a common workaround?
for
loops in Verilog are used to create several copies of an assignment. The loop is automatically unrolled (which is why it needs constant bounds).
For example
always@(posedge clk)
for (i=1; i<4; i=i+1)
foo[i] <= foo[i-1]*foo[i-1];
is equivalent to
always@(posedge clk) begin
foo[1] <= foo[0]*foo[0];
foo[2] <= foo[1]*foo[1];
foo[3] <= foo[2]*foo[2];
end
So, the code you provided never assigns a value to addr
, which is likely why you aren't see any change. (In the same way that i
doesn't appear in the second part of my example)
Consider instead splitting these up.:
always@(posedge clk)
addr<=(addr+1)%ADDR_MAX;
always@(*)begin
if (memory_value) // mem[addr]
//...
end