放置30-574 IO引脚和BUFG之间的布线布局不良

时间:2015-04-20 00:06:53

标签: 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; //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只是找到。

1 个答案:

答案 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_detectedincr_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>

实际上,我已经写了两个版本。第二个试图模仿单稳态的行为,因此在检测到第一个低到高转换后,输入不会被采样一段特定的时间。

您将看到第二个版本产生的脉冲比第一个版本早得多,但它也容易出现故障作为有效的上升沿,如模拟中所示。我当时坚持使用第一个版本。