我正在尝试编写一个滚动移位/环形计数器,它将两个开关作为verilog中的时钟.
我的代码如下:
module roll(CLK1, CLK2, LEDS);
input CLK1;
input CLK2;
output [3:0] LEDS;
reg [3:0] LEDS;
initial
begin
LEDS = 4'b0001;
end
always@(posedge CLK1 or posedge CLK2)
begin
if(CLK1)
begin
LEDS[3]<=LEDS[2];
LEDS[2]<=LEDS[1];
LEDS[1]<=LEDS[0];
LEDS[0]<=LEDS[3];
end
// Roll Right
if(CLK2)
begin
LEDS[3]<=LEDS[0];
LEDS[2]<=LEDS[3];
LEDS[1]<=LEDS[2];
LEDS[0]<=LEDS[1];
end
end
endmodule
Run Code Online (Sandbox Code Playgroud)
我尝试使用两个always块,但后来发现我不能这样做.当我posedge CLK2在always声明中,我的FPGA上的LED都保持不变.
记住Verilog不是一种编程语言,它是一种硬件描述语言.
在编写合成代码时,只有编写可以使用实际门实例化的代码,才能获得成功.因此,除非对两个信号之一的响应具有RESET或PRESET操作的效果,否则不能合成写入对两个不同信号的边缘敏感的始终块.
您的代码在逻辑上也不会执行您想要的操作.如果在CLK1已经为高电平时CLK2存在上升沿(或反之亦然),请考虑代码所说的内容.您的灯将向左滚动,然后立即向右滚动增益,导致无变化.
更常见的方法是使时钟运行速度比预期UP和DOWN输入更快,并使用它来驱动逻辑.例如
module roller(input clk, input rst, input UP, input DOWN, output reg LEDS[3:0]);
reg UP1, DOWN1;
always @(posedge clk or posedge rst)
if (rst) begin
LEDS[3:0] <= 4'b0001;
end
else
begin
UP1 <= UP;
DOWN1 <= DOWN;
if (UP & ~UP1) begin
LEDS[3:0] <= {LEDS[2:0], LEDS[3]};
end
else if (DOWN & ~DOWN1) begin
LEDS[3:0] <= {LEDS[0], LEDS[3:1]};
end
end
endmodule;
Run Code Online (Sandbox Code Playgroud)
请注意,这优先于UP.如果UP和DOWN都被置位,则模式将"向上"而不是向下滚动.如果您想要不同的行为,则必须修改代码才能实现它.