从第一个LED转换LED

时间:2015-03-25 04:49:29

标签: verilog

main.v

    `timescale 1ns / 1ps

module main(
    input reset,
    input clk, //50MHz
    output [6:0] led
    );
    reg [26:0] counter;
    reg trigger;
    reg [6:0] temp;
    initial begin
        temp <= 7'b0000001;
    end

    always @ (posedge clk, posedge reset) begin
        if (reset == 1'b1) begin
            temp <= 7'b0000001;
        end

        else begin
            counter <= counter + 1;
        end
    end

    always @ (counter) begin
        if (counter == 26'd50000000)begin //1Hz
            trigger <= ~trigger;
            counter <= 26'd0;
        end

    end

    always @ (trigger) begin
        temp <= (temp == 7'b1000000) ? 7'b0000001 :
                (temp == 7'b0000001) ? 7'b0000010 :
                (temp == 7'b0000010) ? 7'b0000100 :
                (temp == 7'b0000100) ? 7'b0001000 :
                (temp == 7'b0001000) ? 7'b0010000 :
                (temp == 7'b0010000) ? 7'b0100000 :
                (temp == 7'b0100000) ? 7'b1000000 : 7'b0000000;

    end
    assign led = temp; 
endmodule

LED不动。它永远停留在第一个LED上。它是不起作用的触发器还是我误解了计数器?

这是工作代码。我不知道为什么我必须使用if语句,但它有效。

`timescale 1ns / 1ps

module main(
    input reset,
    input clk, //50MHz
    output [6:0] led
    );
    reg [26:0] counter;
    reg trigger;
    reg [6:0] temp;

    always @ (posedge clk, posedge reset) begin
        if (reset == 1'b1) begin
            counter <= 'b0;
            trigger <= 'b0;
        end
        else begin
           if (counter == 26'd50000000)begin //1Hz
              trigger <= ~trigger;
              counter <= 26'd0;
           end
           else begin
              counter <= counter + 1;
           end
        end
    end

    always @ (posedge trigger, posedge reset) begin
            if (reset == 1'b1) begin
                temp <= 7'd0;
            end
            else begin

            if (temp == 7'b1000000) begin
                temp = 7'b0000001;
            end

            else if (temp == 7'b0000001) begin
                temp = 7'b0000010;
            end

            else if (temp == 7'b0000010) begin
                temp = 7'b0000100;
            end

            else if (temp == 7'b0000100) begin
                temp = 7'b0001000;
            end

            else if (temp == 7'b0001000) begin
                temp = 7'b0010000;
            end                        

            else if (temp == 7'b0010000) begin
                temp = 7'b0100000;
            end

            else if (temp == 7'b0100000) begin
                temp = 7'b1000000;
            end                        

            else begin
                temp = 7'b0000001;
            end
            trigger <= 'b0;
            end
        end
    assign led = temp; 
endmodule

2 个答案:

答案 0 :(得分:1)

FPGA的触发器的一般结构是使用初始设置默认值,或者使用ASIC进行异步复位。

看代码发挥:

initial begin
    temp <= 7'b0000001;
end

always @ (posedge clk, posedge reset) begin
    if (reset == 1'b1) begin
        temp <= 7'b0000001;
    end

    else begin
        counter <= counter + 1;
    end
end

我们有临时为异步重置和初始值分配的值,而计数器永远不会被初始化。使用异步重置创建flip_flop的更标准方法是:

always @ (posedge clk, posedge reset) begin
    if (reset == 1'b1) begin
        counter <= 'b0;
    end
    else begin
        counter <= counter + 1;
    end
end

第2部分

下一段代码是:

always @ (counter) begin
    if (counter == 26'd50000000)begin //1Hz
        trigger <= ~trigger;
        counter <= 26'd0;
    end
end

这有一个在计数器上触发的手动灵敏度列表,最佳做法是使用always @*的自动灵敏度列表。这也是一个组合块,因此它应该使用阻塞分配(=)。

在verilog中,不应为变量分配多个块的值,因为计数器在此处。例外情况是使用初始块作为默认值。

组合块不保持状态,并且此块仅更改特定计数的值。暗示触发器将保持其值,这将意味着一个锁存器。意外隐含的锁存器可能会引起很多问题,因为这是一个比这里讨论的更大的话题。

请考虑改为:

always @ (posedge clk, posedge reset) begin
    if (reset == 1'b1) begin
        counter <= 'b0;
        trigger <= 'b0;
    end
    else begin
       if (counter == 26'd50000000)begin //1Hz
          trigger <= ~trigger;
          counter <= 26'd0;
       end
       else begin
          counter <= counter + 1;
       end
    end
end

第3部分

您的最后一段代码再次是手动敏感度列表:

 always @ (trigger) begin

这不是边缘触发,因此是组合部分。组合循环是输出本身的函数。 temp = some function of temp

看起来你真的想让它成为触发器正边缘更新的触发器:

<强>更新 我还注意到你使用了一个小于或等于,这在这种情况下不起作用,因为你的数字最多。

always @ (posedge trigger, posedge reset) begin
    if (reset == 1'b1) begin
        temp <= 'b0;
    end
    else begin
    temp <= (temp == 7'b1000000) ? 7'b0000001 : // <= changed to  ==
            (temp <= 7'b0000001) ? 7'b0000010 :
            (temp <= 7'b0000010) ? 7'b0000100 :
            (temp <= 7'b0000100) ? 7'b0001000 :
            (temp <= 7'b0001000) ? 7'b0010000 :
            (temp <= 7'b0010000) ? 7'b0100000 :
            (temp <= 7'b0100000) ? 7'b1000000 : 7'b0000000;
    end
end

答案 1 :(得分:0)

如果要将触发器用作异步时钟分频器,则需要使用T-FF而不是D-FF。使用异步生成的时钟并不是一种好的方式。不再需要对din的反馈。

您的FSM永远不会达到b00000100,因为没有转换。请检查您的“nextstage”编码。这也应该是循环错误的原因。