Verilog 在IO引脚和BUFG之间布线时放置30-574不良位置 `时间刻度为1ns/1ps 模块秒表( 输入时钟, 输入复位, 投入增量, 输入启动, 输出[6:0]分段, 输出dp, 输出[3:0]an ); reg[3:0]reg_d0、reg_d1、reg_d2、reg_d3//保存单个计数的寄存器 注册[22:0]股票代码; 线击; //mod 1kHz时钟以每0.001秒产生一次滴答声 始终@(posedge(时钟)或posedge(重置)) 开始 如果(重置) 开始 ticker
我认为问题与代码的这一部分有关:Verilog 在IO引脚和BUFG之间布线时放置30-574不良位置 `时间刻度为1ns/1ps 模块秒表( 输入时钟, 输入复位, 投入增量, 输入启动, 输出[6:0]分段, 输出dp, 输出[3:0]an ); reg[3:0]reg_d0、reg_d1、reg_d2、reg_d3//保存单个计数的寄存器 注册[22:0]股票代码; 线击; //mod 1kHz时钟以每0.001秒产生一次滴答声 始终@(posedge(时钟)或posedge(重置)) 开始 如果(重置) 开始 ticker,verilog,Verilog,我认为问题与代码的这一部分有关: `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; //regis
`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
基本上,您使用的是一个输入信号作为时钟,在为FPGA设计时,这是完全不鼓励的。P&R尝试将IO
引脚重新路由到FPGA内部的BUFG
(全局缓冲区),以便将其用作时钟
对于FPGA设计,您应该为所有always@(posedge…
构造使用一个时钟信号,并使用输入信号有条件地加载/更新寄存器
为此,您必须首先将增量
信号与时钟
同步,以避免亚稳态问题:
always @ (posedge (increment))
begin
if (reg_d3 == 9)
inc_temp = 0;
else
inc_temp = reg_d3 + 1;
end
为了检测有效的上升沿,我们存储了increment\u synched
的最后16个值的历史记录。当产生从0到1的有效稳定变化时,历史模式将匹配模式0011111111
。然后,也只有在那时,我们通过将incr\u detected
提高到1来发出信号。在下一个时钟周期,历史模式将与上述序列不匹配,并且检测到的增量将再次降至0
在此之前,连接到的按钮increment
中的多次反弹将导致许多转换,从而导致许多增量。使用这样的模式匹配可以消除由多次反弹引起的故障。使用1Khz时钟,这种模式应该足够了
现在,您可以在原始代码中使用incr\u detected
,incr\u detected
将在一个clk
周期内为1
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
可以使用以下模拟来测试这些添加:
您将看到有一个模块,它从外部接收增量
输入信号,并在输入信号从低电平最终转换为高电平时生成一个无故障的单周期脉冲
事实上,我已经写了两个版本。第二种方法试图模仿单稳态的行为,因此在检测到第一次从低到高的转变后的特定时间段内不会对输入进行采样
您将看到,第二个版本比第一个版本产生脉冲快得多,但它也容易将小故障视为有效的上升沿,如模拟中所示。我会坚持第一个版本
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
always @ (posedge clk) begin
if (incr_detected) begin
if (reg_d3 == 9)
inc_temp = 0;
else
inc_temp = reg_d3 + 1;
end
end