从第一个 LED 移动 LED
Shifting LED from first LED
main.v
`timescale 1ns / 1ps
module main(
input reset,
input clk, //50MHz
output [6:0] led
);
reg [26:0] counter;
reg trigger;
reg [6:0] temp;
initial begin
temp <= 7'b0000001;
end
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'b0000001;
end
else begin
counter <= counter + 1;
end
end
always @ (counter) begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
end
always @ (trigger) begin
temp <= (temp == 7'b1000000) ? 7'b0000001 :
(temp == 7'b0000001) ? 7'b0000010 :
(temp == 7'b0000010) ? 7'b0000100 :
(temp == 7'b0000100) ? 7'b0001000 :
(temp == 7'b0001000) ? 7'b0010000 :
(temp == 7'b0010000) ? 7'b0100000 :
(temp == 7'b0100000) ? 7'b1000000 : 7'b0000000;
end
assign led = temp;
endmodule
LED 没有移动。它永远停留在第一个 LED 上。是触发器不起作用还是我误解了计数器?
这是工作代码。我不知道为什么我必须使用 if 语句,但它有效。
`timescale 1ns / 1ps
module main(
input reset,
input clk, //50MHz
output [6:0] led
);
reg [26:0] counter;
reg trigger;
reg [6:0] temp;
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
trigger <= 'b0;
end
else begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
else begin
counter <= counter + 1;
end
end
end
always @ (posedge trigger, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'd0;
end
else begin
if (temp == 7'b1000000) begin
temp = 7'b0000001;
end
else if (temp == 7'b0000001) begin
temp = 7'b0000010;
end
else if (temp == 7'b0000010) begin
temp = 7'b0000100;
end
else if (temp == 7'b0000100) begin
temp = 7'b0001000;
end
else if (temp == 7'b0001000) begin
temp = 7'b0010000;
end
else if (temp == 7'b0010000) begin
temp = 7'b0100000;
end
else if (temp == 7'b0100000) begin
temp = 7'b1000000;
end
else begin
temp = 7'b0000001;
end
trigger <= 'b0;
end
end
assign led = temp;
endmodule
如果您想使用触发器作为异步时钟分频器,您需要使用 T-FF 而不是 D-FF。使用异步生成的时钟不是好的风格。不再需要对 din 的反馈。
你的 FSM 永远不会达到 b00000100,因为没有转换。请检查您的 'nextstage' 编码。这应该也是循环错误的原因。
FPGA 触发器的一般结构是使用初始设置默认值,或者 ASIC 使用异步复位。
看代码发挥:
initial begin
temp <= 7'b0000001;
end
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'b0000001;
end
else begin
counter <= counter + 1;
end
end
我们在异步重置和初始化中为 temp 分配了一个值,而计数器从未被初始化。使用异步重置创建 flip_flop 的更标准方法:
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
end
else begin
counter <= counter + 1;
end
end
第 2 部分
下一段代码是:
always @ (counter) begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
end
这有一个在计数器上触发的手动敏感度列表,最好使用带有 always @*
的自动敏感度列表。这也是一个组合块,因此它应该使用阻塞赋值 (=
)。
在 verilog 中,不应从多个块中为变量赋值,因为这里有计数器。例外情况是使用初始块作为默认值。
组合块不保持状态,并且此块仅在特定计数时更改值。暗示触发器将保持其价值,这将意味着闩锁。意外隐含的闩锁可能会导致很多问题,因为这是一个更大的话题,无法在此处讨论。
考虑改为这样做:
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
trigger <= 'b0;
end
else begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
else begin
counter <= counter + 1;
end
end
end
第 3 部分
你的最后一段代码又是一个手动敏感度列表:
always @ (trigger) begin
这不是边缘触发,所以是组合部分。组合循环是输出是其自身的函数的地方。 temp = some function of temp
.
看起来你真的想把它做成一个在触发上升沿更新的触发器:
更新
我刚刚还注意到您使用了小于或等于,这在这种情况下不起作用,因为您首先拥有最大的数字。
always @ (posedge trigger, posedge reset) begin
if (reset == 1'b1) begin
temp <= 'b0;
end
else begin
temp <= (temp == 7'b1000000) ? 7'b0000001 : // <= changed to ==
(temp <= 7'b0000001) ? 7'b0000010 :
(temp <= 7'b0000010) ? 7'b0000100 :
(temp <= 7'b0000100) ? 7'b0001000 :
(temp <= 7'b0001000) ? 7'b0010000 :
(temp <= 7'b0010000) ? 7'b0100000 :
(temp <= 7'b0100000) ? 7'b1000000 : 7'b0000000;
end
end
main.v
`timescale 1ns / 1ps
module main(
input reset,
input clk, //50MHz
output [6:0] led
);
reg [26:0] counter;
reg trigger;
reg [6:0] temp;
initial begin
temp <= 7'b0000001;
end
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'b0000001;
end
else begin
counter <= counter + 1;
end
end
always @ (counter) begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
end
always @ (trigger) begin
temp <= (temp == 7'b1000000) ? 7'b0000001 :
(temp == 7'b0000001) ? 7'b0000010 :
(temp == 7'b0000010) ? 7'b0000100 :
(temp == 7'b0000100) ? 7'b0001000 :
(temp == 7'b0001000) ? 7'b0010000 :
(temp == 7'b0010000) ? 7'b0100000 :
(temp == 7'b0100000) ? 7'b1000000 : 7'b0000000;
end
assign led = temp;
endmodule
LED 没有移动。它永远停留在第一个 LED 上。是触发器不起作用还是我误解了计数器?
这是工作代码。我不知道为什么我必须使用 if 语句,但它有效。
`timescale 1ns / 1ps
module main(
input reset,
input clk, //50MHz
output [6:0] led
);
reg [26:0] counter;
reg trigger;
reg [6:0] temp;
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
trigger <= 'b0;
end
else begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
else begin
counter <= counter + 1;
end
end
end
always @ (posedge trigger, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'd0;
end
else begin
if (temp == 7'b1000000) begin
temp = 7'b0000001;
end
else if (temp == 7'b0000001) begin
temp = 7'b0000010;
end
else if (temp == 7'b0000010) begin
temp = 7'b0000100;
end
else if (temp == 7'b0000100) begin
temp = 7'b0001000;
end
else if (temp == 7'b0001000) begin
temp = 7'b0010000;
end
else if (temp == 7'b0010000) begin
temp = 7'b0100000;
end
else if (temp == 7'b0100000) begin
temp = 7'b1000000;
end
else begin
temp = 7'b0000001;
end
trigger <= 'b0;
end
end
assign led = temp;
endmodule
如果您想使用触发器作为异步时钟分频器,您需要使用 T-FF 而不是 D-FF。使用异步生成的时钟不是好的风格。不再需要对 din 的反馈。
你的 FSM 永远不会达到 b00000100,因为没有转换。请检查您的 'nextstage' 编码。这应该也是循环错误的原因。
FPGA 触发器的一般结构是使用初始设置默认值,或者 ASIC 使用异步复位。
看代码发挥:
initial begin
temp <= 7'b0000001;
end
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
temp <= 7'b0000001;
end
else begin
counter <= counter + 1;
end
end
我们在异步重置和初始化中为 temp 分配了一个值,而计数器从未被初始化。使用异步重置创建 flip_flop 的更标准方法:
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
end
else begin
counter <= counter + 1;
end
end
第 2 部分
下一段代码是:
always @ (counter) begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
end
这有一个在计数器上触发的手动敏感度列表,最好使用带有 always @*
的自动敏感度列表。这也是一个组合块,因此它应该使用阻塞赋值 (=
)。
在 verilog 中,不应从多个块中为变量赋值,因为这里有计数器。例外情况是使用初始块作为默认值。
组合块不保持状态,并且此块仅在特定计数时更改值。暗示触发器将保持其价值,这将意味着闩锁。意外隐含的闩锁可能会导致很多问题,因为这是一个更大的话题,无法在此处讨论。
考虑改为这样做:
always @ (posedge clk, posedge reset) begin
if (reset == 1'b1) begin
counter <= 'b0;
trigger <= 'b0;
end
else begin
if (counter == 26'd50000000)begin //1Hz
trigger <= ~trigger;
counter <= 26'd0;
end
else begin
counter <= counter + 1;
end
end
end
第 3 部分
你的最后一段代码又是一个手动敏感度列表:
always @ (trigger) begin
这不是边缘触发,所以是组合部分。组合循环是输出是其自身的函数的地方。 temp = some function of temp
.
看起来你真的想把它做成一个在触发上升沿更新的触发器:
更新 我刚刚还注意到您使用了小于或等于,这在这种情况下不起作用,因为您首先拥有最大的数字。
always @ (posedge trigger, posedge reset) begin
if (reset == 1'b1) begin
temp <= 'b0;
end
else begin
temp <= (temp == 7'b1000000) ? 7'b0000001 : // <= changed to ==
(temp <= 7'b0000001) ? 7'b0000010 :
(temp <= 7'b0000010) ? 7'b0000100 :
(temp <= 7'b0000100) ? 7'b0001000 :
(temp <= 7'b0001000) ? 7'b0010000 :
(temp <= 7'b0010000) ? 7'b0100000 :
(temp <= 7'b0100000) ? 7'b1000000 : 7'b0000000;
end
end