(4)8個led每0.5s閃爍(跑馬燈)

数字ic新人發表於2024-04-03

設計思路:

設計程式碼:

module led_run(
    clk,rst,led
    );
    
    input clk,rst;
    output reg [7:0] led = 8'b0000_0001;
    reg [24:0] cnt;
    
    parameter TIME = 24_999_999;
    always@(posedge clk or negedge rst)
        if(!rst)
            cnt <= 0;
        else if (cnt == TIME)
            cnt <= 0;
        else cnt <= cnt + 1;
        
    //透過移位實現
    always@(posedge clk or negedge rst)
        if(!rst)
            led <= 8'b0000_0001;
        else if(cnt == TIME)
            begin
                if(led == 8'b1000_0000)
                    led <=  8'b0000_0001;
                else
                    led <= (led<<1);    //led每0.5s左移一次
            end
        else
            led <= led;

endmodule

驗證tb:

`timescale 1ns / 1ps

module led_run_tb();

reg clk,rst;
wire [7:0] led;

led_run u_led_run(
    .clk(clk),
    .rst(rst),
    .led(led)
    );

initial clk = 1;
always #10 clk = ~clk;

initial begin
rst = 0;
#201;   //錯開時鐘邊沿
rst = 1;
#5_000_000_000;//8個led,每個0.5s 
$stop;

end endmodule

波形驗證:

  注:為了提高設計開發效率,在模擬驗證的時候沒必要真的用0.5s跑,比如本設計在實現時設定為500us,這樣可以節省時間。

模擬結果:

  可以觀察到8個led依次閃爍,證明設計符合要求。


方法二:

  直接用程式碼

led <= {led[6:0],led[7]};

就可以省略兩個巢狀if的判斷。


方法三:

  使用上一節提到的38譯碼器完成設計,具體程式碼如下:

  這裡注意兩點:

  1.   這裡是將cnt設定為3位,然後呼叫底層模組,所以要注意這裡的例化格式
  2.   由於在底層模組已經對reg out 了,因此這裡的led就不能再reg了,要把上面的reg刪掉!!

相關文章