`timescale 1ns / 1ps
module stopwatch(
input clock,
input reset,
input increment,
input start,
output [6:0] seg,
output dp,
output [3:0] an
);
reg [3:0] reg_d0, reg_d1, reg_d2, reg_d3; //registers that will hold the individual counts
reg [22:0] ticker;
wire click;
//the mod 1kHz clock to generate a tick ever 0.001 second
always @ (posedge (clock) or posedge (reset))
begin
if(reset)
begin
ticker <= 0;
end
else
begin
if (start)
begin
if(ticker == (100000 - 1)) //if it reaches the desired max value reset it
ticker <= 0;
else if (increment)
ticker <= ticker;
else
ticker <= ticker + 1;
end
end
end
//increment a second everytime rising edge of down button
reg [3:0] inc_temp;
always @ (posedge (increment))
begin
if (reg_d3 == 9)
inc_temp = 0;
else
inc_temp = reg_d3 + 1;
end
assign click = ((ticker == (100000 - 1))?1'b1:1'b0); //click to be assigned high every 0.001 second
//update data start from here
always @ (posedge (clock) or posedge (reset))
begin
if(reset)
begin
reg_d0 <= 0;
reg_d1 <= 0;
reg_d2 <= 0;
reg_d3 <= 0;
end
else
begin
if (increment)
begin
reg_d3 <= inc_temp;
reg_d0 <= reg_d0;
reg_d1 <= reg_d1;
reg_d2 <= reg_d2;
end
else if (click) //increment at every click
begin
if(reg_d0 == 9) //xxx9 - 1th milisecond
begin
reg_d0 <= 0;
if (reg_d1 == 9) //xx99 - 10th milisecond
begin
reg_d1 <= 0;
if (reg_d2 == 9) //x999 - 100th milisecond
begin
reg_d2 <= 0;
if(reg_d3 == 9) //9999 - The second digit
reg_d3 <= 0;
else
reg_d3 <= reg_d3 + 1;
end
else
reg_d2 <= reg_d2 + 1;
end
else
reg_d1 <= reg_d1 + 1;
end
else
reg_d0 <= reg_d0 + 1;
end
else
begin
reg_d3 <= reg_d3;
reg_d0 <= reg_d0;
reg_d1 <= reg_d1;
reg_d2 <= reg_d2;
end
end
end
//Mux for display 4 7segs LEDs
localparam N = 18;
reg [N-1:0]count;
always @ (posedge clock or posedge reset)
begin
if (reset)
count <= 0;
else
count <= count + 1;
end
reg [6:0]sseg;
reg [3:0]an_temp;
reg reg_dp;
always @ (*)
begin
case(count[N-1:N-2])
2'b00 :
begin
sseg = reg_d0;
an_temp = 4'b1110;
reg_dp = 1'b1;
end
2'b01:
begin
sseg = reg_d1;
an_temp = 4'b1101;
reg_dp = 1'b0;
end
2'b10:
begin
sseg = reg_d2;
an_temp = 4'b1011;
reg_dp = 1'b1;
end
2'b11:
begin
sseg = reg_d3;
an_temp = 4'b0111;
reg_dp = 1'b0;
end
endcase
end
assign an = an_temp;
//update the data to display to LEDs
reg [6:0] sseg_temp;
always @ (*)
begin
case(sseg)
4'd0 : sseg_temp = 7'b1000000;
4'd1 : sseg_temp = 7'b1111001;
4'd2 : sseg_temp = 7'b0100100;
4'd3 : sseg_temp = 7'b0110000;
4'd4 : sseg_temp = 7'b0011001;
4'd5 : sseg_temp = 7'b0010010;
4'd6 : sseg_temp = 7'b0000010;
4'd7 : sseg_temp = 7'b1111000;
4'd8 : sseg_temp = 7'b0000000;
4'd9 : sseg_temp = 7'b0010000;
default : sseg_temp = 7'b0111111; //dash
endcase
end
assign seg = sseg_temp;
assign dp = reg_dp;
endmodule
我试图设计一个秒表,但我仍然坚持增量。目的是当我按下increment
(按钮)时,reg_d3
将递增1并保持其状态直到按钮被释放。我可以在按下按钮时停止闹钟,但我无法更新reg_d3
。我总是收到
[放置30-574] IO引脚和BUFG之间的布线布局不良
我不知道为什么;我在clkdivider中使用increment只是找到。
答案 0 :(得分:2)
我认为问题与代码的这一部分有关:
always @ (posedge (increment))
begin
if (reg_d3 == 9)
inc_temp = 0;
else
inc_temp = reg_d3 + 1;
end
您基本上使用输入信号作为时钟,在设计FPGA时完全不鼓励这样做。 P&amp; R尝试将IO
引脚重新路由到FPGA内部的BUFG
(全局缓冲区),以便将其用作时钟。
对于FPGA设计,您应该为所有always @(posedge...)
结构使用一个时钟信号,并使用输入信号有条件地加载/更新寄存器。
为此,您首先要将increment
信号与clk
同步,以避免亚稳态问题:
reg incr1=1'b0, incr2=1'b0;
always @(posedge clk) begin
incr1 <= increment;
incr2 <= incr1;
end
wire increment_synched = incr2;
然后,去毛刺increment_synched
并检测其中的上升沿:
reg [15:0] incrhistory = 16'h0000;
reg incr_detected = 1'b0;
always @(posedge clk) begin
incrhistory <= { incrhistory[14:0] , increment_synched };
if (incrhistory == 16'b0011111111111111)
incr_detected <= 1'b1;
else
incr_detected <= 1'b0;
end
为了检测有效的上升沿,我们存储了increment_synched
的最后16个值的历史记录。当产生从0到1的有效稳定变化时,历史模式将匹配模式0011111111111111
。然后,只有这样,我们通过将incr_detected
提升到1来发出信号。下一个时钟周期,历史模式不会与上述序列匹配,incr_detected
将再次降为0。
在此之前,连接按钮increment
中的多次跳转会导致许多转换,从而导致许多增量。使用类似的模式匹配消除了由多次反弹引起的毛刺。你似乎使用1Khz时钟,这个模式应该足够了。
现在,您可以在原始代码中使用incr_detected
,incr_detected
只需1个clk
周期。
always @ (posedge clk) begin
if (incr_detected) begin
if (reg_d3 == 9)
inc_temp = 0;
else
inc_temp = reg_d3 + 1;
end
end
您可以使用以下模拟测试这些添加: http://www.edaplayground.com/x/AQY
您将看到有一个模块从外部接收您的increment
输入信号,并在输入信号从低电平到最高电平的最终转换时产生无毛刺的单周期脉冲。 / p>
实际上,我已经写了两个版本。第二个试图模仿单稳态的行为,因此在检测到第一个低到高转换后,输入不会被采样一段特定的时间。
您将看到第二个版本产生的脉冲比第一个版本早得多,但它也容易出现故障作为有效的上升沿,如模拟中所示。我当时坚持使用第一个版本。