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.
Related
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.
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
Why am I getting error "q is not constant"?
module prv(
input [7:0]x,
input [7:0]y,
output [49:0]z
);
wire [24:0]q;
assign z=1;
genvar k;
for (k=50; k<0; k=k-1)
begin
wire [25:0]a;
assign a=0;
assign q= x;
genvar i;
for(i=0; i<8; i=i+1)
begin
if(q[0]==1)
begin
assign a=a+z;
end
assign {a,q}={a,q}>>1;
end
assign z={a[24:0],q};
end
endmodule
I'm afraid that you are trying to use Verilog the wrong way. q is a wire, not a variable (a reg) so it cannot be assigned with a value that includes itself, because that would cause a combinational loop. You are using the assign statement as if it were a regular variable assignment statement and it's not.
Declare a and q as reg, not wire. i and k don't need to be genvars variables, unless you are trying to generate logic by replicating multiple times a piece of code (description). For for loops that need to behave as regular loops (simulation only) use integer variables.
Besides, behavioral code must be enclosed in a block, let it be combinational, sequential, or initial.
A revised (but I cannot make guarantees about its workings) version of your module would be something like this:
module prv(
input wire [7:0] x,
input wire [7:0] y,
output reg [49:0] z
);
reg [24:0] q;
reg [25:0] a;
integer i,k;
initial begin
z = 1;
for (k=50; k<0; k=k-1) begin
a = 0;
q = x;
for (i=0; i<8; i=i+1) begin
if (q[0] == 1) begin
a = a + z;
end
{a,q} = {a,q}>>1;
end
z = {a[24:0],q};
end
endmodule
Can you tell me why this simple verilog program doesn't print 4 as I want?
primitive confrontatore(output z, input x, input y);
table
0 0 : 1;
0 1 : 0;
1 0 : 0;
1 1 : 1;
endtable
endprimitive
comparatore :
module comparatore (r, x, y);
output wire r;
input wire [21:0]x;
input wire [21:0]y;
wire [21:0]z;
genvar i;
generate
for(i=0; i<22; i=i+1)
begin
confrontatore t(z[i],x[i],y[i]);
end
endgenerate
assign r = & z;
endmodule
commutatore :
module commutatore (uscita_commutatore, alpha);
output wire [2:0]uscita_commutatore;
input wire alpha;
reg [2:0]temp;
initial
begin
case (alpha)
1'b0 : assign temp = 3;
1'b1 : assign temp = 4;
endcase
end
assign uscita_commutatore = temp;
endmodule
prova:
module prova();
reg [21:0]in1;
reg [21:0]in2;
wire [2:0]uscita;
wire uscita_comparatore;
comparatore c(uscita_comparatore, in1, in2);
commutatore C(uscita, uscita_comparatore);
initial
begin
in1 = 14;
$dumpfile("prova.vcd");
$dumpvars;
$monitor("\n in1 %d in2 %d -> uscita %d uscita_comparatore %d \n", in1, in2, uscita, uscita_comparatore);
#25 in2 = 14;
#100 $finish;
end
endmodule
The issue is in commutatore. You are using initial, which means the procedural block is only executed at time 0. At time 0, the input alpha is 1'bx, meaning temp is not assigned to anything. Instead of initial, use always #* which will execute the procedural block every time alpha changes.
Generally you should not assign statements in procedural blocks. It is legal Verilog however it is often the source of design bugs and synthesis support is limited.
always #*
begin
case (alpha)
1'b0 : temp = 3;
1'b1 : temp = 4;
default: temp = 3'bx; // <-- optional : to catch known to unknown transitions
endcase
end
The reason you are not getting 4 as you expect for an output is because your commutatore uses an initial block with assign statements in it when you wanted an always #* block to perform the combinational logic to get temp. initial blocks only fire once at the beginning of a simulation, while you want continuous assignment to act as combinational logic. Also, the assign statements in the block are not needed, they only make the simulation behave improperly for your purposes (typically, you will never need to use assign inside another block (initial,always,etc) as this has another meaning than simply set x to y.
For example, you really want something like this:
always #(*) begin
case (alpha)
1'b0: temp = 3'd3;
1'b1: temp = 3'd4;
endcase
end
Also, Verilog already has a build XNOR primative so your confrontatore is not needed, you can use xnor instead.
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