首先,让我解释一下我要做的事情。我使用的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 ...
赞赏任何有建设性的意见。
答案 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会自动执行此操作)。
如果您的按钮没有去抖动,按下它时可能会快速上下闪烁,这样在此电路中您反复按下该按钮几次。因此,您可以获得一次印刷的多个更新。这是一个非常常见的主题,如果您需要,我相信您可以找到有关如何去除按钮的其他资源。