Create a int parameter from a loop variable - verilog

I am trying to get a code similar to this to work:
module testModule #( parameter LEN = 4,
parameter logic [0:0] OPTION = 1'b0 )
(
input Clk,
input [LEN-1:0] DataIn,
input [LEN-1:0] Condition,
output [LEN-1:0] DataOut_1,
output [LEN-1:0] DataOut_2
);
// CODE 1
always_ff #(posedge Clk) begin
for (int i = 0; i < LEN; i++) begin
if (OPTION == 1'b0) begin
if (Condition[0]) begin
DataOut_1[i] <= DataIn[i];
end else begin
DataOut_1[i] <= 1'b0;
end
end else begin
if (Condition[i]) begin
DataOut_1[i] <= DataIn[i];
end else begin
DataOut_1[i] <= 1'b0;
end
end
end
end
// CODE 2
always_ff #(posedge Clk) begin
for (int i = 0; i < LEN; i++) begin
int select = (OPTION == 1'b0) ? 0 : i;
if (Condition[select]) begin
DataOut_2[i] <= DataIn[i];
end else begin
DataOut_2[i] <= 1'b0;
end
end
end
endmodule
OPTION can be either 0 of 1.
I would like CODE 1 and 2 to do the same thing, and I am trying to simplify CODE 1.
DataOut_1 and DataOut_2 return the same value, but I get the following errors in CODE 2 in line
int select = (OPTION == 1'b0) ? 0 : i;
Local static variable with initializer requires 'static' keyword
automatic variable illegal in static variable initializer
And I am not sure if there is a way to do it

This code is illegal because you are not allowed to declare an implicitly static variable select with an initialization expression.
The reason for this restriction is exactly for the mistake you have made thinking that select will get initialized each time through the loop. Variables with static lifetimes only get initialized once at time zero, whereas variables with automatic lifetimes get initialized each time they enter the procedural block they are declared in.
Verilog declarations inside procedural block are implicitly static (exceptions are variables i declared as part of a for loop, and variables declared inside class methods, which are automatic.
There are a number of ways to fix this.
Explictly declare select with an automatic lifetime so that it gets initialized each iteration of the for loop.
Separate the declaration and initialization into a declaration and assignment statements. The assigment statement executes each iteration of the loop
Get rid of the variable and embed it onto the other expressions. That is essentially what code 1 and another answers does.

You can simplify CODE 1 by using a ternary and bitwise operator instead of the for loop:
module testModule #( parameter LEN = 4,
parameter logic [0:0] OPTION = 1'b0 )
(
input Clk,
input [LEN-1:0] DataIn,
input [LEN-1:0] Condition,
output reg [LEN-1:0] DataOut_1
);
always_ff #(posedge Clk) begin
if (OPTION == 1'b0) begin
DataOut_1 <= (Condition[0]) ? DataIn : '0;
end else begin
DataOut_1 <= DataIn & Condition;
end
end
endmodule

Related

How to simplify code using a temporal int variable

I want CODE 1 and CODE 2 to do the same
module testModule #( parameter LEN = 4,
parameter logic [0:0] OPTION = 1'b0 )
(
input Clk,
input [ 7:0][LEN-1:0] DataIn,
input [ 7:0][LEN-1:0] Factor,
output [15:0][LEN-1:0] DataOut_1,
output [15:0][LEN-1:0] DataOut_2
);
// CODE 1
always_ff #(posedge Clk) begin
for (int i = 0; i < LEN; i++) begin
if (OPTION == 1'b0) begin
DataOut_1[i] <= DataIn[i] * Factor[0];
end else begin
DataOut_1[i] <= DataIn[i] * Factor[i];
end
end
end
// CODE 2
always_ff #(posedge Clk) begin
for (int i = 0; i < LEN; i++) begin
int select = (OPTION == 1'b0) ? 0 : i;
DataOut_2[i] <= DataIn[i] * Factor[select];
end
end
endmodule
OPTION can be either 0 of 1.
But I get the following errors in CODE 2 in line
int select = (OPTION == 1'b0) ? 0 : i;
Local static variable with initializer requires 'static' keyword
automatic variable illegal in static variable initializer
I don't want to simplify the for loop because the in my original code I need it
This question is a variant on this other but I didn't want to change the original code question
You have a couple of issues there:
you cannot assign to a net inside an always block. DataOut_1/2 are declared as nets. So, you should declare them as regs at minimum:
output reg [15:0][LEN-1:0] DataOut_1,
output reg [15:0][LEN-1:0] DataOut_2
All variables defined in the module are static by nature. Except in some cases. The i defined in the 'for' loop is automatic. Therefore you cannot use it as an initializer to a static variable. You need to declare 'select' as automatic:
automatic int select = (OPTION == 1'b0) ? 0 : i;

Using a for loop inside a clocked process: "Cannot generate logic"

I would like to generate a number of statements inside a clocked process, seen below:
parameter C_INPUT_LENGTH = 32;
parameter C_OUTPUT_NUM_BITS = 5;
reg [C_OUTPUT_NUM_BITS-1:0] address;
reg [C_INPUT_LENGTH-1:0] vector_i;
always#(posedge clk) begin
if(rst) begin
address <= 0;
end
else begin
if (vector_i[0] == 1) begin
address <= 0;
end
if (vector_i[1] == 1) begin
address <= 1;
end
...
if (vector_i[C_INPUT_LENGTH-1] == 1) begin
address <= C_INPUT_LENGTH-1;
end
end
end // always# (posedge clk)
I did so like this:
integer forcount;
always#(posedge clk) begin
if(rst) begin
address <= 0;
end
else begin
for (forcount = 0;forcount <= C_INPUT_LENGTH-1 ;forcount = forcount + 1) begin
if (vector_i[forcount] == 1) begin <--
address <= forcount;
end
end
end
end // always# (posedge clk)
Xilinx vivado (2014.1) gives the following error, referring to the line indicated above:
[Synth 8-903] failed to generate logic
I've done this before using a similar method in the past and it has worked, what am I doing wrong? How do I generate these if statements?
According to Xilinx, this is a known bug documented under CR 801365. The use of an integer as a loop counter causes this issue in some cases. It's due to be fixed in vivado 2014.3.
The solution is to replace the integer with a signal type reg of appropriate size.
Is your input vector_i one-hot? The code you wrote doesn't guarantee that address will only be written to one value. Try this:
for (forcount = 0;forcount <= C_INPUT_LENGTH-1 ;forcount = forcount + 1) begin
if (vector_i[forcount] == 1) begin
address <= forcount;
break;
end
end
Adding the break statement will break out of the for loop the first time the condition is true. Note that this will generate some carry-chain logic and you might get better results with a case statement.
As a temporary work-around, you could consider using a generate statement.
For example:
genvar i;
always #(posedge clk) begin
if (rst) begin
address <= 0;
end else begin
generate
for (i = 0; i < C_INPUT_LENGTH; i = i + 1) begin: foreach_input
if (vector_i[i]) address <= i;
end
endgenerate
end // if (rst)
end // always #(posedge clk)
edit: oh, never mind -- I missed the bit above where Xilinx's recommended workaround is to simply use a dimensioned variable rather than "integer" for the iterator. That would be easier!

cannot use an input for if statement in Verilog

I am trying to pass an integer value to a module, but the IF statement does not work with the parameter. It throws the following error. I am new to Verilog so I have no idea how to make this work.
Error (10200): Verilog HDL Conditional Statement error at clock_divider.v(17):
cannot match operand(s) in the condition to the corresponding edges in the enclosing
event control of the always construct
clock_divider.v module
module clock_divider (clockHandler, clk, rst_n, clk_o);
parameter DIV_CONST = 10000000 ; // 1 second
parameter DIV_CONST_faster = 10000000 / 5;
input clockHandler;
input clk;
input rst_n;
output reg clk_o;
reg [31:0] div;
reg en;
integer div_helper = 0;
always # (posedge clk or negedge rst_n)
begin
if(clockHandler == 0)
begin div_helper = DIV_CONST;
end
else
begin div_helper = DIV_CONST_faster;
end
if (!rst_n)
begin div <= 0;
en <= 0;
end
else
begin
if (div == div_helper)
begin div <= 0;
en <= 1;
end
else
begin div <= div + 1;
en <= 0;
end
end
end
always # (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
clk_o <= 1'b0;
end
else if (en)
clk_o <= ~clk_o;
end
endmodule
main.v module
reg clockHandler = 1;
// 7-seg display mux
always # (*)
begin
case (SW[2:0])
3'b000: hexdata <= 16'h0188;
3'b001: hexdata <= register_A ;
3'b010: hexdata <= program_counter ;
3'b011: hexdata <= instruction_register ;
3'b100: hexdata <= memory_data_register_out ;
3'b111: hexdata <= out;
default: hexdata <= 16'h0188;
endcase
if(SW[8] == 1)
begin
clockHandler = 1;
end
else
begin
clockHandler = 0;
end
end
HexDigit d0(HEX0,hexdata[3:0]);
HexDigit d1(HEX1,hexdata[7:4]);
HexDigit d2(HEX2,hexdata[11:8]);
HexDigit d3(HEX3,hexdata[15:12]);
clock_divider clk1Hzfrom50MHz (
clockHandler,
CLOCK_50,
KEY[3],
clk_1Hz
);
It's my understanding that the first statement in a verilog always block must be the if(reset) term if you're using an asynchronous reset.
So the flop construct should always look like this:
always # (posedge clk or negedge rst_n) begin
if(~rst_n) begin
...reset statements...
end else begin
...all other statements...
end
end
So for your case you should move the if(clockHandler==0) block inside the else statement, because it is not relevant to the reset execution. Even better would be to move it into a separate combinational always block, since mixing blocking and nonblocking statements inside an always block is generally not a good idea unless you really know what you're doing. I think it is fine in your case though.
To add to Tim's answer - the original code (around line 17, anyway) is valid Verilog.
What it's saying is "whenever there's a rising edge on clk or a falling edge on rst_n, check clockHandler and do something" (by the way, get rid of the begin/ends; they're redundant and verbose). The problem comes when you want to implement this in real hardware, so the error message is presumably from a synthesiser, which needs more than valid Verilog. The synth suspects that it has to build a synchronous element of some sort, but it can't (or won't, to be precise) handle the case where clockHandler is examined on an edge of both clk and rst_n. Follow the rules for synthesis templates, and you won't get this problem.
is this a compilation error or synthesis error? i used the same code to see if it compiles fine, and i din get errors.. Also, it is recommended to use "<=" inside synchronous blocks rather than "="
You're using the same flop construct for two different things. Linearly in code this causes a slipping of states. I always place everything within one construct if the states rely on that clock or that reset, otherwise you require extra steps to make sure more than one signal isn't trying to change your state.
You also don't need the begin/end when it comes to the flop construct, Verilog knows how to handle that for you. I believe Verilog is okay with it though, but I generally don't do that. You also don't have to use it when using a single statement within a block.
So your first module would look like this (if I missed a block somewhere just let me know):
clock_divider.v module (edited)
module clock_divider (clockHandler, clk, rst_n, clk_o);
parameter DIV_CONST = 10000000 ; // 1 second
parameter DIV_CONST_faster = 10000000 / 5;
input clockHandler;
input clk;
input rst_n;
output reg clk_o;
reg [31:0] div;
reg en;
integer div_helper = 0;
always # (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
div <= 0;
en <= 0;
clk_o <= 1'b0;
end
else if(en)
begin
clk_o <= ~ clk_o;
if(clockHandler == 0)
begin
div_helper = DIV_CONST;
end
else
begin
div_helper = DIV_CONST_faster;
end
else
begin
if (div == div_helper)
begin
div <= 0;
en <= 1;
end
end
else
begin
div <= div + 1;
en <= 0;
end
end
end
end module
If that clk_o isn't meant to be handled at the same time those other operations take place, then you can separate everything else with a general 'else' statement. Just be sure to nest that second construct as an if-statement to check your state.
And also remember to add always # (posedge clk or negedge rst_n) to your main.v module as Tim mentioned.

Timing issue in Verilog

I am new to verilog and I am working on verilg code that defines two modules.
The first module calculates the mod of 2 numbers and the second uses the result to do some operation on it.
The result was wrong and has alot of don't care values because the same clk was used in both modules. Any suggestion please for synchronisation.
The mod module
module mod(m,a,b);
input [15:0] a,b;
output [15:0] m;
reg [31:0] mod;
reg [31:0] mul;
integer i;
always #* begin
mul = a*b;
mod = 32'h80008000;
for(i=0;i<16;i=i+1) begin
if(mul > mod) begin
mul = mul - mod;
mod = mod >> 1;
end
else begin
mod = mod >> 1;
end
end
assign m=mul[15:0];
endmodule
Part of the top module:
initial begin
keyp <= 2'b10;
shift <= 1'b0;
end
always #(posedge clk) begin
if(load)
case (keyp)
2'b10: begin
key[127:64] <= {k1,k0};
keyp <= 2'b01;
end
2'b01: begin
key[63:0] <= {k1,k0};
keyp <= 2'b00;
shift <= 1'b1;
end
//default: keyp <=2'b00;
endcase
else if (shift) begin
//shift key for first round
temp[24:0] <= key[127:103];
key[127:25] <= key[102:0];
key [24:0] <= temp [24:0];
shift <= 1'b0;
end
end
assign w1[2*SIZE-1:SIZE] = d1+key[2*SIZE-1:SIZE];
assign w1[3*SIZE-1:2*SIZE] = d2+key[3*SIZE-1:2*SIZE];
mod mod1( w1[SIZE-1:0], d0, key[SIZE-1:0] );
mod mod2( w1[4*SIZE-1:3*SIZE], d3, key[4*SIZE-1:3*SIZE]);
Assigning to the same value multiple times with blocking assignments is perfectly valid Verilog. Even having the same term appear on both sides is fine, provided it's been assigned at least once prior to that.
The code here is incomplete but the problem appears to be that the code is assigning to 'key' in multiple places. Both as the output of the mod instances and inside the clocked block. Anytime these two 'disagree' about the value of key it's going to been seen as an X. X in addition to representing unknown also reflects contention where two different assignments conflict.
Since I'm not sure what this code is meant to do (seems to be some sort of encryption) I can't offer a fix but you need to separate the assignments to key.
x's are referred to as do not cares in casex statements or Karnaugh maps, here they represent unknown values. Unknown values can come from a value not being initialised (reset) or multiple (conflicting) drivers.
The mod module contains this section of code:
always #* begin
mul = a*b;
mod = 32'h80008000;
for(i=0;i<16;i=i+1) begin
if(mul > mod) begin
mul = mul - mod;
mod = mod >> 1;
end
else begin
mod = mod >> 1;
end
end
always #* is a combinatorial block, you assign mul multiple times only the last assignment will have any effect.
The use of a for loop here makes it look like you are trying to reuse variables, as you would in c. Remember that we are describing hardware and that the value is intended to exist somewhere as flip flops or wires between modules and can only hold a single value in any given clock cycle.
In the combinatorial block you have mul = mul - mod; that is mul defining itself this will not work, you need to add a flip flop to break the loop.

Verilog generate/genvar in an always block

I'm trying to get a module to pass the syntax check in ISE 12.4, and it gives me an error I don't understand. First a code snippet:
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
generate
always #(posedge sysclk) begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0;
end
end
endgenerate
When I try a syntax check, I get the following error message:
ERROR:HDLCompiler:731 - "test.v" Line 46: Procedural assignment to a
non-register <c> is not permitted.
I really don't understand why it's complaining. "c" isn't a wire, it's a genvar. This should be the equivalent of the completely legal syntax:
reg [3:0] temp;
always #(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
Please, no comments about how it'd be easier to write this without the generate. This is a reduced example of a much more complex piece of code involving multiple ifs and non-blocking assignments to "temp". Also, don't just tell me there are newer versions of ISE, I already know that. OTOH, if you know it's fixed in a later version of ISE, please let me know which version you know works.
You need to reverse the nesting inside the generate block:
genvar c;
generate
for (c = 0; c < ROWBITS; c = c + 1) begin: test
always #(posedge sysclk) begin
temp[c] <= 1'b0;
end
end
endgenerate
Technically, this generates four always blocks:
always #(posedge sysclk) temp[0] <= 1'b0;
always #(posedge sysclk) temp[1] <= 1'b0;
always #(posedge sysclk) temp[2] <= 1'b0;
always #(posedge sysclk) temp[3] <= 1'b0;
In this simple example, there's no difference in behavior between the four always blocks and a single always block containing four assignments, but in other cases there could be.
The genvar-dependent operation needs to be resolved when constructing the in-memory representation of the design (in the case of a simulator) or when mapping to logic gates (in the case of a synthesis tool). The always #posedge doesn't have meaning until the design is operating.
Subject to certain restrictions, you can put a for loop inside the always block, even for synthesizable code. For synthesis, the loop will be unrolled. However, in that case, the for loop needs to work with a reg, integer, or similar. It can't use a genvar, because having the for loop inside the always block describes an operation that occurs at each edge of the clock, not an operation that can be expanded statically during elaboration of the design.
You don't need a generate bock if you want all the bits of temp assigned in the same always block.
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always #(posedge sysclk) begin
for (integer c=0; c<ROWBITS; c=c+1) begin: test
temp[c] <= 1'b0;
end
end
Alternatively, if your simulator supports IEEE 1800 (SytemVerilog), then
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always #(posedge sysclk) begin
temp <= '0; // fill with 0
end
end
If you do not mind having to compile/generate the file then you could use a pre processing technique. This gives you the power of the generate but results in a clean Verilog file which is often easier to debug and leads to less simulator issues.
I use RubyIt to generate verilog files from templates using ERB (Embedded Ruby).
parameter ROWBITS = <%= ROWBITS %> ;
always #(posedge sysclk) begin
<% (0...ROWBITS).each do |addr| -%>
temp[<%= addr %>] <= 1'b0;
<% end -%>
end
Generating the module_name.v file with :
$ ruby_it --parameter ROWBITS=4 --outpath ./ --file ./module_name.rv
The generated module_name.v
parameter ROWBITS = 4 ;
always #(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
Within a module, Verilog contains essentially two constructs: items and statements. Statements are always found in procedural contexts, which include anything in between begin..end, functions, tasks, always blocks and initial blocks. Items, such as generate constructs, are listed directly in the module. For loops and most variable/constant declarations can exist in both contexts.
In your code, it appears that you want the for loop to be evaluated as a generate item but the loop is actually part of the procedural context of the always block. For a for loop to be treated as a generate loop it must be in the module context. The generate..endgenerate keywords are entirely optional(some tools require them) and have no effect. See this answer for an example of how generate loops are evaluated.
//Compiler sees this
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
always #(posedge sysclk) //Procedural context starts here
begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0; //Still a genvar
end
end
for verilog just do
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always #(posedge sysclk) begin
temp <= {ROWBITS{1'b0}}; // fill with 0
end
To put it simply, you don't use generate inside an always process, you use generate to create a parametrized process or instantiate particular modules, where you can combine if-else or case. So you can move this generate and crea a particular process or an instantiation e.g.,
module #(
parameter XLEN = 64,
parameter USEIP = 0
)
(
input clk,
input rstn,
input [XLEN-1:0] opA,
input [XLEN-1:0] opB,
input [XLEN-1:0] opR,
input en
);
generate
case(USEIP)
0:begin
always #(posedge clk or negedge rstn)
begin
if(!rstn)
begin
opR <= '{default:0};
end
else
begin
if(en)
opR <= opA+opB;
else
opR <= '{default:0};
end
end
end
1:begin
superAdder #(.XLEN(XLEN)) _adder(.clk(clk),.rstm(rstn), .opA(opA), .opB(opB), .opR(opR), .en(en));
end
endcase
endmodule

Resources