LED开关的简单Verilog示例?
我正在尝试为1热编码的简单LED开关按钮构建一个状态机 特别是我试图通过我的例子来理解阻塞和非阻塞赋值 你会认为下面的事情可以做得更好,还是在任何一个街区都是完全错误的LED开关的简单Verilog示例?,verilog,hdl,Verilog,Hdl,我正在尝试为1热编码的简单LED开关按钮构建一个状态机 特别是我试图通过我的例子来理解阻塞和非阻塞赋值 你会认为下面的事情可以做得更好,还是在任何一个街区都是完全错误的 module example ( input clk, input rst, input push, output reg led_on ); reg on; reg off; reg t_on_off; reg t_off_on; always @* begin t_on_off = on &a
module example (
input clk,
input rst,
input push,
output reg led_on
);
reg on;
reg off;
reg t_on_off;
reg t_off_on;
always @* begin
t_on_off = on & (push);
end
always @* begin
t_off_on = off & (push);
end
always @(posedge clk or posedge rst) begin
if (rst) on <= 1'b0;
else if (t_off_on) on <= 1'b1;
else if (t_on_off) on <= 1'b0;
end
always @(posedge clk or posedge rst) begin
if (rst) off <= 1'b1;
else if (t_off_on) off <= 1'b0;
else if (t_on_off) off <= 1'b1;
end
always @* begin
led_on = on;
end
endmodule
?
特别是我想知道:我能把过渡的赋值合并成一个块吗,比如
是的,你可以完全按照你描述的那样做
如果需要,还可以组合顺序块:
always @(posedge clk or posedge rst) begin
if (rst) begin
on <= 1'b0;
off <= 1'b1;
end else if (t_off_on) begin
on <= 1'b1;
off <= 1'b0;
end
(etc....)
end
始终@(posedge clk或posedge rst)开始
如果(rst)开始
在是时,可以将多个always块组合成一个块
您只需要将同步块(时钟块)和异步块分离为单独的always块
但是,一个好的样式是为每个单独的输出都有一个always块。这更易于阅读,更像真实世界,因为每个“始终”块彼此并发。如果它不需要是一个热块,则将其简化为:
module example (
input clk,
input rst,
input push,
output reg led_on
);
always @(posedge clk or posedge rst) begin
if (rst) led_on <= 1'b0;
else if (push) led_on <= !led_on;
end
endmodule
模块示例(
输入时钟,
输入rst,
输入推送,
输出reg led_开启
);
始终@(posedge clk或posedge rst)开始
如果(rst)引导了重构建议:
output reg led_on;
always @* begin
led_on = on;
end
致:
您也可以对t\u on\u off
和t\u off\u on
wire t_on_off;
wire t_off_on;
assign t_on_off = on & (push);
assign t_off_on = off & (push);
或者,如果您更喜欢将declare和assign放在一行中
wire t_on_off = on & (push);
wire t_off_on = off & (push);
但是,如果您将两个时钟始终块滚动到一个块中,则不需要单独的逻辑,将@Tim的答案与t_on_off检查相结合:
module example (
input clk,
input rst,
input push,
output reg led_on
);
reg on;
reg off;
assign led_on = on;
always @(posedge clk or posedge rst) begin
if (rst) begin
on <= 1'b0;
off <= 1'b1;
end
else if (off & push) begin
on <= 1'b1;
off <= 1'b0;
end
else if (on & push) begin
on <= 1'b0;
off <= 1'b1;
end
end
endmodule
模块示例(
输入时钟,
输入rst,
输入推送,
输出reg led_开启
);
注册;
登记关闭;
分配led_开=开;
始终@(posedge clk或posedge rst)开始
如果(rst)开始
在上,这已经是很久以前的事了,但给出的解决方案可能并不完全是您所期望的。从我可以推断出的解决方案都认为,LED将继续切换只要按钮被按下(即,它将切换时钟的频率),使它在视觉上察觉不到,如果时钟频率高。但是,我假设您希望在每次按下按钮时只切换一次LED,并在此期间保持LED状态
下面的示例根据3个按钮的活动切换3个LED的状态
只要按下pbutton0,led0就会激活
led1定期保持切换(基于clk_div的大小),并在按下pbutton1时复位
只要按下pbutton2,led2就会切换
请注意,led0是组合的,而其他两个LED是顺序的。对于切换led2,必须存储pbutton2的先前状态;每当pbutton2(t-1)==0和pbutton2(t)==1时,这意味着按钮刚从低变高,因此led2的状态必须改变
最后,请忽略时钟源,因为它仅用于演示Xilinx SP605开发工具包上的代码
////////////////////////////////////////////////////
// This project uses 3 pushbuttons and 3 LEDs.
// pbutton0 activates led0
// pbutton1 serves as reset for led1 periodic toggling
// pbutton2 toggles led2
//
// The clock source (divider+buffer) was created using the clocking IP wizard.
//
module xilinx_sp605_board_leds
(
input CLK_IN1_P,
input CLK_IN1_N,
input pbutton0,
input pbutton1,
input pbutton2,
output led0,
output reg led1,
output reg led2
);
// declarations
wire clk;
wire reset = pbutton1;
reg [19:0] clk_div;
reg pbutton2_reg;
// led0 = state of pbutton0
assign led0 = pbutton0;
// differential clock divider+buffer
clk_source CLK_SOURCE (
.CLK_IN1_P(CLK_IN1_P),
.CLK_IN1_N(CLK_IN1_N),
.CLK_OUT1(clk),
.RESET(reset));
// led1, led2 toggling
always @(posedge reset or posedge clk)
begin
if(reset)begin
clk_div <= 0;
led1 <= 0;
pbutton2_reg <= 0;
led2 <= 0;
end else begin
clk_div <= clk_div + 1;
if(clk_div==0)
led1 <= ~led1;
pbutton2_reg <= pbutton2;
if(~pbutton2_reg && pbutton2)
led2 <= ~led2;
end
end
endmodule
////////////////////////////////////////////////////
//此项目使用3个按钮和3个LED。
//pbutton0激活led0
//pbutton1用作led1定期切换的复位
//pbutton2切换led2
//
//时钟源(除法器+缓冲区)是使用时钟IP向导创建的。
//
模块xilinx_sp605_板_LED
(
在1\u P中输入时钟,
输入CLK_in 1_N,
输入pbutton0,
输入pbutton1,
输入pbutton2,
输出led0,
输出寄存器led1,
输出寄存器led2
);
//声明
电线电缆;
导线复位=pbutton1;
注册[19:0]时钟分区;
reg pbutton2_reg;
//led0=pbutton0的状态
分配led0=pbutton0;
//差分时钟分频器+缓冲器
时钟源时钟源(
.CLK_IN1_P(CLK_IN1_P),
.CLK_IN1_N(CLK_IN1_N),
.CLK_OUT1(CLK),
.重置(重置));
//led1,led2切换
始终@(posedge重置或posedge clk)
开始
如果(重置)开始
九龙分区
module example (
input clk,
input rst,
input push,
output reg led_on
);
reg on;
reg off;
assign led_on = on;
always @(posedge clk or posedge rst) begin
if (rst) begin
on <= 1'b0;
off <= 1'b1;
end
else if (off & push) begin
on <= 1'b1;
off <= 1'b0;
end
else if (on & push) begin
on <= 1'b0;
off <= 1'b1;
end
end
endmodule
////////////////////////////////////////////////////
// This project uses 3 pushbuttons and 3 LEDs.
// pbutton0 activates led0
// pbutton1 serves as reset for led1 periodic toggling
// pbutton2 toggles led2
//
// The clock source (divider+buffer) was created using the clocking IP wizard.
//
module xilinx_sp605_board_leds
(
input CLK_IN1_P,
input CLK_IN1_N,
input pbutton0,
input pbutton1,
input pbutton2,
output led0,
output reg led1,
output reg led2
);
// declarations
wire clk;
wire reset = pbutton1;
reg [19:0] clk_div;
reg pbutton2_reg;
// led0 = state of pbutton0
assign led0 = pbutton0;
// differential clock divider+buffer
clk_source CLK_SOURCE (
.CLK_IN1_P(CLK_IN1_P),
.CLK_IN1_N(CLK_IN1_N),
.CLK_OUT1(clk),
.RESET(reset));
// led1, led2 toggling
always @(posedge reset or posedge clk)
begin
if(reset)begin
clk_div <= 0;
led1 <= 0;
pbutton2_reg <= 0;
led2 <= 0;
end else begin
clk_div <= clk_div + 1;
if(clk_div==0)
led1 <= ~led1;
pbutton2_reg <= pbutton2;
if(~pbutton2_reg && pbutton2)
led2 <= ~led2;
end
end
endmodule