localparam / parameter with unpack array : icarus - verilog

I am trying to initilize unpack parameter.
module dut #(parameter int arr[3])
(
input logic clk
);
endmodule
module main;
int t[3];
initial begin
t[0] = 0;
t[1] = 1;
t[2] = 2;
end
localparam int arr1[3] = t; //'{1,2,3};
localparam int A0 = 1;
localparam int A1 = 1;
localparam int A2 = 1;
localparam int [3] arr = '{A0, A1, A2};
logic clk;
dut
# (.arr (arr))
dut_inst1
(.clk(clk));
dut
# (.arr (arr1))
dut_inst1
(.clk(clk));
endmodule
Icarus does not like any unpack initilization I tried.
I would have used pack initilization but then I have problem using it when generating based on it.

Icarus is not a system verilog compiler. it implements some features but not all of them. The following example is a legal system verilog, but not an icarus one.
It looks like icarus 0.10 (from eda playground) does not understand parameter arrays and assignment patterns. So, most likely there is no good way to do it without using separate parameter per array element. I do not have newer versions though. Talk to icarus community.
As for correct system verilog syntax, in the following example I fixes your t by using the previously commented aggregate assignment and fixes your declaration of parameters in dut and localparam in main. It is compilable with a commercial simulators but not with icarus.
module dut #(parameter int arr[3] = '{0,0,0})
(
input logic clk
);
endmodule
module main;
/*
int t[3];
initial begin
t[0] = 0;
t[1] = 1;
t[2] = 2;
end
*/
localparam int arr1[3] = '{1,2,3};
localparam int A0 = 1;
localparam int A1 = 1;
localparam int A2 = 1;
localparam int arr [3] = '{A0, A1, A2};
logic clk;
dut
# (.arr (arr))
dut_inst1
(.clk(clk));
dut
# (.arr (arr1))
dut_inst2
(.clk(clk));
endmodule

Related

Systemverilog recursion update value for next stage

I am trying to create a recursive logic in Systemverilog but I seem to be missing the right logic to carry the output of one iteration to the next.
Here is an example of the problem:
parameter WIDTH=4;
module test_ckt #(parameter WIDTH = 4)(CK, K, Z);
input CK;
input [WIDTH-1:0] K;
output reg Z;
wire [WIDTH/2-1:0] tt;
wire [WIDTH-1:0] tempin;
assign tempin = K;
genvar i,j;
generate
for (j=$clog2(WIDTH); j>0; j=j-1)
begin: outer
wire [(2**(j-1))-1:0] tt;
for (i=(2**j)-1; i>0; i=i-2)
begin
glitchy_ckt #(.WIDTH(1)) gckt (tempin[i:i], tempin[(i-1):i-1], tt[((i+1)/2)-1]);
end
// How do I save the value for the next iteration?
wire [(2**(j-1))-1:0] tempin;
assign outer[j].tempin = outer[j].tt;
end
endgenerate
always #(posedge CK)
begin
// How do I use the final output here?
Z <= tt[0];
end
endmodule
module glitchy_ckt #(parameter WIDTH = 1)(A1, B1, Z1);
input [WIDTH-1:0] A1,B1;
output Z1;
assign Z1 = ~A1[0] ^ B1[0];
endmodule
Expected topology:
S1 S2
K3--<inv>--|==
|XOR]---<inv>----|
K2---------|== |
|==
<--gckt---> |XOR]
|==
K1--<inv>--|== |
|XOR]------------|
K0---------|== <-----gckt---->
Example input and expected outputs:
Expected output:
A - 1010
----
S1 0 0 <- j=2 and i=3,1.
S2 1 <- j=1 and i=1.
Actual output:
A - 1010
----
S1 0 0 <- j=2 and i=3,1.
S2 0 <- j=1 and i=1. Here, because tempin is not updated, inputs are same as (j=2 & i=1).
Test-bench:
`timescale 1 ps / 1 ps
`include "test_ckt.v"
module mytb;
reg CK;
reg [WIDTH-1:0] A;
wire Z;
test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));
always #200 CK = ~CK;
integer i;
initial begin
$display($time, "Starting simulation");
#0 CK = 0;
A = 4'b1010;
#500 $finish;
end
initial begin
//dump waveform
$dumpfile("test_ckt.vcd");
$dumpvars(0,dut);
end
endmodule
How do I make sure that tempin and tt get updated as I go from one stage to the next.
Your code does not have any recursion in it. You were trying to solve it using loops, but generate blocks are very limited constructs and, for example, you cannot access parameters defined in other generate iterations (but you can access variables or module instances).
So, the idea is to use a real recursive instantiation of the module. In the following implementation the module rec is the one which is instantiated recursively. It actually builds the hierarchy from your example (I hope correctly).
Since you tagged it as system verilog, I used the system verilog syntax.
module rec#(WIDTH=1) (input logic [WIDTH-1:0]source, output logic result);
if (WIDTH <= 2) begin
always_comb
result = source; // << generating the result and exiting recursion.
end
else begin:blk
localparam REC_WDT = WIDTH / 2;
logic [REC_WDT-1:0] newSource;
always_comb // << calculation of your expression
for (int i = 0; i < REC_WDT; i++)
newSource[i] = source[i*2] ^ ~source[(i*2)+1];
rec #(REC_WDT) rec(newSource, result); // << recursive instantiation with WIDTH/2
end // else: !if(WIDTH <= 2)
initial $display("%m: W=%0d", WIDTH); // just my testing leftover
endmodule
The module is instantiated first time from the test_ckt:
module test_ckt #(parameter WIDTH = 4)(input logic CK, input logic [WIDTH-1:0] K, output logic Z);
logic result;
rec#(WIDTH) rec(K, result); // instantiate first time )(top)
always_ff #(posedge CK)
Z <= result; // assign the results
endmodule // test_ckt
And your testbench, a bit changed:
module mytb;
reg CK;
reg [WIDTH-1:0] A;
wire Z;
test_ckt #(.WIDTH(WIDTH)) dut(.CK(CK), .K(A), .Z(Z));
always #200 CK = ~CK;
integer i;
initial begin
$display($time, "Starting simulation");
CK = 0;
A = 4'b1010;
#500
A = 4'b1000;
#500 $finish;
end
initial begin
$monitor("Z=%b", Z);
end
endmodule // mytb
Use of $display/$monitor is more convenient than dumping traces for such small examples.
I did not do much testing of what I created, so there could be issues, but you can get basic ideas from it in any case. I assume it should work with any WIDTH which is power of 2.

Selecting a set of parameters based on input value in Verilog

I am working on a Module which changes it's constant values based on the input to calculate it's output.
Let me illustrate what I am looking for,
Let x be the input, y the output and a,b,c,d,e the set of constants.
Module performs something like the following operation:
y=(a*x)+(b*x)+(c*x)+(d*x)+(e*x); //separate adder and multiplier modules are used and this code itself is huge so just providing the idea.
Now I have used following method to choose the right value for the constants depending on the input: (Pseudo code)
module top (x,clk,y);
input clk;
input [31:0] x;
output [31:0] y;
if (x>=32'h08000000 && x<32'h0A000000) begin
localparam a = 32'h058B90C0;
localparam b = 32'h193C9F60;
localparam c = 32'h29AC1740;
localparam d = 32'hA48B9440;
localparam e = 32'h0B6392E0;
end else if (x>=32'h0A000000 && x<32'h0C000000) begin
localparam a = 32'h028A50C1;
localparam b = 32'hE98B489C;
localparam c = 32'h17402948;
localparam d = 32'h9440E45B;
localparam e = 32'h392E00AF;
end
y=(a*x)+(b*x)+(c*x)+(d*x)+(e*x); // Module that computes using any of the above mentioned constant sets
endmodule
I get the following errors:
(1) "Unable to bind parameter".
(2) "Cannot evaluate genvar conditional expression: ((x)G(32'000010000....00))&& so on......"
My question is:
My user will give the input through x, right constants will be chosen, my module will calculate and provide the output. Just providing the right constants to the module is enough. How shall I do it? Ideas through pseudo code will be helpful for me.
I had to look up where localparam is allowed. You can define a localparam after a begin : < label >.
I tried it and found that (at least in Vivado) it passed and worked.
always #( a )
if (a>=1)
begin : a_be_1
localparam P1 = 3;
c = P1;
end
else
begin : a_sm_1
localparam P1 = 5;
c = P1;
end

Bit slicing in verilog

How can I write wdata[((8*j)+7) : (8*i)] = $random; in verilog programming language? , where i and j are reg type variable. Modelsim gives error for constant range variable. How could I write it in proper manner.
You should think from Hardware prospective for the solution.
Here is one solution. Hope that it will help you.
module temp(clk);
input clk;
reg i, j;
reg [23:0] register, select;
wire [23:0] temp;
initial
begin
i = 'd1;
j = 'd1;
end
generate
for(genvar i = 0; i<24; i++)
begin
assign temp[i] = select[i] ? $random : register[i];
end
endgenerate
always # (posedge clk)
begin
register <= temp;
end
always # *
begin
select = (32'hffff_ffff << ((j<<3)+8)) ^ (32'hffff_ffff << (i<<3));
end
endmodule
Use the array slicing construction. You can find more detailed explanation at Array slicing Q&A
bit [7:0] PA, PB;
int loc;
initial begin
loc = 3;
PA = PB; // Read/Write
PA[7:4] = 'hA; // Read/Write of a slice
PA[loc -:4] = PA[loc+1 +:4]; // Read/Write of a variable slice equivalent to PA[3:0] = PA[7:4];
end
Verilog 2001 Syntax
[M -: N] // negative offset from bit index M, N bit result
[M +: N] // positive offset from bit index M, N bit result

system verilog slicing arrays

I am still not sure how the array slicing works in System Verilog?
For example, let's say that I have a packed 2D array.
localparam [0:2][4:0] TEMP = {5'd4,5'd9,5'd20};
So my array has three rows and each row is a 5-bit number.
So, when I am trying to do something like this, it doesn't quite work !!!
logic [1:0] arr;
assign arr = TEMP[0][1:0]
How come this doesn't work?
The compiler doesn't complain, but the simulation shows all 'X !!
Here I am including the module that has the issue:
module slice_issue ();
// clock and reset
reg board_resetl;
reg tb_clkh;
parameter CLK_PER = 4;
always #(CLK_PER/2) tb_clkh = ~ tb_clkh;
initial begin: main_process
board_resetl = 0;
tb_clkh = 0;
#100
#(posedge tb_clkh);
board_resetl = 1;
end
localparam logic [4:0] PARAM_1 = 14;
localparam logic [4:0] PARAM_2 = 18;
localparam logic [4:0] PARAM_3 = 26;
localparam [0:2] [4:0] CAND_MODE_LIST = {PARAM_1, PARAM_2, PARAM_3};
logic [1:0] temp;
logic [4:0] temp2;
logic [1:0] in_pred_mode;
logic [4:0] cnt_reg;
always # (posedge tb_clkh or negedge board_resetl)
begin
if (~board_resetl) begin
in_pred_mode <= 0;
cnt_reg <= 0;
end else
cnt_reg <= cnt_reg + 1;
if (cnt_reg == 31) begin
in_pred_mode <= $urandom_range(0, 1);
end
end
// bad
assign temp = CAND_MODE_LIST[in_pred_mode][1:0];
// good
assign temp2 = CAND_MODE_LIST[in_pred_mode];
endmodule
A self contained example could be :
module tb;
localparam [0:2][4:0] TEMP = {5'd4,5'd9,5'd20};
logic [1:0] arr;
assign arr = TEMP[0][1:0];
initial begin
$display("arr : %b", arr);
#1ps;
$display(TEMP[0]);
$display(TEMP[1]);
$display(TEMP[2]);
$display("arr : %b", arr);
end
endmodule
For me this (correctly) outputs:
# KERNEL: arr : 00
# KERNEL: 4
# KERNEL: 9
# KERNEL: 20
# KERNEL: arr : 00
This does not show the error condition from the question, unless the question adds more information, the exact reason for the error can not be determined.
example on EDA Playground
instead of negative points, I should've gotten a positive one. I contacted the vendor (Aldec), and it turned out it is Aldec's simulator issue, and they are going to fixed it in their next revision.

How to design a 64 x 64 bit array multiplier in Verilog?

I know how to design a 4x4 array multiplier , but if I follow the same logic , the coding becomes tedious.
4 x 4 - 16 partial products
64 x 64 - 4096 partial products.
Along with 8 full adders and 4 half adders, How many full adders and half adders do I need for 64 x 64 bit. How do I reduce the number of Partial products? Is there any simple way to solve this ?
Whenever tediously coding a repetitive pattern you should use a generate statement instead:
module array_multiplier(a, b, y);
parameter width = 8;
input [width-1:0] a, b;
output [width-1:0] y;
wire [width*width-1:0] partials;
genvar i;
assign partials[width-1 : 0] = a[0] ? b : 0;
generate for (i = 1; i < width; i = i+1) begin:gen
assign partials[width*(i+1)-1 : width*i] = (a[i] ? b << i : 0) +
partials[width*i-1 : width*(i-1)];
end endgenerate
assign y = partials[width*width-1 : width*(width-1)];
endmodule
I've verified this module using the following test-bench:
http://svn.clifford.at/handicraft/2013/array_multiplier/array_multiplier_tb.v
EDIT:
As #Debian has asked for a pipelined version - here it is. This time using a for loop in an always-region for the array part.
module array_multiplier_pipeline(clk, a, b, y);
parameter width = 8;
input clk;
input [width-1:0] a, b;
output [width-1:0] y;
reg [width-1:0] a_pipeline [0:width-2];
reg [width-1:0] b_pipeline [0:width-2];
reg [width-1:0] partials [0:width-1];
integer i;
always #(posedge clk) begin
a_pipeline[0] <= a;
b_pipeline[0] <= b;
for (i = 1; i < width-1; i = i+1) begin
a_pipeline[i] <= a_pipeline[i-1];
b_pipeline[i] <= b_pipeline[i-1];
end
partials[0] <= a[0] ? b : 0;
for (i = 1; i < width; i = i+1)
partials[i] <= (a_pipeline[i-1][i] ? b_pipeline[i-1] << i : 0) +
partials[i-1];
end
assign y = partials[width-1];
endmodule
Note that with many synthesis tools it's also possible to just add (width) register stages after the non-pipelined adder and let the tools register balancing pass do the pipelining.
[how to] reduce the number of partial products?
A method somewhat common used to be modified Booth encoding:
At the cost of more complicated addend selection, it at least almost halves their number.
In its simplest form, considering groups of three adjacent bits (overlapping by one) from one of the operands, say, b, and selecting 0, a, 2a, -2a or -a as an addend.
The code below generates only half of expected the output.
module arr_multi(a, b, y);
parameter w = 8;
input [w-1:0] a, b; // w-width
output [(2*w)-1:0] y; // p-partials
wire [(2*w*w)-1:0] p; //assign width as input bits multiplied by
output bits
genvar i;
assign p[(2*w)-1 : 0] = a[0] ? b : 0; //first output size bits
generate
for (i = 1; i < w; i = i+1)
begin
assign p[(w*(4+(2*(i-1))))-1 : (w*2)*i] = (a[i]?b<<i :0) + p[(w*(4+(2*
(i-2))))-1 :(w*2)*(i-1)];
end
endgenerate
assign y=p[(2*w*w)-1:(2*w)*(w-1)]; //taking last output size bits
endmodule

Resources