Turning matrix to array in verilog 2005 - verilog

I know that in Verilog a matrix can not be passed to the ports, so i am wondering how could i turn matrix into array.
Consider the code:
input [7:0] matrix1 [0:3][0:3];
The code is valid in systemverilog, but not in Verilog 2005 standard.
Anyone got any ideas how to do this? I need it to be synthesizable.

You got choices.
Break it up into a smaller ports:
module top();
// ...
example dut(
.matrix1_0_0(matrix1[0][0]),
.matrix1_0_1(matrix1[0][1]),
// ...
.matrix1_3_2(matrix1[3][2]),
.matrix1_3_3(matrix1[3][3]),
// ... other ports ...
);
// ...
endmodule
module example(
input [7:0] matrix1_0_0,
input [7:0] matrix1_0_1,
// ...
input [7:0] matrix1_3_2,
input [7:0] matrix1_3_3,
// ... other ports ...
);
wire [7:0] matrix1 [0:3][0:3];
assign matrix1[0][0] = matrix1_0_0;
// ...
assign matrix1[3][3] = matrix1_3_3;
// ... other logic
endmodule
Merge into a single bus then split it back to a matrix using +: or -: (see part-select addressing):
module top();
// ...
integer i,j;
reg [8*4*4-1:0] matrix1_bus;
always #* begin
for(i = 0; i<4; i=i+1) begin
for(j = 0; j<4; j=j+1) begin
matrix1_bus[ 8*( 4*i + j) +: 8] = matrix1[i][j];
end
end
end
example dut(
.matrix1_bus(matrix1_bus),
// ... other ports ...
);
// ...
endmodule
module example(
input [8*4*4-1:0] matrix1_bus,
// ... other ports ...
);
integer i,j;
reg [7:0] matrix1 [0:3][0:3];
always #* begin
for(i = 0; i<4; i=i+1) begin
for(j = 0; j<4; j=j+1) begin
matrix1[i][j] = matrix1_bus[ 8*( 4*i + j) +: 8];
end
end
end
// ... other logic
endmodule
Or mix/match combination of two approaches.
For a small matrix it doesn't matter which approaches you use. For a very larger matrix, then the specific synthesizer tool, version, and synthesis constraints may start becoming factors on which strategy to use.

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.

How can I use genvar variable to access input signals?

I have a module with 30-vector inputs.. I need help in the for loop assignment.
module test (
input [3:0] i0,
input [3:0] i1,
input [3:0] i2,
...
input [3:0] i29
);
wire [3:0] int_i [0:29];
genvar j;
generate
for (j=0; j<30; j=j+1) begin
assign int_i[j] = i(j) //need help here
end
endgenerate
endmodule
Is there a easy way to do this in Verilog. I know I can do this in System verilog by creating a 2-d vector of inputs. But is there a way to do this in Verilog?
The only way to do this in Verilog is to flatten out the 2-D array into a single vector.
module test (
input [30*4-1:0] i;
);
wire [3:0] int_i [0:29];
genvar j;
for (j=0; j<30; j=j+1) begin
assign int_i[j] = i[4*j+:4];
end
This is a systemverilog feature, in verilog, this should be packing the input array into a vector (I included a parameter in order to automatize things):
module test
# (
parameter WIDTH = 4,
parameter DEPTH = 30
) (input [(WIDTH*DEPTH)-1:0] i);
wire [WIDTH-1:0] int_i [DEPTH-1:0];
genvar j;
generate
for(j=0; j<DEPTH; j=j+1) begin: assign_i_gen //..(don't forget to name the for loop)
assign int_i[j] = i[(WIDTH*j)+:WIDTH];
end
endgenerate

How to fix X in the nonrestoring divider output?

I made a design for a divider, but the result is wrong.
module div(x,y,quotient,remainder);
parameter M=4;
parameter N=4;
input [M-1:0] x;
input [N-1:0] y;
output [N-1:0] quotient;
output [M-1:0] remainder;
wire [M-1:0] rem_carry;
wire sum[M-1:0][N-1:0];
wire carry[M-1:0][N-1:0];
genvar i, j;
generate for(i=N-1; i>=0; i=i-1) begin:
unsigned_divider
if(i==N-1)
for(j=0; j<M; j=j+1) begin: first_row
if(j==0)
assign {carry[j][i],sum[j][i]}=y[i]+!x[j]+1;
assign {carry[j][i],sum[j][i]}=!x[j]+carry[j-1][i];
end
else
for(j=0; j<M;j=j+1) begin:rest_rows
if(j==0)
assign{carry[j][i],sum[j][i]}=y[i]+(x[j]^carry[M-1][i+1])+carry[M-1][i+1];
else
assign {carry[j][i],sum[j][i]}=sum[j-1][i+1]+(x[j]^carry[M-1][i+1])+carry[j-1][i];
end
end endgenerate
generate for(i=0; i<N; i=i+1)
begin:product_quotient
assign quotient[i]=carry[M-1][i];
end endgenerate
generate for(j=0;j<M;j=j+1)
begin:remainder_adjust
if(j==0)
assign{rem_carry[j],remainder[j]} = sum[j][0]+(sum[M-1][0]&x[j]);
else
assign{rem_carry[j],remainder[j]} =sum[j][0]+(sum[M-1][0]&x[j])+rem_carry[j-1];
end endgenerate
endmodule
and testbench simulation code
module tb_div();
parameter M = 4; // default divisor width
parameter N = 4; // default dividend width
reg [M-1:0] x;
reg [N-1:0] y;
wire[N-1:0] quotient;
wire[M-1:0] remainder;
wire[M-1:0] rem_carry;
div U0(.x(x), .y(y), .quotient(quotient), .remainder(remainder));
initial begin
x = 0; y = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
x=4'b0001;y=4'b0000;
#300 x=4'b0100;y=4'b0011;
#300 x=4'b1101;y=4'b1010;
#300 x=4'b1110;y=4'b1001;
#300 x=4'b1111;y=4'b1010;
end
endmodule
But, quotient, remainder, rem_carry is not value.
How to change the code? I think testbench is the problem.
The X values on quotient and remainder are due to contention on carry and sum in the design. Change:
assign {carry[j][i],sum[j][i]}=!x[j]+carry[j-1][i];
to:
else assign {carry[j][i],sum[j][i]}=!x[j]+carry[j-1][i];
The missing else caused carry to be simultaneously driven by 2 assign statements. The same goes for sum. My simulators gave me a "part-select index out of declared bounds" compile warning on that line. Proper indentation would have made it easier to catch this bug.
You get Z on the rem_carry signal in the testbench because the signal is undriven. You need to add an output port to the div module and make the proper connection in the testbench.

Verilog HDL syntax error near text "for"; expecting "endmodule"

So I just got around to learning verilog and I was implementing a basic binary adder in it.
From my limited understanding of verilog, the following should add two 16-bit values.
module ADD(X, Y, Z);
input[15:0] X;
input[15:0] Y;
output Z[15:0];
wire C[15:0];
assign C[0] = 0;
integer i;
for(i=1; i<16; i=i+1) begin
assign C[i]=(X[i-1]&Y[i-1])|(X[i-1]&C[i-1])|(Y[i-1]&C[i-1]);
end
for(i=0; i<16; i=i+1) begin
assign Z[i]=X[i]^Y[i]^C[i];
end
endmodule
However, I get an error when I try to synthesize the above.
Error (10170): Verilog HDL syntax error at add.v(10) near text "for"; expecting "endmodule"
I'm not sure what is wrong with the code. Any help is appreciated!
The for-loop is used outside of an always block, so i needs to be a genvar instead of an integer. Also, you probably want Z and C to declared an packed arrays instead of unpacked, mo the [15:0] to the other side.
output [15:0] Z; // make as packed bits
wire [15:0] C;
assign C[0] = 0;
genvar i; // not integer
generate // Required for IEEE 1364-2001, optional for *-2005 and SystemVerilog
for(i=1; i<16; i=i+1) begin
assign C[i]=(X[i-1]&Y[i-1])|(X[i-1]&C[i-1])|(Y[i-1]&C[i-1]);
end
for(i=0; i<16; i=i+1) begin
assign Z[i]=X[i]^Y[i]^C[i];
end
endgenerate // must be matched with a generate
Alternative solution 1: use an always block
output reg[15:0] Z; // make as reg
reg [15:0] C;
integer i; // integer OK
always #* begin
for(i=1; i<16; i=i+1) begin
if (i==0) C[i] = 1'b0;
else C[i]=(X[i-1]&Y[i-1])|(X[i-1]&C[i-1])|(Y[i-1]&C[i-1]);
Z[i]=X[i]^Y[i]^C[i];
end
end
Alternative solution 2: bit-wise assignment
output [15:0] Z;
wire [15:0] C = { (X&Y)|(X&C)|(Y&C) , 1'b0 };
assign Z = X^Y^C;
Alternative solution 3: behavioral assignment
output [15:0] Z;
assign Z = X+Y;
Working examples here
Change the definition of i from integer to genvar.
Notice that for loops can be used either in an always block or in a generate block. The latter is implicitly the context that you are using it in your code. In generate blocks, the loop variable should be of type genvar.
More info in IEEE Std 1800-2012

Shift Register Design using Structural Verilog outputs X

I am designing a shift register using hierarchical structural Verilog. I have designed a D flip flop and an 8 to 1 mux that uses 3 select inputs. I am trying to put them together to get the full shift register, but my output only gives "XXXX" regardless of the select inputs.
Flip Flop Code
module D_Flip_Flop(
input D,
input clk,
output Q, Q_bar
);
wire a,b,c,d;
nand(a,D,b);
nand(b,a,clk,d);
nand(c,a,d);
nand(d,c,clk);
nand(Q,d,Q_bar);
nand(Q_bar,b,Q);
endmodule
8 to 1 Mux
module Mux8to1(
input [2:0]S,
input A,B,C,D,E,F,G,H,
output Out
);
wire a,b,c,d,e,f,g,h;
and(a, A,~S[2],~S[1],~S[0]);
and(b, B,~S[2],~S[1],S[0]);
and(c, C,~S[2],S[1],~S[0]);
and(d, D,~S[2],S[1],S[0]);
and(e, E,S[2],~S[1],~S[0]);
and(f, F,S[2],~S[1],S[0]);
and(g, G,S[2],S[1],~S[0]);
and(h, H,S[2],S[1],S[0]);
or(Out, a,b,c,d,e,f,g,h);
endmodule
Hierarchical Combination of the Two
module shiftRegister_struct(
input clk,
input [2:0]S,
input [3:0]L,
output reg [3:0]V
);
wire a,b,c,d;
wire V_bar[3:0];
Mux8to1 stage3(S[2:0],V[3],V[0],V[2],1'b0,V[2],V[3],V[2],L[3],a);
Mux8to1 stage2(S[2:0],V[2],V[3],V[1],V[3],V[1],V[3],V[1],L[2],b);
Mux8to1 stage1(S[2:0],V[1],V[2],V[0],V[2],V[1],V[2],V[1],L[1],c);
Mux8to1 stage0(S[2:0],V[0],V[1],V[3],V[1],1'b0,V[1],1'b0,L[0],d);
D_Flip_Flop stage3b(a,clk,V[3],V_bar[3]);
D_Flip_Flop stage2b(b,clk,V[2],V_bar[2]);
D_Flip_Flop stage1b(c,clk,V[1],V_bar[1]);
D_Flip_Flop stage0b(d,clk,V[0],V_bar[0]);
end module
Any thoughts on what might be screwing up my output? The output is V[3:0].
I should also include my test bench code:
module Shift_Test_Bench;
// Inputs
reg [2:0] S;
reg [3:0] L;
reg clk;
integer i;
integer j;
// Outputs
wire [3:0] V;
// Instantiate the Unit Under Test (UUT)
shiftRegister_struct uut (
.clk(clk),
.S(S),
.L(L),
.V(V)
);
initial begin
// Initialize Inputs
S = 7;
L = 3;
clk = 1;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
for(i = 0; i < 16; i = i+1)
begin
S = i;
for(j = 0; j < 2; j = j+1)
begin
clk = !clk;
#5;
end
end
end
endmodule
You have a wiring bug in your D_Flip_Flop module. When I simulated your testbench, I got compiler warnings:
Implicit wire 'f' does not have any driver, please make sure this is
intended.
Implicit wire 'e' does not have any driver, please make sure this is
intended.
Here are the lines:
nand(Q,d,f);
nand(Q_bar,b,e);
Your missing a reset condition, either synchronous or asynchronous. Your flops have an unknown value and never reach known state because the data input is dependent on the flop output. By adding a reset to can put the flops into a known state independent of its outputs (V/V_bar).
In this case adding a synchronous is be easier. Simply add some 2-to-1 muxes and a new reset pin.
Mux2to1 syncrst3(a_d,a,1'b0,reset);
// ...
D_Flip_Flop stage3b(a_d,clk,V[3],V_bar[3]);
// ...

Resources