2016-03-06 126 views
0

我想寫一個Verilog代碼做以下3項任務:如果右按鍵一次,Verilog代碼總是涉及塊

  1. LED將轉移到不斷向右
  2. 如果左按鈕被按下一次,LED將連續向左移動
  3. 在任何時候我想改變LED的方向(例如從右到左),我只需要按左鍵一次

我的代碼如下:

module moveled(input clk, input buttonright, input buttonleft, output [15:0]led); 

reg [15:0]led=16'b0000100000000000; 
wire slowclk; 
wire r; 
wire qr; 
wire l; 
wire ql; 


slowclock clk(clk, slowclk); 

pulse spR(clk,buttonright,r); 
pulse spL(clk,buttonleft,l); 
jkff jkR(r,r,clk,qr); 
jkff jkL(l,l,clk,ql); 

always @(posedge slowclk) 
begin 

    if(qr==1 && ql==0) 
    begin 
    led<=led>>1; 
    end 

    else if(qr==0 && ql==1) 
    begin 
    led<=led<<1; 
    end 

    else 
    led<=led; 
end  

endmodule 

慢時鐘模塊正在使led向左/向右移動,使其更易於觀察。脈衝模塊用於消除反彈。 2 jkff模塊是觸發器來切換qr和ql,使led可以連續向右/向左移動。我的代碼中的主要問題是在always塊中,當qr=1ql=1時代碼失敗。例如,如果qr=1,我的LED正在向右移動,並且我按下左側按鈕,使qr=1ql=1,led停止。當我嘗試再次按下左按鈕向左移動時,LED將移向右側,因爲ql=0qr=1。 if()中的靈敏度列表必須是qr==1 && ql==0否則led將移動到正確的非停止位置。

因此,如上所述,此代碼未能完成任務3。任何幫助將不勝感激。

+0

你希望如何從停止('11')切換到'01'狀態,即在qr按下時取消ql和斷言qr。目前它們互不影響。 – Morgan

+0

如果可能,我想避免(11)狀態,當它向右移動時應該是(01)狀態,並且在向左移動時應該是(10)狀態 – David

回答

0

假設你脈衝接通的電平的按鈕按壓的成單個1個時鐘寬度脈衝(邊緣檢測),那麼,你可以只具有:

NB:需要添加復位以設置狀態到S_IDLE要麼通過初始或低電平有效復位。

localparam S_IDLE = 2'b00; 
localparam S_RIGHT = 2'b10; 
localparam S_LEFT = 2'b01; 
localparam BOTH = 2'b11; 

reg [1:0] state; 
wire [1:0] next_state = {r,l};//bypass toggle flops 

always @(posedge slowclk) begin 
    case(next_state) 
    S_IDLE : state <= S_IDLE ; 
    S_RIGHT : state <= S_RIGHT; 
    S_LEFT : state <= S_LEFT ; 
    S_BOTH : state <= S_IDLE ; 
    endcase 
end 

//Outputs 
always @(posedge slowclk) begin 
    case(state) 
    S_IDLE : led <= led; 
    S_RIGHT : led <= led>>1; 
    S_LEFT : led <= led<<1; 
    default : led <= led; 
    endcase 
end