Using assign inside a for loop - verilog

I'm trying to assign I/O vectors inside a for loop in order to save space. I am unsure if this is not possible or I am running into a syntax issue.
I have tried using generate and am still running into issues
My current code is as follows:
module Test_IO
(
output [7:0] led,
input [7:0] sw
);
genvar i;
generate
for(i = 0;i < 8; i = i + 1)
{
assign led<i> = sw<i>;
}
endgenerate
endmodule
I was hoping to save space instead of having to use 8 assign statements but I have been receiving the following error:
ERROR:HDLCompiler:806 -
"C:/Users/Danie/Desktop/Digilent/Projects/Test_IO/Test_IO.v" Line 31:
Syntax error near "{".

I am assuming you are using verilog. Try the below code. You really don't need a genvar for the assignment you are doing.
module Test_IO
(
output [7:0] led,
input [7:0] sw
);
genvar i;
generate
for(i = 0;i < 8; i = i + 1)
assign led[i] = sw[i];
endgenerate
endmodule
Alternatively you may try the below one too
module Test_IO
(
output reg [7:0] led,
input [7:0] sw
);
integer i;
always#(*)
begin
for(i=0;i<8;i=i+1)
led[i] = sw[i];
end
endmodule

Your problem is syntax. In verilog use begin and end, not { and }
genvar i;
generate
for(i = 0;i < 8; i = i + 1)
{
assign led<i> = sw<i>;
}
endgenerate
becomes
genvar i;
generate
for(i = 0;i < 8; i = i + 1) begin
assign led[i] = sw[i];
end
endgenerate
sometimes compilers requires the generate loop to be named using : NAME after begin
genvar i;
generate
for(i = 0;i < 8; i = i + 1) begin : ASSIGN_GEN
assign led[i] = sw[i];
end
endgenerate

Related

Does SystemVerilog Generate support delays?

I thought of generating clock using genvar like below:
reg [7:0]clk;
genvar i;
generate
for (i=0; i < 7; i++) begin
#1 clk[i]=~clk[i];
end
endgenerate
I am getting an error:
error: near "#": syntax error, unexpected '#'
How can we resolve it? Can I use delays inside generate block?
I feel it isn't necessary to have a generate, you can use the for loop directly in an always block:
reg [7:0] clk;
integer i;
always begin
#1;
for(i = 0; i < 7; i = i + 1)
clk[i] = ~clk[i];
end
Nevertheless, if all the bits are toggled at the same time, you can simplify it with:
always
#1 clk = ~clk; //..bitwise invert the array
Yes, generate blocks support delays. To fix your problem, use a procedural always block:
reg [7:0] clk;
genvar i;
generate
for (i=0; i < 7; i++) begin
always #1 clk[i]=~clk[i];
end
endgenerate
It looks like OP wanted to have a sequential delay model. In this case the code should look like this:
always begin
for(i = 0; i < 7; i = i + 1)
#1 clk[i] = ~clk[i];
end

Multiplication of 2 matrix in verilog

I've written a code for matrx multiplication in Verilog.
module multiply3x3(i1,i2,i3,i4,i5,i6,i7,i8,i9,j1,j2,j3,j4,j5,j6,j7,j8,j9,prod);
output reg [31:0]prod;
wire [7:0]resultant[3:0][3:0];
wire [7:0]a[3:0][3:0];
wire [7:0]b[3:0][3:0];
genvar i,j,k;
generate
for (i = 0; i <= 2; i=i+1) begin:i_
for (j = 0; j <= 2; j=j+1) begin:j_
assign resultant[i][j] = 8'd0;
for (k = 0; k <= 2; k=k+1) begin:k_
assign resultant[i][j] = resultant[i][j] + a[i][k] * b[k][j];
end
end
end
endgenerate
endmodule
initial begin
#100 prod = {resultant[0][0],resultant[0][1],resultant[0][2],resultant[1][0],resultant[1][1],resultant[1][2],resultant[2][0],resultant[2][1],resultant[2][2]};
end
This is where the multiplication happens, but i cannot get the output for this.
What am I doing wrong?
consider a,b declared properly.
Accumulation (a = a + p) doesn't work with wires. The type wire is supposed to model a physical wire.
You'll have to declare the variable resultant as a reg. The reg type, in Verilog, can in some cases be treated like a variable in other programming languages.
Also, you can't use the assign statement on a wire or reg multiple times (like you've done in line 78 and 80 of https://pastebin.com/txrcwUBd). You should use always (and not generate) blocks to perform such things.
Corrected Verilog:
reg [7:0] resultant[3:0][3:0];
int i, j, k;
always #(*)
for(i=0; i<3; i=i+1)
for(j=0; j<3; j=j+1) begin
resultant[i][j] = 8'd0;
for(k=0; k<3; k=k+1)
resultant[i][j] = resultant[i][j] + (a[i][k]*b[k][j]);
end

How to assign variable pins to a port in verilog?

I have a 32-bit input port pins and a 32-bit input enable pin_en, and want to generate a 16-bit output selected by the enables. I wrote verilog like this, but seems there are some errors.
How can I fix it or any other way to achive? Thanks!
ps: No more than 16 pins selected by en, but maybe less.
input [31:0] pins;
input [31:0] pin_en;
output [15:0] actual_pins;
generate
genvar i;
localparam cnt = 0;
for(i = 0; (i < 'd32) & (cnt < 'd16); i = i + 'd1) begin : b1
if(pin_en[i]) begin
assign actual_pins[i] = pins[cnt];
cnt = cnt + 'd1;
end
end
if(cnt < 16)
assign actual_pins[16 : cnt] = 'b0;
endgenerate
I think that there are several errors in you code:
in generate blocks you cannot do any generation, based on the actual values of variables. The blocks are for the constant expressions only which could be resolved at compilation time, not at the run time. Also, you cannot modify anything in the generated blocks besides genvars. Paremeters (localparams) cannot be modified, so the cnt = cnt + 1 is just illegal there.
you messed up actual_pins and pins. by logic there should be actual_pins[cnt];
you use binary & operator, but you should have used logical && instead.
So, all your code should have been implemented in a run-time constructs, i.e., always blocks. You also need a trigger which will cause the always block to be evaluated. I created a small example where the always block is to be triggered by a clock.
module top (
input clk,
input [31:0] pins,
input [31:0] pin_en,
output reg [15:0] actual_pins
);
always #(posedge clk) begin
int cnt = 0;
int i;
for(i = 0; (i < 'd32) && (cnt < 'd16); i = i + 'd1) begin
if(pin_en[i]) begin
actual_pins[cnt] = pins[i];
cnt = cnt + 'd1;
end
end
for(; cnt < 16; cnt = cnt + 1)
actual_pins[j] = 1'b0;
end
endmodule

Priority encoder in verilog

I am somewhat new to verilog, I tried running this code but it gives me an error:
module enc(in,out);
input [7:0] in;
output [3:0] out;
reg i;
reg [3:0] out;
always #*
begin
for (i=0;i<7;i=i+1)
begin
if ((in[i]==1) && (in[7:i+1]==0))
out = i;
else
out = 0;
end
end
endmodule
I think it complains about in[7:i+1] but i don't understand why ?
Can someone please advise..
EDIT
ok so I am reluctant to using the X due to their numerous problems.. I was thinking of modifying the code to something like this :
module enc(in,out);
input [7:0] in;
output [2:0] out;
reg i;
reg [2:0] out,temp;
always #*
begin
temp = 0;
for (i=0;i<8;i=i+1)
begin
if (in[i]==1)
temp = i;
end
out = temp;
end
endmodule
Do you think that will do the trick ? I currently don't have access to a simulator..
A priority encoder mean giving priority to a one bit if two or more bits meet the criteria. Looking at your code, it appears you wanted to give priority to a LSB while using a up counter. out is assigned in every look, so even if your could compile, the final result would be 6 or 0.
For an LSB priority encoder, first start with a default value for out and use a down counter:
module enc (
input wire [7:0] in,
output reg [2:0] out
);
integer i;
always #* begin
out = 0; // default value if 'in' is all 0's
for (i=7; i>=0; i=i-1)
if (in[i]) out = i;
end
endmodule
If you are only interested in simulation than your linear loop approach should be fine, something like
out = 0;
for (i = W - 1; i > 0; i = i - 1) begin
if (in[i] && !out)
out = i;
end
If you also care about performance, the question becomes more interesting. I once experimented with different approaches to writing parameterized priority encoders here. It turned out that Synopsys can generate efficient implementation even from the brain-dead loop above but other toolchains needed explicit generate magic. Here is an excerpt from the link:
output [WIDTH_LOG - 1:0] msb;
wire [WIDTH_LOG*WIDTH - 1:0] ors;
assign ors[WIDTH_LOG*WIDTH - 1:(WIDTH_LOG - 1)*WIDTH] = x;
genvar w, i;
integer j;
generate
for (w = WIDTH_LOG - 1; w >= 0; w = w - 1) begin
assign msb[w] = |ors[w*WIDTH + 2*(1 << w) - 1:w*WIDTH + (1 << w)];
if (w > 0) begin
assign ors[(w - 1)*WIDTH + (1 << w) - 1:(w - 1)*WIDTH] = msb[w] ? ors[w*WIDTH + 2*(1 << w) - 1:w*WIDTH + (1 << w)] : ors[w*WIDTH + (1 << w) - 1:w*WIDTH];
end
end
endgenerate
So my Edited solution worked... how silly !! I forgot to declare reg [2:0] i; and instead wrote reg i;
Thanks everybody
Hunks, I have to tell you, all your solutions are either too complex or non-synthesizable, or implement into slow multiplexors. Alexej Bolshakov at OpenCores uploaded an outstandin' parametrizable encoder on Aug 23, 2015, based on OR elements. No muxes, 100% synthesizable. His code (with my tiny formatting):
module encoder #(
parameter LINES = 16,
parameter WIDTH = $clog2(LINES)
)(
input [LINES-1:0] unitary_in,
output wor [WIDTH-1:0] binary_out
);
genvar i, j;
generate
for (i = 0; i < LINES; i = i + 1)
begin: loop_i
for (j = 0; j < WIDTH; j = j + 1)
begin: loop_j
if (i[j])
assign binary_out[j] = unitary_in[i];
end
end
endgenerate
endmodule
RTL viewer screenshot, Model-Sim screenshot
This solution divides the input into four blocks and checks for the first nonzero block. This block is further subdivided in the same way. It is reasonably efficient.
// find position of most significant 1 bit in 64 bits input
// (system verilog)
module bitscan(
input logic [63:0] in, // number input
output logic [5:0] out, // bit position output
output logic zeroout // indicates if input is zero
);
logic [63:0] m0; // intermediates
logic [15:0] m1;
logic [3:0] m2;
logic [5:0] r;
always_comb begin
m0 = in;
// choose between four 16-bit blocks
if (|m0[63:48]) begin
m1 = m0[63:48];
r[5:4] = 3;
end else if (|m0[47:32]) begin
m1 = m0[47:32];
r[5:4] = 2;
end else if (|m0[31:16]) begin
m1 = m0[31:16];
r[5:4] = 1;
end else begin
m1 = m0[15:0];
r[5:4] = 0;
end
// choose between four 4-bit blocks
if (|m1[15:12]) begin
m2 = m1[15:12];
r[3:2] = 3;
end else if (|m0[11:8]) begin
m2 = m1[11:8];
r[3:2] = 2;
end else if (|m0[7:4]) begin
m2 = m1[7:4];
r[3:2] = 1;
end else begin
m2 = m1[3:0];
r[3:2] = 0;
end
// choose between four remaining bits
if (m2[3]) r[1:0] = 3;
else if (m2[2]) r[1:0] = 2;
else if (m2[1]) r[1:0] = 1;
else r[1:0] = 0;
out = r;
zeroout = ~|m2;
end
endmodule
Here is another solution that uses slightly less resourcess:
module bitscan4 (
input logic [63:0] in,
output logic [5:0] out,
output logic zout
);
logic [63:0] m0;
logic [3:0] m1;
logic [3:0] m2;
logic [5:0] r;
always_comb begin
r = 0;
m0 = in;
if (|m0[63:48]) begin
r[5:4] = 3;
m1[3] = |m0[63:60];
m1[2] = |m0[59:56];
m1[1] = |m0[55:53];
m1[0] = |m0[51:48];
end else if (|m0[47:32]) begin
r[5:4] = 2;
m1[3] = |m0[47:44];
m1[2] = |m0[43:40];
m1[1] = |m0[39:36];
m1[0] = |m0[35:32];
end else if (|m0[31:16]) begin
r[5:4] = 1;
m1[3] = |m0[31:28];
m1[2] = |m0[27:24];
m1[1] = |m0[23:20];
m1[0] = |m0[19:16];
end else begin
r[5:4] = 0;
m1[3] = |m0[15:12];
m1[2] = |m0[11:8];
m1[1] = |m0[7:4];
m1[0] = |m0[3:0];
end
if (m1[3]) begin
r[3:2] = 3;
end else if (m1[2]) begin
r[3:2] = 2;
end else if (m1[1]) begin
r[3:2] = 1;
end else begin
r[3:2] = 0;
end
m2 = m0[{r[5:2],2'b0}+: 4];
if (m2[3]) r[1:0] = 3;
else if (m2[2]) r[1:0] = 2;
else if (m2[1]) r[1:0] = 1;
else r[1:0] = 0;
zout = ~|m2;
out = r;
end
endmodule
To be able to use variable indexes in part-slice suffixes, you must enclose the for block into a generate block, like this:
gen var i;
generate
for (i=0;i<7;i=i+1) begin :gen_slices
always #* begin
... do whatever with in[7:i+1]
end
end
The problem is that apllying this to your module, the way it's written, leads to other errors. Your rewritten module would look like this (be warned: this won't work either)
module enc (
input wire [7:0] in,
output reg [2:0] out // I believe you wanted this to be 3 bits width, not 4.
);
genvar i; //a generate block needs a genvar
generate
for (i=0;i<7;i=i+1) begin :gen_block
always #* begin
if (in[i]==1'b1 && in[7:i+1]=='b0) // now this IS allowed :)
out = i;
else
out = 3'b0;
end
end
endgenerate
endmodule
This will throw a synthesis error about out being driven from more than one source. This means that the value assigned to out comes from several sources at the same time, and that is not allowed.
This is because the for block unrolls to something like this:
always #* begin
if (in[0]==1'b1 && in[7:1]=='b0)
out = 0;
else
out = 3'b0;
end
always #* begin
if (in[1]==1'b1 && in[7:2]=='b0)
out = 1;
else
out = 3'b0;
end
always #* begin
if (in[2]==1'b1 && in[7:3]=='b0)
out = 2;
else
out = 3'b0;
end
.... and so on...
So now you have multiple combinational block (always #*) trying to set a value to out. All of them will work at the same time, and all of them will try to put a specific value to out whether the if block evaluates as true or false. Recall that the condition of each if statement is mutually exclusive with respect of the other if conditions (i.e. only one if must evaluate to true).
So a quick and dirty way to avoid this multisource situation (I'm sure there are more elegant ways to solve this) is to let out to be high impedance if the if block is not going to assign it a value. Something like this:
module enc (
input wire [7:0] in,
output reg [2:0] out // I believe you wanted this to be 3 bits width, not 4.
);
genvar i; //a generate block needs a genvar
generate
for (i=0;i<7;i=i+1) begin :gen_block
always #* begin
if (in[i]==1'b1 && in[7:i+1]=='b0) // now this IS allowed :)
out = i;
else
out = 3'bZZZ;
end
end
endgenerate
always #* begin
if (in[7]) // you missed the case in which in[7] is high
out = 3'd7;
else
out = 3'bZZZ;
end
endmodule
On the other way, if you just need a priority encoder and your design uses fixed and small widths for inputs and outputs, you may write your encoder as this:
module enc (
input wire [7:0] in,
output reg [2:0] out
);
always #* begin
casex (in)
8'b1xxxxxxx : out = 3'd7;
8'b01xxxxxx : out = 3'd6;
8'b001xxxxx : out = 3'd5;
8'b0001xxxx : out = 3'd4;
8'b00001xxx : out = 3'd3;
8'b000001xx : out = 3'd2;
8'b0000001x : out = 3'd1;
8'b00000001 : out = 3'd0;
default : out = 3'd0;
endcase
end
endmodule
(although there seems to be reasons to not to use casex in a design. Read the comment #Tim posted about it in this other question: How can I assign a "don't care" value to an output in a combinational module in Verilog )
In conclusion: I'm afraid that I have not a bullet-proof design for your requirements (if we take into account the contents of the paper Tim linked in his comment), but at least, you know now why i was unallowed inside a part-slice suffix.
On the other way, you can have half of the work done by studying this code I gave as an answer to another SO question. In this case, the module works like a priority encoder, parametrized and without casex statements, only the output is not binary, but one-hot encoded.
How to parameterize a case statement with don't cares?
out = in&(~(in-1))
gives you the one-hot results(FROM LSB->MSB where the first 1 at)

In synthesizable verilog, can we use assign statement in generate block?

For example, I have the below piece of code. Can we assign wire inside the generate block in synthesizable verilog? Can we use assign statement inside the generate block in synthesizable verilog?
genvar i;
generate
for (i = 0; i < W; i=i+1) begin:m
wire [2:0] L;
assign L[1:0] = { a[i], b[i] };
end
endgenerate
Yes. It is possible. A generate statement is just a code generator directive to the synthesizer. Basically, it is just loop unrolling. This is if the loop can be statically elaborated. That is, the number of times the loop is to executed should be determinable at compile time.
genvar i;
generate
for (i = 0; i < 2 ; i++) {
assign x[i] = i;}
endgenerate
unrolls into
assign x[0] = 0;
assign x[1] = 1;
In synthesizeable Verilog, it is possible to use an assign statement inside of a generate block. All a generate block does is mimic multiple instants. Be careful though, because just like a for loop, it could be very big space-wise.
You can use assign in generate statment, it is quite common to help parameterise the hook up modules
The original code has some issues: L is defined multiple times and it is only assigned 2 out of 3 bits
genvar i;
generate
for (i = 0; i < W; i=i+1) begin:m
wire [2:0] L;
assign L[1:0] = { a[i], b[i] };
end
endgenerate
Could be changed to:
localparam W = 4;
reg [W-1:0] a;
reg [W-1:0] b;
wire [1:0] L [0:W-1];
genvar i;
generate
for (i = 0; i < W; i=i+1) begin:m
assign L[i] = { a[i], b[i] };
end
endgenerate
Here L[i] selects the i'th wire [1:0] part of L. While a[i] and b[i] are bit selects.

Resources