我想做一个具有输出使能的向上计数器(当为高电平时,向上计数器应该在每个时钟周期向上计数,否则它将保持其先前的值)。为了在我的 Altera TerASIC 板上获得可见的结果,我使用了它的板载时钟发生器,并在 Verilog 中内置了一个时钟分频器模块,以便为我的向上计数器提供一个频率更合适的时钟。此外,我创建了一个十六进制模块,将其连接到向上计数器输出,以便能够以数字形式查看输出值。 问题是,我不知道为什么在 TeraASIC 板上运行设计时,输出每个时钟周期都会增加 2(而不是预期的 1)。我提供了下面的完整代码,因为我不知道问题源于何处。尽管如此,我相信十六进制模块完全没问题。问题发生在计数器块内或除法器块内。 此外,我做了一个小测试台,其结果很奇怪,因为它们证实了电路工作正常。我在这篇文章的底部详细介绍了测试平台。 然而,有趣的是,如果我用一个不考虑 en 和 d 信号的简单 else 替换计数器中的 else if,我会得到一个完整的功能设计,一个简单的向上计数器,它在每个时钟沿后递增其值。我不知道为什么会发生这种情况。也许真正的问题就隐藏在那里。我在该代码区域中添加了注释,以便更加明显。
module counter(
input clk,
input rst_b,
input en,
input [2:0] d,
output [6:0] digit
);
wire clk_d;
reg [2:0] q;
divider i0(.clk(clk),.rst_b(rst_b),.clk_d(clk_d));
decoder i1(.binary(q),.digit(digit));
always @(posedge clk_d, negedge rst_b) begin
if(rst_b == 1'b0)
q <= 3'b000;
else if(en)//when it was only else q<=q+en; it went fine...why???
if(q == d)
q <= 3'b000;
else
q <= q + en;//increment by 2 instead of 1
end
endmodule
module divider(
input clk,
input rst_b,
output clk_d
);
reg [24:0] q;
always @(posedge clk) begin
if(rst_b == 1'b0)
q <= 25'b0;
else
q <= q-1;
end
assign clk_d = (q == 25'b0);
endmodule
module decoder(
input [2:0] binary,
output reg [6:0] digit
);
always @ * begin
case (binary)
4'h0: digit = ~7'b0111111;
4'h1: digit = ~7'b0000110;
4'h2: digit = ~7'b1011011;
4'h3: digit = ~7'b1001111;
4'h4: digit = ~7'b1100110;
4'h5: digit = ~7'b1101101;
4'h6: digit = ~7'b1111101;
4'h7: digit = ~7'b0000111;
default : digit = ~7'b1110001;
endcase
end
endmodule
我得到了一个小测试平台,它令人惊讶地证明至少在理论上我的模块工作得很好:
module counter_tb;
reg clk, rst_b, en;
reg [2:0] d;
wire [6:0] digit;
counter i0( .clk(clk),
.rst_b(rst_b),
.en(en),
.d(d),
.digit(digit)
);
always begin
#1 clk = ~clk;
end
initial begin
clk = 1'b0;
en = 1'b1;
d = 3'b111;
rst_b = 1'b0;
#3 rst_b = 1'b1;
end
endmodule
我不知道您的问题是什么或解决方法是什么,但是您使用的设计实践通常不适用于创建时钟的综合流程(针对硬件)。如果它在一个构建中有效,那么在下一个构建中可能就不起作用了。一点额外的延迟(例如添加启用)将在硬件中产生完全不同的结果。
这种做法是欺骗性的,因为您可以编写一些在模拟中表现如您所愿的东西,但在综合/硬件工作流程中却不会按预期表现。 Verilog模拟器通常不会对延迟进行建模(基于延迟的仿真是可能的,但仍然不能解决问题),因此必须使用某些良好的设计实践来使硬件结果与仿真一致。
您通常不能创建时钟并将其用作其他触发器的时钟,在物理 FPGA 中使用简单的触发器分频器。有两个可靠的选项可以获取与生成较慢时钟相关的行为。
这个链接解释了更多,写得很好,我无法解释得更好
在 FPGA 上的 RTL 中使用触发器的时钟分频器 – 绝对不行!
无需写论文。
这将是一个单独的新问题和答案
“如何在 FPGA 中创建一个可以针对综合工作流程中的硬件的时钟分频器”
如果触发器除法器
assign clk_d = (q == 25'b0);
及其相关逻辑并使用我提到的两个解决方案之一,并在提供的链接中提到,我会摆脱它。
此外,如果您将 RTL 代码部署到实验室而不使用测试平台进行模拟,那么您通常会看到一个黑匣子,上面写着“它不起作用”