1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Verilog实现交通灯(数电课设)-----新--及对于状态机的理解

Verilog实现交通灯(数电课设)-----新--及对于状态机的理解

时间:2022-06-06 18:44:12

相关推荐

Verilog实现交通灯(数电课设)-----新--及对于状态机的理解

目录

此文主要用于状态机的理解,及代码书写的对比(同之前写的交通灯)。

状态机

状态机注意要点:

依据久思路重写交通灯

控制模块

仿真截图

显示模块

解决上次遗留问题(新代码的控制)

此文主要用于状态机的理解,及代码书写的对比(同之前写的交通灯)。

原来的交通灯:/qq_41467882/article/details/83651966

对于状态机的理解,此处参考这三篇博文(感谢)

FPGA三段式状态机的思维陷阱:/NarutoInspire/article/details/53893779

fpga状态机详解:/ruanyz_nobody/article/details/49892037

FPGA 学习之路(八)深入理解状态机:/GOGOmusic/article/details/54768462

状态机

笔者将重写交通灯,同之前的进行对比同时解决上次文章末尾留下来的一段代码的问题。这些文章中所提及的知识点笔者将尽可能的体现在代码的书写中。

由于之博文前介绍了原理等其他问题,这里直接上代码,所有问题我将在代码注释或者代码后边解决。

//第一个进程,同步时序always块,形式固定always@(posedge clk or negedge rst_n)beginif(!rst_n)current_state <= idle;else current_state <= next_state;end//第二个always,组合逻辑模块,描述状态迁移条件判断always@(*)begincase(current_state)idle:beginif(...)next_state = elsenext_state = ends0:beginends1:beginenddefault:beginnext_state = idle;endendcaseend//第三个进程,描述输出,同步时序always块always@(posedge clk or negedge rst_n)beginif(!rst_n)dout <= 1'b0;else begincase(next_state)idle: dout <= ;s0: dout <= ;s1: dout <= ;default : dout <= ;endcase endend

状态机注意要点:

三个always块,第一个第三个为同步时序always块(用非阻塞赋值方式)。第二个为组合逻辑always块(使用阻塞赋值方式)。组合逻辑模块敏感列表采用*第三段状态输出为next_state。用current_state会晚一个时钟周期(应该是由于D触发器的原因)三段式并不是有三个always块。后面一段是(第三个,第四个......)是用来描述状态输出的

依据久思路重写交通灯

接下来我用上面这个模板写出来新的交通灯。这里只用了A路口,B路口只不过就是改改转换条件。代码过程中的异或我会加在注释里。同样只写控制模块。

控制模块

module traffic_control(clk,rst_n,emgercy_brake,digitA,ledA);input clk;input rst_n;input emgercy_brake;output [5:0] digitA;output [2:0] ledA;parameter idle = 4'b0001,s0 = 4'b0010,s1 = 4'b0100,s2 = 4'b1000;reg [3:0] stateA;//第一个进程,同步时序always块/*reg [3:0] next_state;reg [3:0] current_state;always@(posedge clk or negedge rst_n)beginif(!rst_n)current_state <= idle;else current_state <= state;end//后面的state全部替换成next_state。不然会延时一个时钟周期*//*第二个always,组合逻辑模块,描述状态迁移条件(这一段笔者是在无能,因为计数器不知道怎么在下一个时钟周期中表示出来并且同时控制状态的跳转)另外,实在是觉得这种思路的交通灯用三段式不是那么好表示,觉得非要写成组合逻辑没多大意义,下面将下面一个代码将写成组合逻辑*///注释解释A路口reg [5:0] cntA;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginstateA <= idle;cntA <= 6'd35;endelse case(stateA)idle:beginif(emgercy_brake == 1'b0)stateA <= s0;elsestateA <= idle;ends0:beginif(emgercy_brake == 1'b1)stateA <= idle;else beginif(cntA == 1)begin stateA <= s1;cntA <= 6'd20;end elsebegin cntA <= cntA - 1'b1;end endends1:beginif(emgercy_brake == 1'b1)stateA <= idle;else beginif(cntA == 1)begin stateA <= s2;cntA <= 6'd5;end elsebegin cntA <= cntA - 1'b1;end endends2:beginif(emgercy_brake == 1'b1)stateA <= idle;else beginif(cntA == 1)begin stateA <= s0;cntA <= 6'd35;end elsebegin cntA <= cntA - 1'b1;end endenddefault:beginstateA <= idle;endendcaseendassign digitA = cntA;//第三个进程,描述输出,同步时序always块reg [2:0] doutA;always@(posedge clk or negedge rst_n)beginif(!rst_n)doutA <= 3'b100;else begincase(stateA)idle : doutA <= 3'b100;s0 : doutA <= 3'b100;s1 : doutA <= 3'b001;s2: doutA <= 3'b010;default: doutA <= 3'b100;endcase endendassign ledA = doutA;endmodule

仿真截图

显示模块

这里的显示模块比较有趣。

assign H_A = cntA / 10;assign L_A = cntA % 10;//依次取cntA的十位和个位

这样简单改写前面的显示模块就很容易完成了。

解决上次遗留问题(新代码的控制)

module traffic_control_1(led,clk,zhidong,cntA_h,cntA_l,cntB_l,cntB_h,rst_n);input rst_n;input clk;input zhidong;output reg [3:0] cntA_h;output reg [3:0] cntA_l;output reg [3:0] cntB_h;output reg [3:0] cntB_l;output reg [5:0] led;reg flag;reg [1:0] current_state;reg [1:0] next_state;parameter [1:0] idle=2'd0,s1=2'd1,s2=2'd2,s3=2'd3;always@(posedge clk or negedge rst_n)beginif(!rst_n)current_state <= idle;else current_state <= next_state;endalways@(*)begincase(current_state)idle : next_state = flag ? s1:current_state;s1 : next_state = flag ? s2:current_state;s2 : next_state = flag ? s3:current_state;s3 : next_state = flag ? idle:current_state;endcaseendalways@(posedge clk or negedge rst_n)beginif(!rst_n)begincntA_h <= 4'd5;cntA_l <= 4'd0;cntB_h <= 4'd4;cntB_l <= 4'd5;flag <= 0;endelse if(zhidong)led <= 6'b100_100;//A红黄绿B红黄绿else case(current_state)idle:beginflag<=0;led<=6'b100_001;//Ared Bgreen 45sif(cntB_h==0&&cntB_l==0) beginflag<=1;cntA_h<=0;cntA_l<=5;cntB_h<=0;cntB_l<=5;endelse if(!cntB_h==0&&cntB_l==0) begincntB_h<=cntB_h-1;cntB_l<=9;endelse if(!cntA_h==0&&cntA_l==0) begincntA_h<=cntA_h-1;cntA_l<=9;endelse begincntA_l<=cntA_l-1;cntB_l<=cntB_l-1;endends1:beginflag<=0;led<=6'b100_010;//Ared Byellow 5sif(cntB_h==0&&cntB_l==0 && cntB_h==0&&cntB_l==0) beginflag<=1;cntA_h<=4;cntA_l<=5;cntB_h<=5;cntB_l<=0;endelse if(!cntB_h==0 && cntB_l==0) begincntB_h<=cntB_h-1;cntB_l<=9;endelse if(!cntA_h==0 && cntA_l==0) begincntA_h<=cntA_h-1;cntA_l<=9;endelse begincntA_l<=cntA_l-1;cntB_l<=cntB_l-1;endends2:beginflag<=0;led<=6'b001_100;//Agreen Bred 45s if(cntB_h==0&&cntB_l==0 && cntB_h==0&&cntB_l==0) beginflag<=1;cntA_h<=0;cntA_l<=5;cntB_h<=0;cntB_l<=5;endelse if(!cntB_h==0 && cntB_l==0) begincntB_h<=cntB_h-1;cntB_l<=9;endelse if(!cntA_h==0&&cntA_l==0) begincntA_h<=cntA_h-1;cntA_l<=9;endelse begincntA_l<=cntA_l-1;cntB_l<=cntB_l-1;endends3:beginflag<=0;led<=6'b100_010;//Ayellow Bredif(cntB_h==0&&cntB_l==0 && cntB_h==0&&cntB_l==0) beginflag<=1;cntA_h<=5;cntA_l<=0;cntB_h<=4;cntB_l<=5;endelse if(!cntB_h==0&&cntB_l==0) begincntB_h<=cntB_h-1;cntB_l<=9;endelse if(!cntA_h==0&&cntA_l==0) begincntA_h<=cntA_h-1;cntA_l<=9;endelse begincntA_l<=cntA_l-1;cntB_l<=cntB_l-1;endendendcaseendendmodule

代码仿真

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。