【问题标题】:Verilog code involving always blocks涉及 always 块的 Verilog 代码
【发布时间】:2016-03-06 09:27:56
【问题描述】:

我正在尝试编写一个verilog代码来完成以下3个任务:

  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

slowclock 模块使 LED 向右/向左移动更慢,以便更容易观察。脉冲模块用于消除去抖动。 2 jkff 模块是 t 触发器,用于切换 qr 和 ql 以使 LED 连续向右/向左移动。我的代码中的主要问题是始终块,当qr=1ql=1 时代码失败。例如,如果qr=1,我的 LED 向右移动,我按下左按钮,qr=1ql=1,LED 停止。当我再次尝试按下左键将 LED 向左移动时,LED 将改为向右移动,因为ql=0qr=1。 if() 中的敏感度列表必须是qr==1 &amp;&amp; ql==0 否则led 会不停地向右移动。

因此,此代码无法完成上述任务 3。任何帮助将不胜感激。

【问题讨论】:

  • 您希望它如何从停止 (11) 切换到 01 状态,即取消断言 ql 并在 qr 按下时断言 qr。目前它们互不影响。
  • 如果可能的话,我想避免一个(11)状态,向右移动应该是(01)状态,向左移动应该是(10)状态

标签: verilog


【解决方案1】:

假设您脉冲将按钮按下的电平转换为单个 1 个时钟宽度的脉冲(边缘检测),那么您可以:

注意:需要通过初始或低电平有效复位添加复位以将状态设置为 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 2013-07-02
    • 2019-11-27
    • 2014-11-10
    • 1970-01-01
    相关资源
    最近更新 更多