Just for fun, I wanted to design and simulate D-type flip-flops using only combinational logic in Verilog (or SystemVerilog). I am using using Verilator for the simulation.
My initial attempt, which uses a classical six-NAND design, seems to work fine -- and has passed all tests. My second attempt, based on a four-NAND JK-type, is not working. The output doesn't stay latched during the positive level of the clock, and for some tests the simulation doesn't even converge.
Q: I know it isn't normal or optimal, but is it reasonable to design flip-flops using combinational logic in Verilog? If so, is there something wrong with my second design?
This one works:
module dff( input clk, input D, output Q );
wire a, sn, rn, b, Qn;
always_comb // captures D @( posedge clk )
begin
a = !(b&sn);
sn = !(a&clk);
rn = !(sn&b&clk);
b = !(rn&D);
Q = !(sn&Qn);
Qn = !(rn&Q);
end
endmodule
This one does not work:
module dff( input clk, input D, output Q );
wire J=D, K=!D;
wire sn, rn, qn;
always_comb // captures D @( posedge clk ), but fails to hold
begin
sn = !(J&clk&qn);
rn = !(K&clk&Q);
Q = !(sn&qn);
qn = !(rn&Q);
end
endmodule
In an effort to eliminate blocking assignment and sensitivity lists, I reimplemented the JK-based approach as follows, but the output waveforms were not affected by this difference.
module dff( input clk, input D, output Q );
wire J=D, K=!D;
wire sn, rn, qn;
assign sn = !(J&clk&qn);
assign rn = !(K&clk&Q);
assign Q = !(sn&qn);
assign qn = !(rn&Q);
endmodule
Note: I based the design of these on the descriptions and diagrams here.