Verilog: Passing parameters - verilog

I have written two verilog modules. The first one is named topmodule.v and the second one is tx.v. The module topmodule.v pass a parameter data[31:0] to tx.v. I want to take the variables Rmax and Cmax from data[31:0]. After that I want to make Rmax and Cmax to be the width of a bus. Moreover, I want to define a reg matrix called Mat with dimensions Cmax-x-Rmax. I receive the error at the 6th line of the code, "Range must be bounded by constant expression". Kindly help me to resolve this problem. The code is given below.
tx (data, output)
input [31:0] data;
reg [15:0] Rmax, Cmax;
assign Rmax [15:0] = data [31:16];
assign Cmax [15:0] = data [15:0];
reg [Rmax-1:0] Matrix [0:Cmax-1];

The error means pretty much what it says, you cannot have a variable size bus or array.
Declare your matrix to be the maximum size that you ever need, and if you want to use a smaller one, then just use a subsection of it while leaving the rest vacant.
Remember that the width of buses are physical objects, they can't change when the circuit is running, only during synthesis.

If you really want these to be parameters then use that:
module tx #(parameter DATA=32'h00000000) (
// inputs and outputs here
);
reg [DATA[31:16]-1:0] Matrix [0:DATA[15:0]-1];
However, I'm not really sure of what you are trying to accomplish. Show some more pseudo code and get a more useful answer.

Related

Why is wire variable causing illegal left-hand side in continuous assignment?

I have read through all similar posts, but none address the issue I'm having, namely that line 41 assign Y[b]=~Y[b]; causes error "Illegal left-hand side in continuous assignment."
I haven't assigned any regs so I don't see what the issue is. If I replace b with an actual number (say, 3) it works fine. But I need b as a variable here.
// Hamming code 1-bit error correction
module HCG(I,e,O);
input [4:1] I; // input BCD
input [7:1] e; // noise simulation
wire [7:1] X; // Hamming code
wire [7:1] Y; // Hamming code after addition of noise
wire [3:1] P; // Parity at start
wire [3:1] S; // Parity at end
wire b; // the error bit
output [4:1] O; // corrected output
assign X[1]=I[1]^I[2]^I[4]; // Hamming code generator
assign X[2]=I[1]^I[3]^I[4];
assign X[3]=I[1];
assign X[4]=I[2]^I[3]^I[4];
assign X[5]=I[2];
assign X[6]=I[3];
assign X[7]=I[4];
assign P[1]=X[1]; // Parity at start
assign P[2]=X[2];
assign P[3]=X[4];
assign Y[1]=e[1]^X[1]; // noise added
assign Y[2]=e[2]^X[2];
assign Y[3]=e[3]^X[3];
assign Y[4]=e[4]^X[4];
assign Y[5]=e[5]^X[5];
assign Y[6]=e[6]^X[6];
assign Y[7]=e[7]^X[7];
assign S[1]=Y[3]^Y[5]^Y[7]; // Parity at end
assign S[2]=Y[3]^Y[6]^Y[7];
assign S[3]=Y[5]^Y[6]^Y[7];
assign b=(S[1]!=P[1])? b:b+1; // if parity of 2^0 not the same, add 1 to b
assign b=(S[2]!=P[2])? b:b+2; // if parity of 2^1 not the same, add 2 to b
assign b=(S[3]!=P[3])? b:b+4; // if parity of 2^2 not the same, add 4 to b
assign Y[b]=~Y[b]; // correct the incorrect bit
assign O[1]=Y[3]; // assigning outputs
assign O[2]=Y[5];
assign O[3]=Y[6];
assign O[4]=Y[7];
endmodule
The lines between module and endmodule are executed concurently. (It seems like you think they are executed sequentially.) Therefore, you are driving all the bits of Y in these lines
assign Y[1]=e[1]^X[1]; // noise added
assign Y[2]=e[2]^X[2];
assign Y[3]=e[3]^X[3];
assign Y[4]=e[4]^X[4];
assign Y[5]=e[5]^X[5];
assign Y[6]=e[6]^X[6];
assign Y[7]=e[7]^X[7];
and then are driving one of the bits of Y again in this line:
assign Y[b]=~Y[b]; // correct the incorrect bit
So (a) you have a short circuit and (b) which bit has the short circuit? That depends on b. So, the position of the short circuit depends on the state of one of the internal wires. You have described a circuit that can reconfigure itself depending on its inputs. Verilog won't let you do that. Verilog is a hardware description language. Conventional digital hardware can't reconfigure itself depending on the state of its inputs.
The problem is the continuous assignment you are doing. To quote from the IEEE Std 1800-2012. (Section 10.3) on continuous assignments:
Continuous assignments shall drive values onto nets or variables, both vector (packed) and scalar. This assignment shall occur whenever the value of the right-hand side changes. Continuous assignments provide a way to model combinational logic without specifying an interconnection of gates.
When you do assign Y[b]=~Y[b], the assignment itself automatically causes the right-hand side to change again, which triggers the assignment again.
Verilog standard lists legal lhs values for the continuous assignment as the following (Table 10-1):
Net or variable (vector or scalar)
Constant bit-select of a vector net or packed variable
Constant part-select of a vector net or packed variable
Concatenation or nested concatenation of any of the above left-hand sides
in your case Y[b] is not a constant selection, because b is not a constant. Therefore syntactically your lhs is illegal and you get this message from the compiler.
On a side note you have a zero-delay loop here. See other answers for explanation.

Giving a matrix as an input to a verilog module

I am working with the implementation of a Product Code on FPGA . The product code is basically a matrix with the rows and columns being codewords coming from a BCH codebase (BCH(1023,993,3)) . I already have a BCH decoder in Verilog . I want to have a 1023 by 1023 matrix as an input to my Product code decoder and then call upon that module to decode the rows and columns of the product code matrix . The way the decoding process works at a higher level is that , if there are more than 3 errors in a codeword , the BCH decoder module fixes those errors and moves to the next row/ column .
The questions I have are as follows :
1) Is it possible to make the input port as a matrix ?
2) If I need to pipeline the decoding process, do I need to instantiate the BCH decoder 1023 times or is there a better way to do it ?
3) If it is not possible to make the input port as a matrix , do I need to give all the 1023 rows as 1-D vectors like input row1[1022:0] or is there a better way to do that ?
4) If the technique mentioned in step 3 is the only one available, how do I make the column vectors out of those row vectors available as the inputs ?
Thanks in advance. I really appreciate your time and effort .
One can not pass a two dimensional array as a port in Verilog. SystemVerilog supports 2D array as ports of modules.
Here, you need to take a vector and do some pack/unpack operations. One can define macros for the same.
Here is a sample code where PACK_ARRAY macro packs two dimensional array into a single vector. Packing is done based on the width and length provided as input. Similarly, UNPACK_ARRAY unpacks a vector into a two dimensional array.
`define PACK_ARRAY(PK_WIDTH,PK_LEN,PK_SRC,PK_DEST) \
genvar pk_idx; \
generate \
for (pk_idx=0; pk_idx<(PK_LEN); pk_idx=pk_idx+1) \
begin \
assign PK_DEST[((PK_WIDTH)*pk_idx+((PK_WIDTH)-1)):((PK_WIDTH)*pk_idx)] = PK_SRC[pk_idx][((PK_WIDTH)-1):0]; \
end \
endgenerate
`define UNPACK_ARRAY(PK_WIDTH,PK_LEN,PK_DEST,PK_SRC) \
genvar unpk_idx; \
generate \
for (unpk_idx=0; unpk_idx<(PK_LEN); unpk_idx=unpk_idx+1) begin \
assign PK_DEST[unpk_idx][((PK_WIDTH)-1):0] = PK_SRC[((PK_WIDTH)*unpk_idx+(PK_WIDTH-1)):((PK_WIDTH)*unpk_idx)]; \
end \
endgenerate
module example (
input [(63):0] pack_4_16_in,
output [(31):0] pack_16_2_out
);
wire [3:0] in [0:15];
`UNPACK_ARRAY(4,16,in,pack_4_16_in)
wire [15:0] out [0:1];
`PACK_ARRAY(16,2,in,pack_16_2_out)
// useful code goes here
endmodule // example
As suggested in comments, I believe that you should think of some other approach rather than directly providing 1023*1023 wires as input and output to a single module. As an alternative, you can provide the 1023*1023 matrix elements row wise and store them into internal memory of module.
module example(
input [1023:0] inp, // One can take 'load', 'addr' etc as inputs also
input clk, rst,
output [1023:0] out
);
reg [1023:0] mem [0:1023];
reg [9:0] cnt;
always #(posedge clk) begin
mem[cnt] <= inp;
cnt <= cnt + 1;
end
// Some other logic
endmodule
Here, it will take 1K clocks to load the memory and some glue logic might be required. But this approach will implement a memory inside the module and you will not have hard coded million wires coming as ports.
Refer to this forum discussion for the above code.

Comparing two numbers without comparison operators in verilog

Two 8-bit inputs are fed to the comparator, and if first one is greater than second, they are supposed to be subtracted, else they are supposed to be added. But, > and < operators aren't supposed to be used to compare them.
So, I have written my logic as:
input[7:0] in1,in2;
output select;
assign select=(in1-in2)?0:1;
It is always subtracting, unless difference equals 0. If I use division, 0 cannot be an input or my program can crash. Any suggestions on how to solve this problem?
Thanks a lot for your time.
Remember that the leftmost bit of a negative number is aways 1. So you can use it to check the sign of the difference.
input[7:0] in1,in2;
output select;
wire [7:0] difference = in1-in2;
wire sign_of_difference = difference[7];
assign select = sign_of_difference? 0:1;

How do you manipulate input arrays in an always block (verilog)?

I'm very new to verilog and i'm just starting to understand how it works.
I want to manipulate an input to a module mant[22:0], in an always block but I am not sure how to go about it.
module normalize(mant,exp,mant_norm,exp_norm);
input [22:0]mant;
input [7:0]exp;
output [22:0]mant_norm;
output [7:0]exp_norm;
reg mantreg[22:0];
reg count=0;
always#(mant or exp)
begin
mantreg<=mant; //this gives an error
if(mant[22]==0)
begin
mant<={mant[21:0],1'b0};//this also gives an error
count<=count+1;
end
end
endmodule
so i have to shift the mant register if the bit22 is zero and count the number of shifts. I am so confused about when to use reg and when to use wire and how to do the manipulation. please help let me know how to go about it.
As you can see in your code you are assigning vector value (mant) to array of 23(mantreg). Instead you should declare mantreg as reg [22:0] mantreg (which is vector of 23 bit).
Wire type variable can not be assigned procedurally. They are used only in continues assignment. Other way around reg varible can only be procedural assigned.
For that try to read out LRM of Verilog .

Designing a 3-bit counter using T-flipflop

module tff(t,i,qbprev,q,qb);
input t,i,qbprev;
output q,qb;
wire q,qb,w1;
begin
assign w1=qbprev;
if(w1==1)begin
not n1(i,i);
end
assign q=i;
not n2(qb,i);
end
endmodule
module counter(a,b,c,cin,x0,x1,x2);
input a,b,c,cin;
output x0,x1,x2;
reg a,b,c,x0,x1,x2,temp,q,qb;
always#(posedge cin)
begin
tff t1(.t(1) ,.i(a),.qbprev(1),.q(),.qb());
x0=q;
temp=qb;
tff t2(.t(1) ,.i(b),.qbprev(temp),.q(),.qb());
x1=q;
temp=qb;
tff t3(.t(1) ,.i(c),.qbprev(temp),.q(),.qb());
x2=q;
a=x0;
b=x1;
c=x2;
end
endmodule
This is my code in verilog. My inputs are - the initial state - a,b,c and cin
I get many errors with the first of them being "w1 is not a constant" What doesn this mean?
I also get error "Non-net port a cannot be of mode input" But I want a to be an input!
Thank you.
Modules are instantiated as pieces of hardware. They are not software calls, and you can not create and destroy hardware on the fly therefore:
if(w1==1)begin
not n1(i,i);
end
With that in mind I hope that you can see that unless w1 is a constant parameter, and this is a 'generate if' What your describing does not make sense.
instance n1 is not called or created as required, it must always exist.
Also you have the input and output connected to i. i represent a physical wire it can not be i and not i. these need to be different names to represent different physical wires.
In your second module you have :
input a,b,c,cin;
// ...
reg a,b,c; //...
Inputs can not be regs as the warning says, just do not declare them as regs for this.
input a,b,c,cin;
output x0,x1,x2;
reg x0,x1,x2,temp,q,qb;

Resources