I am attempting to initialize my memory to zeros so that later I can initialize my memory with a file. My memory is composed of sram blocks, each of which is 32-lines and 32-bits per line. The sram32x32 have a member in the module called reg [31:0] mem [31:0]. Each bank contains some blocksPerBank amount of these 32x32 blocks. There are sramBanks=8 banks right now.
Consecutive memory addresses interleave through each bank. After going through each bank, it goes to the next line. After going through all of the lines, it goes to the next block. After that, it rolls back around (this can be seen in the nested for-loop ordering in the initial block). Here is how I instantiate and initialize my memory. I think this should be sufficient information, but let me know if more is necessary.
generate
for(i=0; i<sramBanks; i=i+1) begin : bank
sram32x32$ block [blocksPerBank-1:0]
(obtag[tagLineMSB:tagLineLSB],
cdb[i*32 +: 32], 1'b0,
FSM_memWR, FSM_ceEnAdj
);
end
integer b, l, k;
initial begin
for(b=0; b<blocksPerBank; b=b+1) begin : bpb
for(l=0; l<32; l=l+1) begin : ln
for(k=0; k<sramBanks; k=k+1) begin : sbnk
bank[k].block[b].mem[l] = 32'b0;
end
end
end
end
endgenerate
But the error I get is:
Error-[XMRE] Cross-module reference resolution error
MainMemory.v, 149
Error found while trying to resolve cross-module reference.
token 'bank'. Originating module 'MainMemory'.
Source info: bank[k].block[b].mem[l] = 32'b0;
How do I reference the modules from the generate loop while in my initial statements?
The index of an arrayed module instance needs to constant. Therefore, b and k need to be genvar.
genvar b, k;
generate
for(b=0; b<blocksPerBank; b=b+1) begin : bpb
for(k=0; k<sramBanks; k=k+1) begin : sbnk
integer l;
initial begin
for(l=0; l<32; l=l+1) begin : ln
bank[k].block[b].mem[l] = 32'b0;
end
end
end
end
endgenerate
Note that integer l is defined inside the for-loop. Each look creates a l visable to the local scope. This prevents clobbering when the generated b*k initial blocks execute in parallel.
Related
I'd like to force some bunch of signals by derived multiple instances in verilog as below.
integer ii;
initial begin
for (ii=0; ii<19; ii=ii+1) begin
force sydnney.top.vx1.mpg.jpg[ii].trig.be[3] = 1'b1;
end
end
But, I've got the below error :
Illegal operand for constant expression [4(IEEE)].
Is that impossible way to using like that?
update
I've got some error when I use as below,
generate
wire val;
genvar xidx;
for(val=0; val<3; val=val+1) begin : force_be3y_loop
#10
for(xidx=0; xidx<3; xidx=xidx+1) begin : force_be3x_loop
initial force top.comp.img.tc[xidx].t1c.b2tc = val;
initial force top.comp.img.tc[xidx].t1c.b2tc[23] = val;
initial force top.comp.img.tc[xidx].t1c.b2tc[22] = val;
initial force top.comp.img.tc[xidx].t1c.b2tc[21] = val;
initial force top.comp.img.tc[xidx].t1c.b2tc[20] = val;
end
end
endgenerate
error message :
Expecting the keyword 'end' [12.1.3(IEEE 2001)].
An 'endgenerate' is expected [12.1.3(IEEE 2001)].
expecting the keyword 'endmodule' [12.1(IEEE)].
An 'endgenerate' is expected [12.1.3(IEEE 2001)].
Do I make something wrong?
update2
the original concept of mine is the below,
integer ii;
initial begin
for (bb=0; bb<3; bb=bb+1) begin
#10
for (ii=0; ii<19; ii=ii+1) begin
force sydnney.top.vx1.mpg.jpg[ii].trig.be[3] = bb;
...
end
end
but that is not work with
Illegal operand for constant expression [4(IEEE)] error message.
So I'm looking for solution.
The module portion of a hierarchical references must be constant. You cannot loop through the indexes of arrayed module instances or generate-for-loops at simulation time. You can loop through them durring the elaboration phase of compilation with a generate-for-loops.
generate
genvar gidx;
for(gidx=0; gidx<19; gidx=gidx+1) begin : force_be3_loop
initial force sydnney.top.vx1.mpg.jpg[gidx].trig.be[3] = 1'b1;
end
endgenerate
I'm new to verilog and I'm trying to build a verilog code that models a direct mapped cache. Every thing is working fine within the compilation process but the testbench module doesn't seem to execute the "Memory" module (instance). The output variables are always unknowns except for those that I assign values in the testbench itself, even the RAM register which I had filled up with data in the main module. What do you think seems to be the problem?
Thanks in advance
This is the instance module code:
module Memory (outdata,address,indata,RE,WE);
input [31:0]address;
input [31:0]indata;
output reg [31:0]outdata;
input RE,WE;
//Declared the inputs and outputs
reg[31:0]RAM[0:1023];
reg[19:0]tag[0:1023];
reg valid [0:1023];
reg [31:0]Data[0:1023];
//Defined the registers that were supposed to be modules
//Divided the cache into tag,data and valid
//Starting thr Reading Process
always # (RE or WE)
begin
if (RE==1)
begin
if (address[31:12] == tag [address[11:2]])
begin
if (valid[address[11:2]] ==1)
begin
outdata = Data[address[11:2]];
end
else if (valid[address[11:2]] ==0) //Read from RAM
begin
Data[address[11:2]] = RAM [address];
valid[address[11:2]] =1;
outdata = Data[address[11:2]];
end
end
if (address[31:12] != tag [address[11:2]])
begin
Data[address[11:2]] <= RAM [address];
tag[address[11:2]] <= address [31:12];
valid[address[11:2]] =1;
outdata <= Data[address[11:2]];
end
end
//Starting the Writing Process
else if (WE==1)
begin
if(address[31:12]==tag[address[11:2]]) //Hit
begin
Data[address[11:2]]<=indata;
valid[address[11:2]] =1;
RAM[address]<=indata;
end
if (address[31:12] != tag [address[11:2]])//Miss
begin
RAM[address]<=indata;
end
end
end
initial
begin
$readmemb("D:\Verilog Project Data/MyMemory.txt",RAM);
end
endmodule
// Filling up the RAM
This is a module where I write the data I want to fill the RAM with in a file:
module WritingToMemory;
reg[31:0]i;
integer file;
initial
begin
i=0;
file = $fopen("D:\Verilog Project Data/MyMemory.txt");
$fmonitor(file,"%b\n",i);
for(i=0; i<1024; i=i+1)
begin
#1
i=i;
end
end
endmodule
TestBench module:
module TestBench;
reg[31:0]address;
reg[31:0]indata;
reg RE;
reg WE;
wire[31:0]outdata;
initial
begin
$monitor("address= %b, Inputputdata= %b, Outputdata= %b, Data=%b, RAMdata=%b",
address,indata,outdata, Data[address[11:2]],RAM[address]);
#10
RE = 1;
address = 0;
#10
RE=1;
address =0;
#10
RE=1;
address=0;
end
Memory M1(outdata,address,indata,RE,WE);
endmodule
Are you sure you simulated this? It does not compile in the current state.
Next time could you please indent the code you post?
Getting to your question, there are three issues:
1) You initialize only RAM, the Tag and Valid arrays are all x. Your HW would be completely unpredictable in real silicon.
Before a cache can be used, the tags and valid bits must be initialized. Now you know why ;)
2) Your testbench is really generating only one transaction. You wrote:
#10
RE = 1;
address = 0;
#10
RE=1;
address =0;
#10
RE=1;
address=0;
Since neither RE nor address ever change after the first assignment, the always # (RE or WE) statement never gets triggered again.
you need to have RE go back to 0 or address change. Or, which is much more likely in the behaviour of an actual cache, introduce a clock.
3) always # (RE or WE) is also incorrect, because address is not part of the sensitivity list. This would cause the memory to latch the address only when the strobe is activated, which might or not be correct in your implementation. That's another very good reason to introduce a clock
I am just starting Verilog, and with little to no direction. I have been trying to build an 4 bit array that I want to walk through turning on and then off each of my LED's in order. I want them to go from 0-3, 7-4 and start over. I haven't set up my loops yet, however I want to see if I'm at least going in the right direction.
// 4 bit oscillating LED pattern
module count_osc (rstn, osc_clk, clk, LED);
input rstn;
output osc_clk;
output clk;
output [7:0] LED;
reg [22:0]c_delay;
genvar i;
genvar j;
GSR GSR_INST (.GSR(rstn)); // Reset occurs when argument is active low.
OSCC OSCC_1 (.OSC(osc_clk));
generate
for (i=0; i<4; i=i+1) begin : LED_loop
assign LED[i] = (clk);
for (j=4; j<8; j=j+1) begin : LED_loop_2
assign LED[j] = (~clk);
end
end
endgenerate
// The c_delay counter is used to slow down the internal oscillator (OSC) output
// to a rate of approximately 0.5 Hz
always #(posedge osc_clk or negedge rstn)
begin
if (~rstn)
c_delay <= 32'h0000;
else
c_delay <= c_delay + 1;
end
assign clk = c_delay[22];
endmodule
There are few misconceptions about verilog here, which are quite common for programmers coming from more procedural languages.
If your not aware Verilog describes hardware and therefore everything can happen in parallel, we do not procedurally start at the top and work our way through lines of code. Every initial and always blocks are running at the same time.
assign should be used outside of loops and it is a continuos assignment, ie combinatorial logic.
generate is used for parameterising hardware instances, you should not need this on basic examples. NB it also means that the hardware you describe can be quite tricky to understand.
With that in mind you may realise that this block:
generate
for (i=0; i<4; i=i+1) begin : LED_loop
assign LED[i] = (clk);
for (j=4; j<8; j=j+1) begin : LED_loop_2
assign LED[j] = (~clk);
end
end
endgenerate
Does not mean much, the first section is:
assign LED[0] = (clk);
assign LED[1] = (clk);
assign LED[2] = (clk);
assign LED[3] = (clk);
The second for loop is inside the first but only uses the second variable essentially overwriting the same statements 4 times:
assign LED[4] = (~clk);
assign LED[5] = (~clk);
assign LED[6] = (~clk);
assign LED[7] = (~clk);
When suggesting you write out what you want I was implying you write out the above instead of using generates.
Solution
I am not sure of the exact sequence you want from your question as you refer to a 4 bit array but uses 8 elements for the LED.
I think this might be a good place to practice creating a FSM (Finite state machine).
reg [2:0] state;
reg [2:0] nextstate;
always #(posedge clk or negede rst_n) begin
if (~rst_n) begin
state <= 'b0;
end
else begin
state<= nextstate;
end
end
//Next state logic (keeping it simple)
always #* begin
nextstate = state +1;
end
//Output logic
always #* begin
case(state)
3'd0 : LED = 'b0000_0000; //Binary makes sense as we can see the LED pattern
3'd1 : LED = 'b0000_0001;
3'd2 : LED = 'b0000_0011;
3'd3 : LED = 'b0000_0111;
3'd4 : LED = 'b0000_1111;
3'd5 : LED = 'b0000_0111;
3'd6 : LED = 'b0000_0011;
3'd7 : LED = 'b0000_0001;
default : LED = 'b0000_0000; //Default unreachable if we completed the case
endcase
end
I do not think this completes the sequence your trying to do but it should give enough of an understanding to complete the sequence yourself.
I am completely new to verilog and I have to know quite a bit of it fairly soon for a course I am taking in university. So I am play around with my altera DE2 board and quartis2 and learning the ins and outs.
I am trying to make a counter which is turned on and off by a switch.
So far the counter counts and resets based on a key press.
This is my error:
Error (10119): Verilog HDL Loop Statement error at my_first_counter_enable.v(19): loop with non-constant loop condition must terminate within 250 iterations
I understand I am being asked to provide a loop variable, but even doing so I get an error.
This is my code:
module my_first_counter_enable(SW,CLOCK_50,LEDR,KEY);
input CLOCK_50;
input [17:0] SW;
input KEY;
output [17:0] LEDR;
reg [32:0] count;
wire reset_n;
wire enable;
assign reset_n = KEY;
assign enable = SW[0];
assign LEDR = count[27:24];
always# (posedge CLOCK_50 or negedge reset_n) begin
while(enable) begin
if(!reset_n)
count = 0;
else
count = count + 1;
end
end
endmodule
I hope someone can point out my error in my loop and allow me to continue.
Thank you!
I don't think you want to use a while loop there. How about:
always# (posedge CLOCK_50 or negedge reset_n) begin
if(!reset_n)
count <= 0;
else if (enable)
count <= count + 1;
end
I also added non-blocking assignments <=, which are more appropriate for synchronous logic.
The block will trigger every time there is a positive edge of the clock. Where you had a while loop does not mean anything in hardware, it would still need a clock to drive the flip flops.
While loops can be used in testbeches to drive stimulus
integer x;
initial begin
x = 0;
while (x<1000) begin
data_in = 2**x ; //or stimulus read from file etc ...
x=x+1;
end
end
I find for loops or repeat to be of more use though:
integer x;
initial begin
for (x=0; x<1000; x=x+1) begin
data_in = 2**x ; //or stimulus read from file etc ...
end
end
initial begin
repeat(1000) begin
data_in = 'z; //stimulus read from file etc (no loop variable)...
end
end
NB: personally I would also add begin end to every thing to avoid adding extra lines later and wondering why they always or never get executed, especially while new to the language. It also has the added benefit of making the indenting look a little nicer.
always# (posedge CLOCK_50 or negedge reset_n) begin
if(!reset_n) begin
count <= 'b0;
end
else if (enable) begin
count <= count + 1;
end
end
Title
Error (10119): Verilog HDL Loop Statement error at : loop with non-constant loop condition must terminate within iterations
Description
This error may appear in the Quartus® II software when synthesis iterates through a loop in Verilog HDL for more than the synthesis loop limit. This limit prevents synthesis from potentially running into an infinite loop. By default, this loop limit is set to 250 iterations.
Workaround / Fix
To work around this error, the loop limit can be set using the VERILOG_NON_CONSTANT_LOOP_LIMIT option in the Quartus II Settings File (.qsf). For example:
set_global_assignment -name VERILOG_NON_CONSTANT_LOOP_LIMIT 300
I encountered a problem with synthesis where if I had two variables in an if statement, Synthesis will fail (with a very misleading and unhelpful error message).
Given the code snippet below
case(state)
//other states here
GET_PAYLOAD_DATA:
begin
if (packet_size < payload_length) begin
packet_size <= packet_size + 1;
//Code to place byte into ram that only triggers with a toggle flag
next_state = GET_PAYLOAD_DATA;
end else begin
next_state = GET_CHKSUM2;
end
end
I get an error in Xilinx ISE during synthesis:
ERROR:Xst:2001 - Width mismatch detected on comparator next_state_cmp_lt0000/ALB. Operand A and B do not have the same size.
The error claims that next_state isn't correct, but if I take out payload_length and assign a static value to it, it works perfectly fine. As both packet_size and payload_length are of type integer, they are the same size and that is not the problem. Therefore I assume its a similar problem to for loops not being implementable in hardware unless it is a static loop with a defined end. But If statements should work as it is just a comparator between 2 binary values.
What I was trying to do here is that when a byte is received by my module, it will be added into RAM until the the size of the entire payload (which I get from earlier packet data) is reached, then change to a different state to handle the checksum. As the data only comes in 1 byte at a time, I recall this state multiple times until the counter reaches the limit, then I set the next state to something else.
My question is then, how do I achieve the same results of calling my state and repeat until the counter has reached the length of the payload without the error showing up?
EDIT:
Snippets of how packet_size and payload_length are declared, as requested in comments
integer payload_length, packet_size;
initial begin
//other stuff
packet_size <= 0;
end
always # (posedge clk) begin
//case statements with various states
GET_PAYLOAD_LEN:
begin
if (rx_toggle == 1) begin
packet_size <= packet_size + 1;
addr <= 3;
din <= rx_byte_buffer;
payload_length <= rx_byte_buffer;
next_state = GET_PAYLOAD_DATA;
end else begin
next_state = GET_PAYLOAD_LEN;
end
end
rx_byte_buffer is a register of the input data my module receives as 8 bits wide, while packet_size increments in various other states of the machine prior to the one you see above.
I have gotten around the error by switching the if statement conditionals around, but still want to understand why that would change anything.
There are some errors that stick out right away about the code, while they may not fix this problem, they will need to be corrected because it will cause a difference in simulation and hardware tests.
The nextstate logic needs to be in a different always block that does not change based on the posedge of clock. The sensitivity list needs to include things like "state" and/or "*". And if you wanted the nextstate logic to be registered like it is now (which you don't) you should use a nonblocking assignment, this is described in great deal in the cummings paper, provided below.
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf
the code should look something like this:
always # (*) begin
//case statements with various states
GET_PAYLOAD_LEN:
begin
if (rx_toggle == 1) begin
packet_size_en = 1'b1;
//these will need to be changed in a similar manner
addr <= 3;
din <= rx_byte_buffer;
payload_length <= rx_byte_buffer;
/////////////////////////////////////////////////////
next_state = GET_PAYLOAD_DATA;
end else begin
next_state = GET_PAYLOAD_LEN;
end
end
always#(posedge clk) begin
if(pcket_size_en)
packet_size <= packet_size +1 ;
end
Also, the first thing I would try is to make these a defined length, by making them of type reg (I assume that you wont be needing a signed number so it should have no difference on simulation), outside of generate blocks, you should try to not let synthesis play around with integers.