設計思路:
設計程式碼:
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譯碼器完成設計,具體程式碼如下:
這裡注意兩點:
- 這裡是將cnt設定為3位,然後呼叫底層模組,所以要注意這裡的例化格式
- 由於在底層模組已經對reg out 了,因此這裡的led就不能再reg了,要把上面的reg刪掉!!