我正在努力使用 T 触发器(JK,J=K=1)在 SystemVerilog 中实现 BCD 计数器。目标是从 0 计数到 9,然后重置回 0。我使用 JK 触发器的 clr 输入,打算在计数达到 4'b1010 时重置触发器。然而,我面临一个问题,在到达 4'b1010 时,计数器重置为 4 而不是 0。
经调查,该问题似乎可能与第三个触发器有关,因为它将always_ff块中的两个条件评估为true。
我的顶级设计:
module bcdCounter(
input logic clk,
input logic rst,
output logic Q0,
output logic Q1,
output logic Q2,
output logic Q3,
output [3:0] out
);
assign out = {Q3,Q2,Q1,Q0};
logic clr;
assign clr = ~(Q3 & Q1);
// $monitor("the value of clr is %0d and Q3 is %d and Q1 is %d", clr,Q3,Q1);
jkFlipFlop flipFlop1(.J(1'b1), .K(1'b1), .rst(rst), .clk(clk), .clr(clr), .Q(Q0));
jkFlipFlop flipFlop2(.J(1'b1), .K(1'b1), .rst(rst), .clk(Q0), .clr(clr), .Q(Q1));
jkFlipFlop flipFlop3(.J(1'b1), .K(1'b1), .rst(rst), .clk(Q1), .clr(clr), .Q(Q2));
jkFlipFlop flipFlop4(.J(1'b1), .K(1'b1), .rst(rst), .clk(Q2), .clr(clr), .Q(Q3));
endmodule
翻牌代码:
module jkFlipFlop(
input logic J,
input logic K,
input logic rst,
input logic clk,
input logic clr,
output logic Q
);
always_ff @(negedge clk, negedge clr ,posedge rst) begin
if (rst) begin
Q <= 1'b0;
end
else if(clr == 1'b0) begin
Q <= 1'b0;
end
else if(clr != 1'b0 )begin
case ({J,K})
2'b00: Q <= Q;
2'b01: Q <= 1'b0;
2'b10: Q <= 1'b1;
2'b11: Q <= ~Q;
endcase
end
end
endmodule
TB:
module bcdTB();
logic clk,rst,Q0,Q1,Q2,Q3;
logic [3:0] out;
bcdCounter bcdCount(.clk(clk), .rst(rst), .Q0(Q0), .Q1(Q1), .Q2(Q2), .Q3(Q3),.out(out));
always #40 clk = ~clk;
initial begin
clk = 1'b0;
rst = 1'b0;
#2 rst = 1'b1;
#2 rst = 1'b0;
#1000
$finish;
end
endmodule
您有模拟竞争条件,因为您的代码没有遵循同步设计的推荐实践。您有 4 个时钟信号,但您应该只有一个。
我建议在更高的抽象级别设计计数器,用标准行为代码替换触发器实例:
module bcdCounter (
input logic clk,
input logic rst,
output logic Q0,
output logic Q1,
output logic Q2,
output logic Q3,
output logic [3:0] out
);
assign {Q3,Q2,Q1,Q0} = out;
always_ff @(negedge clk, posedge rst) begin
if (rst) begin
out <= 4'h0;
end else if (out == 9) begin
out <= 4'h0;
end else begin
out <= out + 1;
end
end
endmodule
输出: