I am new to Verilog and I was trying to make a Decade counter. I simply took the reference of an actual circuit that implements the decade counter using JK-Flip Flops. So I wrote a sub-module for JK-Flip Flop and a top-module that would connect all the Flip-Flops.
Here is my code for the JK-Flip Flop:
module JK(
input j,
input k,
input clk,
input reset,
output reg q
);
initial q=0;
always @ (*)
begin
if (reset)
q=0;
end
always @ (negedge clk)
begin
if (~j&&k)
q=0;
else if (j&&~k)
q=1;
else if (j&&k)
q=~q;
end
endmodule
and my code for the circuit:
module DECADECOUNTER(
input clk,
output q0,
output q1,
output q2,
output q3
);
JK jk0(1'b1,1'b1,clk,q1&q3,q0);
JK jk1(1'b1,1'b1,q0,q1&q3,q1);
JK jk2(1'b1,1'b1,q1,q1&q3,q2);
JK jk3(1'b1,1'b1,q2,q1&q3,q3);
endmodule
So the idea is that the last input is a reset and will clear all of my flip-flops if both q1 and q3 are 1 (1010).
But when I try to simulate the circuit on Xilinx, I get the following result:
This screen is from very instant the simulation starts. As you can see q0 and q1 are 0 but q2 and q3 are not. My guess is that after resetting q1, the condition q1&q3 went false and hence q2 and q3 remained to be 1. This seems as if the circuit is asynchronous. But that isn't the way Verilog is supposed to work right? If something is present in the ports, ideally its value should be propagated to other ports before it changes. Because that's how a real-world circuit is supposed to work.
-
1\$\begingroup\$ JK Flip-Flops are not used any more (except to pose difficult questions to electronic engineers), definitely not in FPGAs or ASICs. Use standard D-registers instead. \$\endgroup\$Oldfart– Oldfart2018年10月13日 07:05:12 +00:00Commented Oct 13, 2018 at 7:05
-
\$\begingroup\$ Kinda hard for anything to happen when the clock is Z. Where is your test bench? \$\endgroup\$Greg– Greg2018年10月13日 19:40:29 +00:00Commented Oct 13, 2018 at 19:40
2 Answers 2
Two problems:
In a sequential always block (one on the clock) always always always use the "non blocking assignment" which looks like a less than/equal to sign (<=).
Never ever assign to a signal from two always blocks. If you want q to be asynchronously reset, make the always block sensitive to negedge clock or posedge reset. Then have if reset first, followed by else for the other conditions. This probably isn't causing your problem now, but it will cause problems eventually.
I figured out it was best to not try and emulate hardware using code (As I was trying to emulate a traditional decade counter circuit using JK-Flip Flop). Instead, it's better to write a code that emulates the output. And the rest should be left to Xilinx to synthesize and convert code into a working piece of hardware.
So here is my new code for the Decade Counter:
module DecadeCounter(
input clk,
input reset,
output q0,
output q1,
output q2,
output q3
);
reg [3:0]q;
initial q = 0;
assign q0 = q[0];
assign q1 = q[1];
assign q2 = q[2];
assign q3 = q[3];
always @ (posedge clk or posedge reset)
begin
if(reset||q[1]&&q[3])
q <= 0;
else
q <= q + 1'b1;
end
endmodule
This code simulates really well and the best part is that it doesn't comes with the usual and nasty surprises of Verilog. It's as natural as writing code on C/C++.
-
\$\begingroup\$ You should always use nonblocking assignments for outputs from sequential always blocks, failure to do so is likely to lead to unpredictable behaviour and/or mismatches between simulation and synthesis. \$\endgroup\$Peter Green– Peter Green2018年10月15日 19:56:34 +00:00Commented Oct 15, 2018 at 19:56