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.
Related
I'm new to verilog. I write a 3-8 decoder and a testbench for it. This is 38_decoder_tb.v:
module decoder_38(input [2:0] in, output reg [7:0] out);
always #* begin
case (in) //Switch based on concatenation of control signals
3'b000 : out = 8'b00000001;
3'b001 : out = 8'b00000010;
3'b010 : out = 8'b00000100;
3'b011 : out = 8'b00001000;
3'b100 : out = 8'b00010000;
3'b101 : out = 8'b00100000;
3'b110 : out = 8'b01000000;
3'b111 : out = 8'b10000000;
endcase
end
endmodule
This is 38_decoder_tb.v:
`timescale 1ns / 1ns
module tb_decoder_38;
// decoder_38 Parameters
parameter PERIOD = 20;
// decoder_38 Inputs
reg [2:0] in ;
// decoder_38 Outputs
wire [7:0] out ;
reg clk;
integer i;
initial
begin
clk = 0;
forever #(PERIOD/2) clk=~clk;
end
decoder_38 u_decoder_38 (
.in ( in [2:0] ),
.out ( out [7:0] )
);
initial
begin
in = 0;
#(PERIOD*2);
for (i = 3'd0; i < 3'd8; i=i+1) begin
in = i;
#PERIOD;
end
end
endmodule
I stimulate the testbench module with ModelSim 10.5. As you can see, the signal just doesn't update. What's the problem? Does it have something to do with the for loop?
Yes, the issue is with the loop.
Your problem is in definition of 3'd8. 8 is the same as 1000 in binary presentation and requires 4 bits. Therefore, 3-bits of it (as you requested) yield 000. As a result your loop does not run at all, looking like the following: for (i = 3'd0; i < 0; i++).
Variable i is defined as integer. An integer type is a 4-state data type, 32-bit signed integer. So, rewriting loop as for(i = 0; i < 8; i++) will solve your issues. There is absolutely no need to define sizes for the constants in this loop.
And, to avoid infinite loop, you need to use $finish when appropriate, as suggested in the other answer.
The posted testbench has an infinite loop because of the forever loop with nothing to stop it.
I added a #30 delay to see the last clock of data, and $finish to stop it.
After that the code behaves as expected.
All 4 simulators on EDA Playground show the same.
initial
begin
in = 0;
#(PERIOD*2);
for (i = 3'd0; i <= 3'd7; i=i+1) begin
in = i;
#PERIOD;
end
//
#30;
$finish;
end
Here is a link playground I put together https://www.edaplayground.com/x/aZYL
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'm doing a LOTTT of pipelining with varying width signals and wanted a SYNTHESIZEABLE module wherein i could pass 2 parameters : 1) number of pipes (L) and 2) width of signal (W).
That way i just have to instantiate the module and pass 2 values which is so much simple and robust than typing loads and loads of signal propagation via dummy registers...prone to errors and et all.
I have HALF written the verilog code , kindly request you to correct me if i am wrong.
I AM FACING COMPILE ERROR ... SEE COMMENTS
*****************************************************************
PARTIAL VERILOG CODE FOR SERIAL IN SERIAL OUT SHIFT REGISTER WITH
1) Varying number of shifts / stages : L
2) Varying number of signal / register width : W
*****************************************************************
module SISO (clk, rst, Serial_in, Serial_out); // sIn -> [0|1|2|3|...|L-1] -> sOut
parameter L = 60; // Number of stages
parameter W = 60; // Width of Serial_in / Serial_out
input clk,rst;
input reg Serial_in;
output reg Serial_out;
// reg [L-1:0][W-1:0] R;
reg [L-1:0] R; // Declare a register which is L bit long
always #(posedge clk or posedge rst)
begin
if (rst) // Reset = active high
//**********************
begin
R[0] <= 'b0; // Exceptional case : feeding input to pipe
Serial_out <= 'b0; // Exceptional case : vomiting output from pipe
genvar j;
for(j = 1; j<= L; j=j+1) // Ensuring ALL registers are reset when rst = 1
begin : rst_regs // Block name = reset_the_registers
R[L] <= 'b0; // Verilog automatically assumes destination width # just using 'b0
end
end
else
//**********************
begin
generate
genvar i;
for(i = 1; i< L; i=i+1)
begin : declare_reg
R[0] <= Serial_in; // <---- COMPILE ERROR POINTED HERE
R[L] <= R[L-1];
Serial_out <= R[L-1];
end
endgenerate;
end
//**********************
endmodule
//**********************
Why so complicated? The following code would be much simpler and easier to understand:
module SISO #(
parameter L = 60, // Number of stages (1 = this is a simple FF)
parameter W = 60 // Width of Serial_in / Serial_out
) (
input clk, rst,
input [W-1:0] Serial_in,
output [W-1:0] Serial_out
);
reg [L*W-1:0] shreg;
always #(posedge clk) begin
if (rst)
shreg <= 0;
else
shreg <= {shreg, Serial_in};
end
assign Serial_out = shreg[L*W-1:(L-1)*W];
endmodule
However, looking at your code there are the following problems:
You declare Serial_in as input reg. This is not possible, an input cannot be a reg.
You are using generate..endgenerate within an always block. A generate block is a module item and cannot be used in an always block. Simply remove the generate and endgenerate statements and declare i as integer.
Obviously Serial_in and Serial_out must be declared as vectors of size [W-1:0].
You are using R as a memory. Declare it as such: reg [W-1:0] R [0:L-1].
You are not using i in you for loop. Obviously you meant to chain all the elements of R together, but you are just accessing the 0th, (L-1)th and Lth element. (Obviously the Lth element is nonexisting, this array would be going from 0 to L-1.
I'm now stopping writing this list because, I'm sorry, I think there really is not much to gain by improving the code you have posted..
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
I know VHDL, and just learning verilog. I'm trying to do a simple assignment with bit shift, and I get undefined 'X' in the result. I don't understand why. This is in simulation with Xilinx ISim software.
This assignment:
assign dout = $signed(data_out >>> shift_bits);
Results in 'X' wherever a '1' should be. For example, if data_out = '00001100', and shift_bits = 1, dout will = '00000XX0'.
Below is the module definition and the assignment operation:
module SensorINV(
input clk,
input [23:0] din,
input idv,
input [4:0] shift_bits,
output [23:0] dout,
output reg odv
);
reg [47:0] data_out = 0; // initialize the output
assign dout = $signed(data_out >>> shift_bits);
// assign dout = data_out[44:21]; // this didn't work either
reg [1:0] state = 0;
always #(posedge clk) begin
case (state)
0 : begin // waiting for new data
...
end
1 : begin
...
data_out <= data_out + temp1_w;
state <= 2;
end
2 : begin
...
state <= 0;
end
default : state <= 0;
endcase
end
The problem turned out to be conflicting drivers of dout, only one of which was shown in the code above. In the next module up, where this one was instantiated (not shown), I had a line like this:
wire [23:0] dout = 0;
This created a continuous assignment, not an initialization value. This conflict didn't show up in simulation until I tried to make dout non-zero. If it were a register reg, it would be an initialization value, but in this case it was a wire. Got rid of the continuous assign = 0, and problem solved.