如何在没有时钟的情况下生成上升沿来控制verilog中的移位寄存器?

时间:2014-03-29 19:57:50

标签: verilog shift-register

首先,让我解释一下我要做的事情。我使用的DE0有四个七段显示器。我的目标是生成一系列滚动显示的文本,文本字符串基于用户输入。用户有三个对应于A,B和C的按钮。

我已经能够创建一个"循环"在七段显示器上显示文本,但我在抓取用户输入时遇到困难。我的想法是使用一个9位移位寄存器,它接受用户输入并转移到链中的输入,可以这么说。

请注意,我对verilog不是很陌生,而且在编写代码时我仍然想弄清楚如何最好地考虑它。到目前为止,我发现最好用物理硬件来对其进行可视化。

那就是说,这就是我可视化的内容:

新输入=> Flip-Flop1 => FF2 => FF3 => FF4 => FF5 => FF6 => FF7 => FF8 =>丢弃旧输入

使用这个想法,我写了以下代码:

wire[1:0] oneFF, twoFF, threeFF, fourFF, fiveFF, sixFF, sevenFF, eightFF;
reg[1:0] change;
wire bA, bB, bC; //Detects change in user input - either 1 or 0
parameter A = 2'b00; parameter B = 2'b01; parameter C = 2'b10;


//They are declared as wires since they really only interconnect portions of
  the hardware

FF One(clk, change, oneFF);
FF Two(clk, oneFF, twoFF);
FF Three(clk, twoFF, threeFF);
FF Four(clk, threeFF, fourFF);
FF Five(clk, fourFF, fiveFF);
FF Six(clk, fiveFF, sixFF);
FF Seven(clk, sixFF, sevenFF);
FF Eight(clk, sevenFF, eightFF);

module FF(clk, in, out);
  input clk;
  input [1:0] in;
  output reg [1:0] out;
  reg [31:0] count;

  always @(posedge clk)
    begin
        count <= count + 1;
        if(count == 50000000) begin
        out <= in;
        count <= 0;
        end
    end
endmodule

然后我写了一个模块来检测change寄存器的输入:

always @(*)
    begin

        if(bA) begin
            change = A;

        end

        if(bB) begin
            change = B;

        end

        if(bC) begin
            change = C;

        end
    end

这是我遇到问题的地方。我可以按一个按钮,但第一个寄存器中的更改将通过链传播。显然,这是因为所有8个寄存器都连接到同一个时钟。此时钟以50mHz运行,因此它似乎立即发生。这就是为什么我通过module FF的柜台,所以我可以证实我的怀疑。

为了解决这个问题,我试图在一个位置进行更新&#34;更新&#34;在always块中尝试在每个输入处创建一个正边缘,但这不起作用。

例如:

  reg update;
  always @(*)
    begin
        update = 0;
        if(bA) begin
            change = A;
            update = ~update;
        end

        if(bB) begin
            update = ~update;
            change = B; 
        end

        if(bC) begin
            change = C;
            update = ~update;
        end
            update = 0;
    end

我还会相应地更改模块实例化。如果我将此块更改为非阻塞分配,也是如此。

我怀疑这个问题有一个非常简单的解决方案。基本上,我想要的就是产生这种效果

字符串初始化:_ _ _ _ _ ...

输入:A _ _ _ _ ...

下一个输入:B A _ _ _ ...

而不是

输入:A A A A A ...

下一个输入:B B B B B ...

赞赏任何有建设性的意见。

1 个答案:

答案 0 :(得分:3)

不要尝试从组合逻辑生成边沿或脉冲。你可以只使用时钟做你想做的事情,所以你应该坚持使用纯时钟逻辑。

如果要根据用户输入更改时生成更新选通信号,则存储按钮的先前值,并在按钮更改时生成更新。

wire bA;
reg  bA_q;
reg  update;

always @(posedge clk) begin
   bA_q <= bA;
end

always @* begin
   if(bA && !bA_q) begin
        change = A;
        update = 1'b1;
   end else begin
        update = 1'b0;
        change = 0; //this can be anything, just set it so you don't infer a latch
   end
end

这会在bA从0转换为1的任何时钟周期生成更新选通。

但是,根据您的FPGA,您可能需要去抖动按钮(某些fpga会自动执行此操作)。

如果您的按钮没有去抖动,按下它时可能会快速上下闪烁,这样在此电路中您反复按下该按钮几次。因此,您可以获得一次印刷的多个更新。这是一个非常常见的主题,如果您需要,我相信您可以找到有关如何去除按钮的其他资源。