我正在使用FPGA(BEMICROMAX10)在面包板上使用七段显示器创建数字时钟,并且我有问题让秒数正好计算1秒。我使用的时钟系统输入为50 MHz。我要将相关代码发布到秒。我用来确定N的等式是(1/50000000)* 2 ^ N = 1,这给了我25.58,所以当我使用26时,它只是一点点慢,而当我把它变成25时,它就是&#39有点太快了。任何想法如何纠正这个?
谢谢
module digital_clock(clk, segsec);
input clk;
output [13:0] segsec;
parameter N = 25;
reg [N-1:0] slow_clk = 0;
reg [7:0] countsec = 0;
always @ (posedge clk)
slow_clk <= slow_clk + 1'b1;
always @ (posedge slow_clk[N-1])
if (countsec == 8'b00111011) countsec <= 8'b0;
else countsec <= countsec + 8'b1;
assign segsec = (countsec == 8'h0 ) ? 16'b01111110111111:
(countsec == 8'h1) ? 16'b01111110000110: //1 0000110 0111111
(countsec == 8'h2) ? 16'b01111111011011: //2 1011011
(countsec == 8'h3) ? 16'b01111111001111: //3 1001111
(countsec == 8'h4) ? 16'b01111111100110: //4 1100110
(countsec == 8'h5) ? 16'b01111111101101: //5 1101101
(countsec == 8'h6) ? 16'b01111111111101: //6 1111101
(countsec == 8'h7) ? 16'b01111110000111: //7 0000111
(countsec == 8'h8) ? 16'b01111111111111: //8 1111111
(countsec == 8'h9) ? 16'b01111111101111: //9 1101111
(countsec == 8'ha) ? 16'b00001100111111: //10
(countsec == 8'hb) ? 16'b00001100000110://11
(countsec == 8'hc) ? 16'b00001101011011://12
(countsec == 8'hd) ? 16'b00001101001111://13
(countsec == 8'he) ? 16'b00001101100110: //14
(countsec == 8'hf) ? 16'b00001101101101: //15
(countsec == 8'h10) ? 16'b00001101111101://16
(countsec == 8'h11) ? 16'b00001100000111://17
(countsec == 8'h12) ? 16'b00001101111111://18
(countsec == 8'h13) ? 16'b00001101101111://19
(countsec == 8'h14) ? 16'b10110110111111://20
(countsec == 8'h15) ? 16'b10110110000110://21
(countsec == 8'h16) ? 16'b10110111011011://22
(countsec == 8'h17) ? 16'b10110111001111://23
(countsec == 8'h18) ? 16'b10110111100110://24
(countsec == 8'h19) ? 16'b10110111101101://25
(countsec == 8'h1a) ? 16'b10110111111101://26
(countsec == 8'h1b) ? 16'b10110110000111://27
(countsec == 8'h1c) ? 16'b10110111111111://28
(countsec == 8'h1d) ? 16'b10110111101111://29
(countsec == 8'h1e) ? 16'b10011110111111://30
(countsec == 8'h1f) ? 16'b10011110000110://31
(countsec == 8'h20) ? 16'b10011111011011://32
(countsec == 8'h21) ? 16'b10011111001111://33
(countsec == 8'h22) ? 16'b10011111100110://34
(countsec == 8'h23) ? 16'b10011111101101://35
(countsec == 8'h24) ? 16'b10011111111101://36
(countsec == 8'h25) ? 16'b10011110000111://37
(countsec == 8'h26) ? 16'b10011111111111://38
(countsec == 8'h27) ? 16'b10011111101111://39
(countsec == 8'h28) ? 16'b11001100111111://40
(countsec == 8'h29) ? 16'b11001100000110://41
(countsec == 8'h2a) ? 16'b11001101011011://42
(countsec == 8'h2b) ? 16'b11001101001111://43
(countsec == 8'h2c) ? 16'b11001101100110://44
(countsec == 8'h2d) ? 16'b11001101101101://45
(countsec == 8'h2e) ? 16'b11001101111101://46
(countsec == 8'h2f) ? 16'b11001100000111://47
(countsec == 8'h30) ? 16'b11001101111111://48
(countsec == 8'h31) ? 16'b11001101101111://49
(countsec == 8'h32) ? 16'b11011010111111://50
(countsec == 8'h33) ? 16'b11011010000110://51
(countsec == 8'h34) ? 16'b11011011011011://52
(countsec == 8'h35) ? 16'b11011011001111://53
(countsec == 8'h36) ? 16'b11011011100110://54
(countsec == 8'h37) ? 16'b11011011101101://55
(countsec == 8'h38) ? 16'b11011011111101://56
(countsec == 8'h39) ? 16'b11011010000111://57
(countsec == 8'h3a) ? 16'b11011011111111://58
(countsec == 8'h3b) ? 16'b11011011101111://59
16'b01111110111111;
endmodule
答案 0 :(得分:2)
一般来说,有三种方法可以解决这个问题:
使用具有更合适频率的单独时钟源(例如,1.048576 MHz = 2 20 Hz)。您正在使用的电路板似乎没有任何时钟晶振插座,但您可能会将其中一个连接到一个GPIO引脚。
使用FPGA中的一个PLL将50 MHz时钟转换为适当的频率。有关详细信息,请参阅MAX 10 Clocking and PLL User Guide。
使用相位累加器生成1 PPS(每秒脉冲数)信号:
reg [25:0] accum = 0;
wire pps = (accum == 0);
always @(posedge clk) begin
accum <= (pps ? 50_000_000 : accum) - 1;
if (pps) begin
… things to do once per second …
end
end
该架构对所有逻辑使用单个时钟信号,而不是从组合逻辑生成单独的较慢时钟。 (由于各种原因,你最好尽可能少地使用不同的时钟。)
答案 1 :(得分:0)
您的等式已经能够计算您的计数器所需的位数;在这种情况下,您需要一个26位计数器。但是一个计数器可以包裹你喜欢的任何值;它并不需要在所有的环绕中包裹。你已经知道了,因为你的另一个计数器已经有逻辑使它在8&#39; b00111011(59)处回绕。所以,改变这个:
always @ (posedge clk)
slow_clk <= slow_clk + 1'b1;
到此:
always @ (posedge clk)
if (slow_clk == 26'd49999999) slow_clk <= 8'b0;
else slow_clk <= slow_clk + 8'b1;
我还注意到你的计数器只有25位。这样:
parameter N = 25;
应该是这样的:
parameter N = 26;
然而,正如您在上一个问题中提到的那样,您有一个派生时钟。你在这里不需要派生时钟,如果可以,你应该总是避免使用派生时钟。衍生时钟不是同步设计,因此除非您知道自己在做什么,否则会导致大问题。因此,请不要使用always
为您的第二个slow_clk[N-1]
阻止时钟,使用clk
计时,并使用slow_clk[N-1]
作为启用信号。不要这样做:
always @ (posedge slow_clk[N-1])
if (countsec == 8'b00111011) countsec <= 8'b0;
else countsec <= countsec + 8'b1;
这样做:
assign enable = (slow_clk == 26'd49999999);
always @ (posedge clk)
if (enable == 1'b1)
if (countsec == 8'b00111011) countsec <= 8'b0;
else countsec <= countsec + 8'b1;
这是EDA Playground上的一个版本(加速因子为1000000 ):