(6)從計數器到可控線性序列機——led實驗六部曲

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

實驗一:讓一個燈亮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使能的情況下,計一個小狀態的計數和狀態切換的計數才能夠計數,否則需要暫停

相關文章