第7个状态:让第4个LED亮,其他的灭,下一状态是第8个状态;
第8个状态:延时1s,下一状态是第1个状态;
default : ;
endcase
end
具体的代码如下:
//////////////////////////////////////////////////////////////////
// 功能:“仿顺序操作”
//////////////////////////////////////////////////////////////////
always @(posedge I_clk or negedge I_rst_n)
begin
if(!I_rst_n)
begin
R_state <= 3'b000 ;
R_cnt_ls <= 32'd0 ;
end
else
begin
case(R_state)
C_S0:
begin
R_led_out_reg <= 4'b0001 ;
R_state <= C_S1 ;
end
C_S1:
begin
if(R_cnt_ls == C_CNT_1S)
begin
R_cnt_ls <= 32'd0 ;
R_state <= C_S2 ;
end
else
R_cnt_ls <= R_cnt_ls + 1'b1 ;
end
C_S2:
begin
R_led_out_reg <= 4'b0010 ;
R_state <= C_S3 ;
end
C_S3:
begin
if(R_cnt_ls == C_CNT_1S)
begin
R_cnt_ls <= 32'd0 ;
R_state <= C_S4 ;
end
else
R_cnt_ls <= R_cnt_ls + 1'b1 ;
end
C_S4:
begin
R_led_out_reg <= 4'b0100 ;
R_state <= C_S5 ;
end
C_S5:
begin
if(R_cnt_ls == C_CNT_1S)
begin
R_cnt_ls <= 32'd0 ;
R_state <= C_S6 ;
end
else
R_cnt_ls <= R_cnt_ls + 1'b1 ;
end
C_S6:
begin
R_led_out_reg <= 4'b1000 ;
R_state <= C_S7 ;
end
C_S7:
begin
if(R_cnt_ls == C_CNT_1S)
begin
R_cnt_ls <= 32'd0 ;
R_state <= C_S0 ;
end
else
R_cnt_ls <= R_cnt_ls + 1'b1 ;
end
default: R_state <= 3'b000 ;
endcase
end
end
assign O_led_out = ~R_led_out_reg ;
时序图如下图:
时序图仍然正确,实现了流水灯的效果
七、 总结
1、所谓的“仿顺序操作”实际上就是一个状态机,通过状态的跳变实现“顺序执行”的效果。这种思想在后面写接口时序的时候还是挺管用的,今后可以多多琢磨琢磨。
2、 C语言的while(1)和Verilog语言的always @(posedge I_clk)有类似的地方,只要CPU的时钟存在,它们就一直执行下去。书上都说C语言是一种串行语言,Verilog是一种并行语言,实际上这里也能有体会:C语言里只能有1个while(1)语句,进入while(1)以后CPU就出不来了,而Verilog中可以有多个always @(posedge I_clk)语句,并且每个always @(posedge I_clk)同时运行的,这就是两种语言最大的区别吧。
八、 附录
1、分频1s产生流水灯的完整代码
module led_work_top
(
input I_clk ,
input I_rst_n ,
output [3:0] O_led_out
);
reg [31:0] R_cnt_ls ;
wire W_clk_ls ;
reg R_clk_ls_reg ;
reg [3:0] R_led_out_reg ;
//////////////////////////////////////////////////////////////////
// 功能:产生1s的时钟
//////////////////////////////////////////////////////////////////
always @(posedge I_clk or negedge I_rst_n)
begin
if(!I_rst_n)
begin
R_cnt_ls <= 32'd0 ;
R_clk_ls_reg <= 1'b1 ;
end
else if(R_cnt_ls == 32'd24_999_999)
begin
R_cnt_ls <= 32'd0 ;
R_clk_ls_reg <= ~R_clk_ls_reg ;
end
else
R_cnt_ls <= R_cnt_ls + 1'b1 ;
end
assign W_clk_ls = R_clk_ls_reg ;
//////////////////////////////////////////////////////////////////
// 功能:对输出寄存器进行移位产生流水效果
//////////////////////////////////////////////////////////////////
always @(posedge W_clk_ls or negedge I_rst_n)
begin
if(!I_rst_n)
R_led_out_reg <= 4'b0001 ;
else if(R_led_out_reg == 4'b1000)
R_led_out_reg <= 4'b0001 ;
else
R_led_out_reg <= R_led_out_reg << 1 ;
end
assign O_led_out = ~R_led_out_reg ;
endmodule
2、 “仿顺序操作”产生流水灯完整代码
module led_work_top
(
input I_clk ,
input I_rst_n ,