Multiple always block using for loop - verilog

Is it posible to generate multiple always statements using a for loop in Verilog
By example. Let's say we want to create a 4bit Ripple/Asynchronous Counter.
We can do this like this
always #(posedge MainClock)
begin
Q[0] = ~Q[0];
end
always #(posedge Q[0])
begin
Q[1] = ~Q[1];
end
always #(posedge Q[1])
begin
Q[2] = ~Q[2];
end
always #(posedge Q[2])
begin
Q[3] = ~Q[3];
end
Is it posible to do something like this instead:
always #(posedge MainClock)
begin
Q[0] = ~Q[0];
end
for (i = 1; i <= 3; i = i+1)
begin
always #(posedge Q[i-1])
begin
Q[i] = ~Q[i];
end
end
I know for a fact that the first methods works, because I tested it. The second method doesn't work, I did test it. Is there a different way to do that?

You can use generate to do that:
genvar i;
generate
for (i = 1; i <= 3; i = i+1) begin : ripple
always #(posedge Q[i-1])
Q[i] = ~Q[i];
end
endgenerate

Related

Verilog - Nested generate for loop with multiple genvars, not possible?

I'm trying to add a second level of nesting to my generate loop in the following code, but iverilog is throwing an error that the register j is unknown:
../crc.v:119: register ``j'' unknown in crc_tb.U_crc.loop[31].
So is it possible to use multiple genvars in verilog? It looks like j is being interpreted as a register.
Code snippet:
genvar i;
genvar j;
reg [DATA_WIDTH-1:0] temp;
generate
for(i = 0; i < CRC_WIDTH; i= i + 1)
begin : loop
always #(posedge clock or posedge reset)
begin
if (reset)
begin
crc_out[i+:1] = SEED[i+:1];
end
else if (init)
begin
crc_out[i+:1] = SEED[i+:1];
end
else if (data_enable)
begin
if (DEBUG)
$display("\n\nCRC OUT[%0d]\n***************************************************************************", i);
if (REVERSE)
begin
for (j = DATA_WIDTH-1; j >= 0; j = j - 1)
begin : reverse_loop
temp[DATA_WIDTH-1-j] = data[i][j];
end
crc_out[i+:1] <= prev(DATA_WIDTH-1,i,temp,crc_out);
end
else
begin
crc_out[i+:1] <= prev(DATA_WIDTH-1,i,data,crc_out);
end
end
end
end
endgenerate
You can nest multiple generate loops, but your inner generate loop is inside a procedural block of code - that is illegal. Perhapsj should just be a local variable instead of a genvar.

Verilog Event control statements

I currently have this code(below) for a debouncer for a button on an fpga, however I am getting an error that says "Multiple event control statements in one always/initial process block are not supported in this case." whenever I try to synthesize the desgin. The line that causes the problem is the #(posedge clk) but I'm wondering how exactly to replace this logic. What I essentially require is always # (quarter & posedge clk)as the sensitivity list for the first always block but this does not work either. I am fairly new to the language so I'm still working out a few syntax kinks.Snippet of Code is below:
always #(quarter)
begin
#(posedge clk)
begin
if (quarter != new) begin new <= quarter; count <= 0; end
else if (count == DELAY) cleanq <= new;
else count <= count+1;
end
end
instead of always
#(posedge event1)
#(posedge event2)
create aflag (1bit reg) event2done : reg event2done; initial event2done=0;
always#(posedge event1)
begin if (!event2done & event 2)
// event2done=1; + type ur code
else if(event2done & !event 2)
event2done =0; end
pseudo code:
always#(something1)
#(something2)
do something
Look in the comments to see explanation as to why this isn't synthesizable
always #(posedge clk)
/* over here you'll have to set the default values
for everything that's being changed in this always block,
you'll otherwise generate latches. Which is likely
not what you want */
begin
if (quarter != new) begin new <= quarter; count <= 0; end
else if (count == DELAY) cleanq <= new;
else count <= count+1;
end
I don't have access to my verilog rig at the moment so I can't confirm the syntax correctness

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.

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