I've following tasks with different input vectors (that part is not written for simplicity) in my Verilog testbench
task input_set_1;
begin
end
endtask
task input_set_2;
begin
end
endtask
task input_set_3;
begin
end
endtask
task input_set_4;
begin
end
endtask
I'm trying to call only one of them during the testbench simulation using the below task
task input_calling;
integer i;
begin
i = $urandom_range(1, 4);
input_set_i;
end
endtask
initial begin
#3;
input_calling;
end
I'm expecting with each test run, any of the input_set_1, or input_set_2 or input_set_3 or input_set_4 will be called based on the random number i=1 to 4, however, I'm getting an error saying input_set_i is not defined. I suspect some string to int mismatch is preventing I to take randomized value in the input _set_i task.
You are trying to do something which is impossible in verilog (as well as in any non-scripting language). Name of the task is a compile-time element which must be known to the compiler at compilation time. i is a run-time, dynamic element. You cannot use run-time objects to modify compile-time objects.
So, your best bet is to use dynamic language features to make your program work, e.g. if statements. Here is an example:
module top;
task a;
$display("a");
endtask
task b;
$display("b");
endtask
initial begin
for (int k = 0; k < 4; k++) begin
automatic int i = $urandom_range(2,1);
if (i == 1)
a;
else if (i == 2)
b;
end
end
endmodule
Related
I have following code snippet where a temp variable is used to count number of 1s in an array:
// count the number 1s in array
logic [5:0] count_v; //temp
always_comb begin
count_v = arr[0];
if (valid) begin
for (int i=1; i<=31; i++) begin
count_v = arr[i] + count_v;
end
end
final_count = count_v;
end
Will this logic create a latch for count_v ? Is synthesis tool smart enough to properly synthesize this logic? I am struggling to find any coding recommendation for these kind of scenarios.
Another example:
logic temp; // temp variable
always_comb begin
temp = 0;
for (int i=0; i<32; i++) begin
if (i>=start) begin
out_data[temp*8 +: 8] = in_data[i*8 +: 8];
temp = temp + 1'b1;
end
end
end
For any always block with deterministic initial assignment, it will not generate latch except logic loop.
Sorry Eddy Yau, we seem to have some discussions going on regarding your post.
Here is some example code:
module latch_or_not (
input cond,
input [3:0] v_in,
output reg latch,
output reg [2:0] comb1,
output reg [2:0] comb2
);
reg [2:0] temp;
reg [2:0] comb_loop;
// Make a latch
always #( * )
if (cond)
latch = v_in[0];
always #( * )
begin : aw1
integer i;
for (i=0; i<4; i=i+1)
comb_loop = comb_loop + v_in[i];
comb2 = comb_loop;
end
always #( * )
begin : aw2
integer i;
temp = 7;
for (i=0; i<4; i=i+1)
temp = temp - v_in[i];
comb1 = temp;
end
endmodule
This is what came out if it according to the Xilinx Vivado tool after elaboration:
The 'latch' output is obvious. You will also notice that temp is not present in the end result.
The 'comb_loop' is not a latch but even worse: it is a combinatorial loop. The output of the logic goes back to the input. A definitely NO-NO!
General rule: if you read a variable before writing to it, then your code implies memory of some sort. In this case, both the simulator and synthesiser have to implement storage of a previous value, so a synthesiser will give you a register or latch. Both your examples write to the temporary before reading it, so no storage is implied.
Does it synthesisie? Try it and see. I've seen lots of this sort of thing in production code, and it works (with the synths I've used), but I don't do it myself. I would try it, see what logic is created, and use that to decide whether you need to think more about it. Counting set bits is easy without a loop, but the count loop will almost certainly work with your synth. The second example may be more problematical.
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
Writing verilog code from quite a few days and one question I have is 'Can we write generate block inside generate block'? I am writing an RTL something like this:
Where 'n' is a parameter.
reg [DATA_WIDTH:0] flops [n-1:0];
generate
if (n > 0) begin
always #(posedge clk) begin
if (en) begin
flops[0] <= mem[addr];
end
end
generate
genvar i;
for (i = 1; i <= n ; i = i + 1) begin
always #(posedge clk) begin
flops[i] <= flops[i-1];
end
end
endgenerate
always #(flops[n - 1])
douta = flops[n - 1];
else
always #(posedge clk) begin
if (en) begin
primary_output = mem[addr];
end
end
end
endgenerate
While compiling the above code, I am getting :
ERROR: syntax error near generate (VERI-1137)
Not sure why. Purpose of this RTL is to create an pipeline of 'n' flops at the output side of the design.
Lets say n is 2, then circuit should become :
flop1-> flop2-> primary output of design
flop1 and flop2 are newly created flops.
You are a long long way from where you should be.
Verilog is not a programming language; it is a hardware description language. You model hardware as a network of concurrent processes. Each process models a small bit of hardware such as a counter, a state machine, a shift-register, some combinational logic... In Verilog, each process is coded as an always block. So, one always statement never ever can appear inside another; that makes no sense.
Secondly, generate is quite a specialised statement. You use it when you want either a large number or a variable number of concurrent processes. That is not a common thing to need, so generate is not common, but is useful when required. You don't need a generate statement to implement a parameterisable shift-register. And, because an always block is a concurrent statement it sits inside a generate statement, not the other way round.
I don't know what your design intent is exactly, to I suspect this code does not do exactly what you want. However, it does implement a parameterisable shift-register of length n and width DATA_WIDTH+1 (did you really mean that?), enabled by the en input:
module N_FLOPS #(n = 2, DATA_WIDTH = 8) (input [DATA_WIDTH:0] dina, input clk, en, output [DATA_WIDTH:0] douta);
reg [DATA_WIDTH:0] flops [n-1:0];
always #(posedge clk)
if (en)
begin : SR
integer i;
flops[0] <= dina;
for (i = 1; i <= n ; i = i + 1)
flops[i] <= flops[i-1];
end
assign douta = flops[n-1];
endmodule
http://www.edaplayground.com/x/3kuY
You can see - no generate statements required. This code conforms to this template, which suffices for any sequential logic without an asynchronous reset:
always #(posedge CLOCK) // or negedge
begin
// do things that occur on the rising (or falling) edge of CLOCK
// stuff here gets synthesised to combinational logic on the D input
// of the resulting flip-flops
end
When I try to synthesize my verilog project i get the following errors:
ERROR:Xst:2634 - "shiftman.v" line 15: For loop stop condition should depend on loop variable or be static.
ERROR:Xst:2634 - "shiftman.v" line 22: For loop stop condition should depend on loop variable or be static.
I think I understand what causes the error, but I can't find a way to fix it.
module shiftman(in,sh,out);
input[47:0] in;
input[8:0] sh;
output[47:0] out;
reg[47:0] out;
reg[7:0] r;
reg i;
always#(in or sh)
begin
r=sh[7:0];
out=in;
if(sh[8]==0)
for(i=0; i<r; i=i+1)
begin
out[23:0]={1'b0,out[23:1]};
end
else
for(i=0; i<r; i=i+1)
begin
out[47:24]={1'b0,out[47:25]};
end
end
endmodule
The reason your synthesis is failing is because you cannot uses variable-iteration loops in synthesizable code. When synthesizing, the tool will attempt to unroll the loop, but it cannot do this if the termination condition for the loop is not static or determinable at synthesis. Your condition i <= r is such a condition as we cannot unroll the loop without knowing r, which is an input to the module and thus, not static.
In order to fix this, youll need to rewrite your code in a way that the synthesis tool can process. By the looks of it, you are simply logically shifting either the top or bottom of in by sh[7:0] depending on sh[8]. In order to do this, you don't need looping at all, but can use the >> (logical right shift operator). So, your always block would look more like this:
always #(*) begin
out = in;
if (sh[8])
out[47:24] = in[47:24] >> sh[7:0];
else
out[23:0] = in[23:0] >> sh[7:0];
end
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.