2016-03-06 55 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