0

首先,让我解释一下我要做什么。我正在使用具有四个七段显示器的 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

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

为了解决这个问题,我尝试在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 _ _ _ _ ...

下一个输入:BA _ _ _ ...

代替

输入: AAAA ...

下一个输入:BBBBB ...

任何建设性的意见表示赞赏。

4

1 回答 1

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 会自动执行此操作)。

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

于 2014-03-29T20:21:46.570 回答