實驗一:讓一個燈亮0.25s,滅0.75s,迴圈
always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == 49_999_999) cnt <= 0; else cnt <= cnt + 1; always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (cnt == 37_499_999) //滅0.75s,即計數到0.75/(20*10e-9)-1 led <= 1; else if (cnt == 49_999_999) led <= 0; //亮0.25s
實驗二:亮0.25s,滅0.5s,亮0.75s,滅1s的狀態迴圈
parameter max = 125_000_000; //2.5s為一個週期 reg [26:0] cnt; always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == 49_999_999) cnt <= 0; else cnt <= cnt + 1; always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (cnt == max/5-1) //0.5s, led <= 1; else if (cnt == max/2-1) //0.5s 0.75s led <= 0; else if (cnt == max*9/10-1) //0.5s 0.75s 1s led <= 1; else if (cnt == max) //0.5s 0.75s 1s 0.25s led <= 0;
和實驗一的思路差不多,不過這裡我和影片寫的不一樣,對於第三個else if括號裡的不太確定,也沒用tb模擬
實驗三:led按指定亮滅模式執行,模式未知,由使用者給定,以0.25s為一個狀態,8個狀態為一個迴圈。
//2s為一個實驗週期,有一個輸入埠 parameter max = 100_000_000; //2s為一個週期 input [7:0] ctrl; //輸入埠 reg [26:0] cnt; always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == 49_999_999) cnt <= 0; else cnt <= cnt + 1; always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (cnt == max/8-1) //0.25s, led <= ctrl[0]; else if (cnt == max*2/8-1) // led <= ctrl[1]; else if (cnt == max*3/8-1) // led <= ctrl[2]; .......//後面懶得寫了
當然,還有一種方法:
實驗三:led按指定亮滅模式執行,模式未知,由使用者給定,8個狀態為一個迴圈,每個狀態的時間可自定義。
input [7:0] ctrl; //輸入埠
input [31:0] time; //輸入時間埠
reg [26:0] cnt;
reg [2:0] counter = 0; //八個狀態
//設計思路:每計滿一個小狀態,counter+1,然後根據counter的值去 //選擇led的電平 always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (cnt == time-1) cnt <= 0; else cnt <= cnt + 1; always@(posedge clk or negedge rst) if(!rst) counter <= 0; else if (cnt == time-1) counter <= counter + 1;
always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (counter == 0) // led <= ctrl[0]; else if (counter == 1) // led <= ctrl[1]; else if (counter == 2) // led <= ctrl[2]; .......//後面懶得寫了
實驗四:多個led各自在不同的模式下迴圈閃爍
差不多就是這樣的思路:
實驗五:每隔10ms讓led的8個狀態迴圈執行一次
設計思路:
程式碼:
input [7:0] ctrl; //輸入埠 reg [26:0] cnt; reg [26:0] cnt1; reg [31:0] time; reg [2:0] counter = 0; //八個狀態 reg en; //計滿一個小狀態 always@(posedge clk or negedge rst) if(!rst) cnt <= 0; else if (en) begin if (cnt == time-1) cnt <= cnt + 1; end else cnt <= cnt + 1; //計滿10ms always@(posedge clk or negedge rst) if(!rst) cnt1 <= 0; else if (cnt == 500000-1) cnt1 <= 0; else cnt1 <= cnt1 + 1; //狀態切換 always@(posedge clk or negedge rst) if(!rst) counter <= 0; else if(en) begin if (cnt == time-1) counter <= counter +1; end else counter <= 0; //使能控制,cnt1為0(即新的10ms開始)時拉高,8個狀態完成後拉低 always@(posedge clk or negedge rst) if(!rst) en <= 0; else if (cnt1 == 0) en <= 1; else if(counter == 7) en <= 0; always@(posedge clk or negedge rst) if(!rst) led <= 0; else if (counter == 0) // led <= ctrl[0]; else if (counter == 1) // led <= ctrl[1]; else if (counter == 2) // led <= ctrl[2]; .......//後面懶得寫了
注意的是,只有在en使能的情況下,計一個小狀態的計數和狀態切換的計數才能夠計數,否則需要暫停