Verilog waveform of inputs is identical, however, output is different - verilog

I'm currently trying to implement an up/down counter in Verilog with dataflow modeling. While trying to add a limit to the counter (so that the counter will reset to the appropriate value when the limit is reached) I stumbled into an error. Even though the waveforms of clear_q, clear, and clear_s are the same, likewise the waveforms of preset_q, preset, and preset_s are the same, the behaviors of Q, R, and S are different, notably Q is different from R and S.
Picture of Waveforms
Of note, the rising edge of the three clear signals is not aligned with the falling edge of the clock, however, Q going from 0 to F is aligned with the rising edge of the three clear signals.
From the code, it is clear that the only difference between clear_q and clear_s, and preset_q and preset_s, is the simple inclusion of "& 1'b1". The only way that Q would go to F from 0 is if preset_q goes low and clear_q goes high momentarily, however from the waveform preset_q stays high.
The purpose of the "& 1'b1" is to temporarily simulate the equality checker commented out.
What exactly is wrong with the "& 1'b1" or is there another issue at hand?
limited_ud_counter.v
module limited_ud_counter(input clk, preset, clear, up, input[3:0] limit, output[3:0] Q);
//wire[3:0] n;
wire[3:0] Q, R, S;
wire e, preset_p, clear_p;
// assign n[0] = Q[0] ^ limit[0];
// assign n[1] = Q[1] ^ limit[1];
// assign n[2] = Q[2] ^ limit[2];
// assign n[3] = Q[3] ^ limit[3];
// assign e = !(n[0] | n[1] | n[2] | n[3]);
assign e = 0;
//(preset & clear & (!(e & up))) | (preset & !clear);
//(preset & clear & !(e & (!up))) | (clear & !preset);
assign preset_q = ((preset & clear) & 1'b1) | (preset & !clear);
assign clear_q = ((preset & clear) & 1'b1) | (clear & !preset);
assign preset_s = ((preset & clear)) | (preset & !clear);
assign clear_s = ((preset & clear)) | (clear & !preset);
//Q not showing expected behavior
up_down_counter udc0(clk, preset_q, clear_q, up, Q);
//R showing expected behavior
up_down_counter udc1(clk, preset, clear, up, R);
//S also showing expected behavior
up_down_counter udc2(clk, preset_s, clear_s, up, S);
endmodule;
up_down_counter.v
module up_down_counter(input clk, preset, clear, up, output[3:0] Q);
wire[2:0] jk_up, jk_down, jk;
wire[3:0] Q_bar;
assign jk_up[0] = Q[0] & up;
assign jk_down[0] = Q_bar[0] & (!up);
assign jk[0] = jk_up[0] | jk_down[0];
assign jk_up[1] = Q[1] & jk_up[0];
assign jk_down[1] = Q_bar[1] & jk_down[0];
assign jk[1] = jk_up[1] | jk_down[1];
assign jk_up[2] = Q[2] & jk_up[1];
assign jk_down[2] = Q_bar[2] & jk_down[1];
assign jk[2] = jk_up[2] | jk_down[2];
jkff jkff0(clk, 1'b1, 1'b1, preset, clear, Q[0], Q_bar[0]);
jkff jkff1(clk, jk[0], jk[0], preset, clear, Q[1], Q_bar[1]);
jkff jkff2(clk, jk[1], jk[1], preset, clear, Q[2], Q_bar[2]);
jkff jkff3(clk, jk[2], jk[2], preset, clear, Q[3], Q_bar[3]);
endmodule
jkff.v
module jkff(input clk, j, k, preset, clear, output q, q_bar);
wire j_p, k_p, q_m, q_bar_m;
assign j_p = !(j & q_bar & clk);
assign k_p = !(k & q & clk);
sr sr0(j_p, k_p, preset, clear, q_m, q_bar_m);
gated_sr gsr0(!clk, q_m, q_bar_m, preset, clear, q, q_bar);
endmodule;
sr.v
//set, reset, preset, clear are active low
module sr(input set, reset, preset, clear, output q, q_bar);
assign q = !(set & preset & q_bar);
assign q_bar = !(reset & clear & q);
endmodule
gated_sr.v
//enable, set, and reset are active high; preset and clear are active low
module gated_sr(input enable, set, reset, preset, clear, output q, q_bar);
wire set_p, reset_p;
assign set_p = !(set & enable);
assign reset_p = !(reset & enable);
sr sr0 (
.set (set_p),
.reset (reset_p),
.preset (preset),
.clear (clear),
.q (q),
.q_bar (q_bar)
);
endmodule
testbench code
`include "limited_ud_counter.v"
`include "../UpDownCounter/up_down_counter.v"
`include "../JKFF/jkff.v"
`include "../GatedSR/gated_sr.v"
`include "../SR/sr.v"
module limited_ud_counter_tb;
reg clk, preset, clear, up;
reg[3:0] limit;
wire[3:0] Q;
always begin
#5 clk = !clk;
end
initial begin
$dumpfile("limited_ud_counter_tb.vcd");
$dumpvars;
clk = 1'b0;
up = 1'b1;
preset = 1'b1;
clear = 1'b0;
limit = 4'b1100;
#12 clear = 1'b1;
#200 $finish;
end
limited_ud_counter ludc0(clk, preset, clear, up, limit, Q);
endmodule
This is using Icarus Verilog if that helps.

I've figured out the issue. What was happening was while the values of preset_q and clear_q were being computed, there was a moment where both preset_q and clear_q went low. Since these were fed into SR-latches, an error would occur.
All at the same time (t=12), preset_q and clear_q went like this:
preset_q = 1, clear_q = 0
preset_q = 0, clear_q = 0 <- this is the problem
preset_q = 1, clear_q = 1
Since these all happened at the same time, only the final values were visible on the waveform. To fix this, I chose to make both preset and clear signals go high if they were both low at the SR-latch level.

Related

Had created a verilog code for modified D flip flop, but when simulated the desing, getting ouput for q and q' as x [duplicate]

I'm trying to simulate the working of t-flipflop.
`timescale 1ns / 1ps
module t_flipflop(
input t,
input clk,
input clear,
output q,
output qbar
);
wire sbar, rbar;
assign sbar= ~(t & clk & qbar & clear);
assign rbar= ~(t & clk & q);
assign q= ~(sbar & qbar);
assign qbar= ~(rbar & q & clear);
endmodule
Now in output the value of q toggles when t=1, but the value of qbar is always 1.
Also when t=1, q is always 0 and qbar is 1.
What am I doing wrong?
Test fixture:
`timescale 1ns / 1ps
module test_t_flipflop;
// Inputs
reg t;
reg clk;
reg clear;
// Outputs
wire q;
wire qbar;
// Instantiate the Unit Under Test (UUT)
t_flipflop uut (
.t(t),
.clk(clk),
.clear(clear),
.q(q),
.qbar(qbar)
);
initial begin
clear=1'b0;
#34 clear=1'b1;
end
initial begin
t=1'b0;
clk=1'b0;
forever #15 clk=~clk;
end
initial begin
#10 t=1;
#95 t=0;
#40 t=1;
end
I want to implement this with the data flow model to understand it clearly.
You are attempting to model sequential logic with continuous assignments. This can result in unpredictable simulation results. For example, when I run your code using Incisive, it results in an infinite loop, which usually indicates a race condition. I assume the race is due to the feedback path: q depends on qbar which in turn depends on q.
The proper way to model sequential logic is to use this register-transfer logic (RTL) coding style:
module t_flipflop (
input t,
input clk,
input clear,
output reg q,
output qbar
);
assign qbar = ~q;
always #(posedge clk or negedge clear) begin
if (!clear) begin
q <= 0;
end else if (t) begin
q <= ~q;
end
end
endmodule
This eliminates the feedback path and simplifies your code by eliminating the internal wires. It can also be used for synthesis.

Why output is in unknown state?

I want to make a serial comparator using a dff with async reset base on with continuous assignment. but output will come in unknown (x) state I don't know why. I checked every wire and assigned each of them an expression
dff code (verilog):
module comparator (input a, input b, input reset, input clk, output [1:0] o);
wire q0_p, q0_n, q1_p, q1_n, d0, d1;
wire s0, r0, w01, w02, s1, r1, w11, w12;
assign d0 = (q1_n & q0_p) | (q0_p & ~a & b) | (q1_n & ~a & b);
assign d1 = (q1_p & q0_n) | (q0_n & a & ~b) | (q1_p & a & ~b);
assign w01 = ~(w02 & s0);
assign s0 = ~(w01 & reset & clk);
assign r0 = ~(s0 & clk & w02);
assign w02 = ~(r0 & d0 & reset);
assign q0_p = ~(s0 & q0_n);
assign q0_n = ~(q0_p & r0 & reset);
assign w11 = ~(w12 & s1);
assign s1 = ~(w11 & reset & clk);
assign r1 = ~(s1 & clk & w12);
assign w12 = ~(r1 & d1 & reset);
assign q1_p = ~(s1 & q1_n);
assign q1_n = ~(q1_p & r1 & reset);
assign o[0] = q0_p;
assign o[1] = q1_p;
endmodule
testbench:
module test();
reg a, b, reset, clk = 0;
wire [1:0] o;
comparator cmp(a, b, reset, clk, o);
always #1 clk <= ~clk;
initial begin
$monitor("%b %b %b", a, b, o);
reset = 0;
reset = 1;
// a = 1110, b = 1011
#1 a = 1; b = 1;
#1 a = 1; b = 0;
#1 a = 1; b = 1;
#1 a = 0; b = 1;
$finish();
end
endmodule
output:
1 1 xx
1 0 xx
1 1 xx
0 1 xx
if 'D' is in 'x' state, as soon as you deassert reset, the outputs will become 'x' again. You need to set a known value to 'D' before deassert. Also, you need a delay between assert and deassert of reset.
For example,
initial begin
$monitor("%b %b %b", a, b, o);
reset = 0;
#1
a = 0; b = 0;
reset = 1;
...
As you can see, it is non-trivial to debug simulation problems when trying to model a logic circuit with feedback at the gate level. You get unknowns (x) because you do not correctly initialize all the signals which need to be initialized.
Your testbench does not really drive the reset signal to 0 because you immediately drive it to 1 (both happen at time 0). You should add a delay between the 2 values. However, that will still be insufficient to initialize all the signals.
The solution is to use the appropriate model for your logic: behavioral level. This is trivial in Verilog. The common way to model a dff with an asynchronous active-low reset is:
always #(posedge clk or negedge nreset) begin
if (!nreset) begin
q <= 1'b0;
end else begin
q <= d;
end
end
The beauty of digital design and Verilog is that you can abstract away all the unnecessary details. The code above eliminates all the issues with properly initializing all your signals.

Verilog Constructing synchronous 4-bit counter using negative edged JK Flip Flop testbench problem

I am constructing a 4-bit mod 12 counter
(0->1->2->...->11->0) in Verilog.
However when I try to simulate this code with testbench in Vivado FPGA,
it doesn't seems to operate correctly. Output of the counter module always shows 0.
I tried to modify testbench codes in several ways but nothing has been changed.
Actually I constructed 2 more counter(3-6-9 counter, 2-digit decade counter),
all counters are not simulated as I expected.
module counter3
`timescale 1ns / 1ps
module counter_3(input RESET_N, input CK, output[3:0] COUNT, output[3:0] COMP);
wire J3, K3, J2, K2, J1, K1, J0, K0;
assign J3 = COUNT[2] & COUNT[1] & COUNT[0];
assign K3 = COUNT[1] & COUNT[0];
assign J2 = COMP[3] & COUNT[1] & COUNT[0];
assign K2 = COUNT[1] & COMP[0];
assign J1 = COUNT[0];
assign K1 = COUNT[0];
assign J0 = 1;
assign K0 = 1;
edgeTriggeredJKFF jk1(.RESET_N(RESET_N), .J(J3), .K(K3), .CK(CK), .Q(COUNT[3]), .Q_(COMP[3]));
edgeTriggeredJKFF jk2(.RESET_N(RESET_N), .J(J2), .K(K2), .CK(CK), .Q(COUNT[2]), .Q_(COMP[2]));
edgeTriggeredJKFF jk3(.RESET_N(RESET_N), .J(J1), .K(K1), .CK(CK), .Q(COUNT[1]), .Q_(COMP[1]));
edgeTriggeredJKFF jk4(.RESET_N(RESET_N), .J(J0), .K(K0), .CK(CK), .Q(COUNT[0]), .Q_(COMP[0]));
endmodule
module edgeTriggeredJKFF
`timescale 1ns / 1ps
module edgeTriggeredJKFF(input RESET_N, input J, input K, input CK, output reg Q, output reg Q_);
initial begin
Q = 0;
Q_ = ~Q;
end
always #(negedge CK) begin
Q = RESET_N & (J&~Q | ~K&Q);
Q_ = ~RESET_N | ~Q;
end
endmodule
Testbench Code
`timescale 1ns / 1ps
module test_tb();
reg counter3_RESET_N;
wire [3:0] counter3_CNT;
reg CK;
integer i;
counter_3 c3 (.RESET_N(counter3_RESET_N), .CK(counter3_ck), .COUNT(counter3_CNT));
always #3 CK = ~CK;
initial begin
Passed = 0;
Failed = 0;
CK <= 0;
counter_3_test;
end
task counter_3_test;
begin
CK <= 0;
counter3_RESET_N <= 1;
#60 counter3_RESET_N <= 0;
#6 counter3_RESET_N <= 1;
#48;
end
endtask
endmodule
You forgot to pass your clock down to the DUT. Instead of CK you passed counter3_ck which has not even been declared. I suggest that you the ``default_nettype none directive to catch those bugs.
On the side note, you misuse blocking and non-blocking assignments. There should be none in the intial block of your test bench and you should have used them in the flop of your jk module. Q_ will not work correclty and will be late one cycle in this case. It should be combinational:
always #(negedge CK)
Q <= RESET_N & (J&~Q | ~K&Q);
always #*
Q_ = ~RESET_N | ~Q;
And you should always consider any initial block as a part of the testbench. So is your initial block in the jk module.

Unexpected output when creating a JK Flip Flop module using an SR Flip Flop

I have written Verilog modules for SR Latch, SR Flip Flop (by instantiating the SR Latch module), and JK Flip Flop (by instantiating the SR Latch module). I'm using Xilinx Vivado 2019 version for simulation and viewing output waveforms. The SR Latch and SR Flip flop modules work just fine and I'm getting the proper output waveforms also. I tried creating a JK Flip Flop Module by instantiating the SR Latch Module. But, I just don't get the output waveforms. I don't know what is going wrong. I checked the Boolean expressions as well. Everything seems to be fine. Can someone please point out the error?
Here are the codes.
SR Latch Module
module sr_latch(s, r, q, qbar);
input s, r;
output q, qbar;
nand(q, s, qbar);
nand(qbar, r, q);
endmodule
SR Flip Flop Module using the SR Latch
module sr_ff(s, r, clk, q, qbar);
input s, r, clk;
output q, qbar;
reg t1, t2;
always #(posedge clk)
begin
t1 <= !(clk & s);
t2 <= !(clk & r);
end
sr_latch SRL(t1, t2, q, qbar);
endmodule
JK Flip Flop using SR Latch
module jk_ff(j, k, clk, q, qbar);
input j, k, clk;
output q, qbar;
reg t1, t2;
always #(posedge clk)
begin
t1 <= !(clk & qbar & j);
t2 <= !(clk & q & k);
end
sr_latch SRL(t2, t1, q, qbar);
endmodule
JK Flip Flop Testbench
module jk_ff_tb();
wire q, qbar;
reg j, k, clk=1;
integer i;
jk_ff JKFF(j, k, clk, q, qbar);
always #25 clk = !clk;
initial
begin
for(i=0; i<4; i=i+1)
begin
{j, k} <= i; #50;
end
$stop;
end
endmodule
Your output is unknown (X) because your jk_ff model does not allow for proper initialization of the SR Latch.
Based on this simple schematic, you need to just implement the 2 NAND gates on the inputs to the SR latch:
This is one way, using continuous assignments:
module jk_ff (j, k, clk, q, qbar);
input j, k, clk;
output q, qbar;
wire sn = clk & qbar & j;
wire rn = clk & q & k;
sr_latch SRL (sn, rn, q, qbar);
endmodule
This allows the output to become known.
Another way is to add 2 nand primitives.
Note that the JK Flip-flop can be constructed from an SR Latch, not an SR Flip-flop.

Using created ALU to make a bigger one

I have a 8-bit ALU unit in verilog that can do addition, invert, etc. This single unit is tested and performs correctly. When I combine 4 of these to make a bigger ALU every output is correct except when I choose the addition operation it comes out as
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010101, basically the first alu does the work right then the output from the second is xxxxxxxx as is the third and fourth. This is really frustrating!!
the 8 bit module( it would be nice to point if this model is behavioral or structural model i go for the former!)
module alu_8bit(
output reg [7:0] out,
output reg cout,g,e,
input [7:0] A,B,
input cin,
input [2:0] S
);
//used functions
parameter BUF_A = 3'b000;
parameter NOT_A = 3'b001;
parameter ADD = 3'b010;
parameter OR = 3'b011;
parameter AND = 3'b100;
parameter NOT_B = 3'b101;
parameter BUF_B = 3'b110;
parameter LOW = 3'b111;
always #(A or B or S) begin
//Comparator
g = A>B;
e = A==B;
//Other selective functions
case(S)
BUF_A: out = A;
NOT_A: out = ~A;
ADD: {cout,out} = A+B+cin;
OR: out = A | B;
AND: out = A & B;
NOT_B: out = ~B;
BUF_B: out = B;
LOW: out = {8{1'b0}};
endcase
end
endmodule
Here is the code of the bigger one:
module alu_32bit(
output [31:0] out,
output cout,g,e,
input [31:0] A,B,
input cin,
input [2:0] S
);
wire e1,e2,e3,e4;
wire g1,g2,g3,g4;
alu_8bit ALU1(out[7:0],cin2,g1,e1,A[7:0],B[7:0],cin,S);
alu_8bit ALU2(out[15:8],cin3,g2,e2,A[15:8],B[15:8],cin2,S);
alu_8bit ALU3(out[23:16],cin4,g3,e3,A[23:16],B[23:16],cin3,S);
alu_8bit ALU4(out[31:24],cout,g4,e4,A[31:24],B[31:24],cin4,S);
assign g = g4 | (e4 & g3) |(e4 & e3 & g2) | (e4& e3 & e2 & g1);
assign e = e4 & e3 & e2 & e1;
endmodule
Can any one give some help?! if you need more info just tell me.
Edited:
Waveform pic clearly input comes in correct but output not
The dataflow diagram shows that ALU1 output is just fine
Your sensitivity list for the main part of the ALU doesn't include cin.

Resources