赞
踩
这里是新写的交通灯Verilog实现交通灯(数电课设)----------新:https://blog.csdn.net/qq_41467882/article/details/86626507
里边又两个核心代码和数码管显示的新方法及对状态机的新理解。。
参考思路:https://www.cnblogs.com/christsong/p/5629643.html
里边有思路框架,可以用来参考。
设计要求:
1,交通灯可以自行转换状态,红黄绿灯分别进行,绿灯转红灯需要五秒的黄灯作为延时
2,可以暂停红黄绿灯的计数
3,可以进入紧急制动状态(红灯全部亮)
4,倒计时显示在数码管上,六个led分别代表红黄绿灯。
第一种方法
设计思路:
状态机的运用,状态的转换,用的basys2板子
模块介绍(代码的书写)
分频模块:
- module fenpin(clk,rst_n,clk1
- );
- input clk;//系统时钟
- output reg clk1;//分频后的时钟
- input rst_n;//复位信号
- reg [25:0] cnt;
-
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- cnt <= 0;
- else if(cnt==26'd24_999_999)//当cnt为24_999_999的时候,重新计数并且将clk1反转
- begin
- cnt <= 0;
- clk1 <= ~clk1;
- end
- else
- cnt <= cnt + 1'b1;
- end
- endmodule
很简单的一个分频模块,系统时钟为50mhz,分频后周期为1s。
数码管动态显示模块:
- module xianshi(
- input clk,
- input rst_n,
- input [7:0] B,
- input [7:0] A,
- output reg [6:0]Y,//显示器段选
- output reg [3:0]an,//显示器位选
- output reg dp
- );
- parameter AB=18'd300000;
- reg[17:0] cnt;//动态扫描计数器
- //这个时间其实可以自己控制,只要在人眼不能观察到间隔就行
- always@(posedge clk or negedge rst_n)
- if(!rst_n)
- cnt<=1'b0;
- else if (cnt==AB-1)
- cnt<=1'b0;
- else cnt<=cnt+1;
- /*动态扫描 选择要显示的数码管(第一个要显示),当速度快到人眼无法区分的时候就是“所有”数码管一//起显示了*/
- reg[3:0]digit;//定义一个储存要显示数据的寄存器
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- an<=4'b1110;
- dp<= 0;
- end
- else if(cnt==AB-1) begin
- an<={an[0],an[3:1]};
- dp <= 1'b1;
- end
- end
- //当某一个数码管被点亮的时候,赋予其对应位置的数据
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- digit<=4'b1111;
- else if(an==4'b1110)
- digit<=B[3:0];
- else if(an==4'b1101)
- digit<=B[7:4];
- else if(an==4'b1011)
- digit<=A[3:0];
- else if(an==4'b0111)
- digit<=A[7:4];
- end
- //七段译码器(显示器)
- always@(*)
- begin
- case(digit)
- 4'b0000:Y<=7'b0000001;
- 4'b0001:Y<=7'b1001111;
- 4'b0010:Y<=7'b0010010;
- 4'b0011:Y<=7'b0000110;
- 4'b0100:Y<=7'b1001100;
- 4'b0101:Y<=7'b0100100;
- 4'b0110:Y<=7'b0100000;
- 4'b0111:Y<=7'b0001111;
- 4'b1000:Y<=7'b0000000;
- 4'b1001:Y<=7'b0000100;
- default Y<=7'b0000001;
- endcase
- end
- endmodule
数码管显示需要进行段选和位选,具体解释位于上述代码
控制模块:
- module control(clk,rst_n,ledA,ledB,A,B,en
- );
- input clk;
- input rst_n;
- input en;
-
- output reg [2:0] ledA;//控制三个ledA方向
- output reg [2:0] ledB;
-
- reg [2:0] stateA;
- reg [2:0] stateB;
- output reg [7:0] A;
- output reg [7:0] B;
-
- parameter redB = 3'b100,greenB = 3'b001,yellowB = 3'b010;
- parameter redA = 3'b100,greenA = 3'b001,yellowA = 3'b010;
-
- always @ ( posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- begin
- stateA <= 3'b100 ;
- A <= 8'b0010_0000;
- end
- else if(en)
- case ( stateA ) //交通灯状态变换
- redA :
- begin
- if(A==0) begin
- A <= 8'b0001_0101;
- stateA <= greenA;
- end
- else if(A[3:0] == 0 && !A[7:4] == 0) begin
- A[7:4] <= A[7:4] - 1'b1;
- A[3:0] <= 4'b1001;
- end
- else if(!A[3:0] == 0) begin
- A[3:0] <= A[3:0] - 1'b1;
- end else
- stateA <= redA;
- end
- greenA :
- begin
- if(A==0) begin
- A <= 8'b0000_0100;
- stateA <= yellowA;
- end
- else if(A[3:0] == 0 && !A[7:4] == 0) begin
- A[7:4] <= A[7:4] - 1'b1;
- A[3:0] <= 4'b1001;
- end
- else if(!A[3:0] == 0) begin
- A[3:0] <= A[3:0] - 1'b1;
- end else
- stateA <= greenA;
- end
- yellowA :
- begin
- if(A==0) begin
- A <= 8'b0010_0000;
- stateA <= redA;
- end
- else if(A[3:0] == 0 && !A[7:4] == 0) begin
- A[7:4] <= A[7:4] - 1'b1;
- A[3:0] <= 4'b1001;
- end
- else if(!A[3:0] == 0) begin
- A[3:0] <= A[3:0] - 1'b1;
- end else
- stateA <= yellowA;
- end
- default : stateA <= redA ;
- endcase
- end
- always@(*)
- begin
- case (stateA)
- redA : ledA <= redA;
- yellowA : ledA <= yellowA;
- greenA : ledA <= greenA;
- endcase
- end
-
- always @ ( posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- begin
- stateB <= 3'b001 ;
- B<= 8'b0001_0101;
- end
- else if(en)
- case ( stateB ) //交通灯状态变换
- greenB:
- begin
- if(B==0) begin
- B<= 8'b0000_0100;
- stateB <= yellowB;
- end
- else if(B[3:0] == 0 && !B[7:4] == 0) begin
- B[7:4] <= B[7:4] - 1'b1;
- B[3:0] <= 4'b1001;
- end
- else if(!B[3:0] == 0) begin
- B[3:0] <= B[3:0] - 1'b1;
- end else
- stateB <= greenB;
- end
- yellowB:
- begin
- if(B == 0) begin
- B <= 8'b0010_0000;
- stateB <= redB;
- end
- else if(B[3:0] == 0 && !B[7:4] == 0) begin
- B[7:4] <= B[7:4] - 1'b1;
- B[3:0] <= 4'b1001;
- end
- else if(!B[3:0] == 0) begin
- B[3:0] <= B[3:0] - 1'b1;
- end else
- stateB <= redB;
- end
- redB:
- begin
- if(B == 0) begin
- B <= 8'b0001_0101;
- stateB <= greenB;
- end
- else if(B[3:0] == 0 && !B[7:4] == 0) begin
- B[7:4] <= B[7:4] - 1'b1;
- B[3:0] <= 4'b1001;
- end
- else if(!B[3:0] == 0) begin
- B[3:0] <= B[3:0] - 1'b1;
- end else
- stateB <= redB;
- end
- default : stateB <= redB;
- endcase
- end
- always@(*)
- begin
- case (stateB)
- redB: ledB<= redB;
- yellowB: ledB<= yellowB;
- greenB: ledB<= greenB;
- endcase
- end
- endmodule
具体代码已经粘贴在上边了。简单介绍下我的思路。
通过一个状态机来控制一个红绿灯的亮灭情况,然后倒计时(采用格雷码的形式)掉到0的时候开始进行下一个状态的跳转。但具体实现的时候有一个小bug。在每次黄灯跳转的时候,会有一秒的延时。所以我将每个黄灯的时间改为5s。(具体原因不太清楚)有兴趣可以交流。
top文件:
- module new1_top(clk,rst_n,Y,an,ledA,ledB,en,dp
- );
- input clk;
- input rst_n;
- input en;
-
- output [2:0] ledA,ledB;
- output [6:0] Y;
- output [3:0] an;
- output dp;
-
- wire clk_1s;
- wire [7:0] lineA;
- wire [7:0] lineB;
-
- control A(
- .clk(clk_1s),
- .rst_n(rst_n),
- .ledA(ledA),
- .ledB(ledB),
- .A(lineA),
- .B(lineB),
- .en(en)
- );
-
- fenpin B(
- .clk(clk),
- .rst_n(rst_n),
- .clk1(clk_1s)
- );
-
- xianshi C(
- .clk(clk),
- .rst_n(rst_n),
- .B(lineB),
- .A(lineA),
- .Y(Y),//显示器段选
- .an(an),//显示器位选
- .dp(dp)
- );
- endmodule
下板子没有问题。可以正常工作。(没有加紧急制动状态,相加的的可以自己加,也很简单)
接下来用一种新的方法写控制模块(没有仿真,下板子,不过应该可以):这里只写控制模块
- module control(led,divclk,zhidong,cntA_h,cntA_l,cntB_l,cntB_h,rst
- );
- input rst;
- input divclk;
- 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 cs,ns;
-
- parameter [1:0] s0=2'd0,s1=2'd1,s2=2'd2,s3=2'd3;
-
- always@(posedge divclk or posedge rst)
- if(rst)
- cs<=s0;
- else
- cs<=ns;
-
- always@(*)
- begin
- case(cs)
- s0:ns=flag?s1:s0;
- s1:ns=flag?s2:s1;
- s2:ns=flag?s3:s2;
- s3:ns=flag?s0:s3;
- endcase
- end
-
- always@(posedge divclk or posedge rst)
- begin
- if(rst)
- begin
- cntA_h<=5;
- cntA_l<=0;
- cntB_h<=4;
- cntB_l<=5;
- flag<=0;
- end
- else if(zhidong)
- led<=6'b100_100;//A红黄绿B红黄绿
- else
- case(cs)
- s0:begin
- flag<=0;
- led<=6'b100_001;//Ared Bgreen 45s
- if(cntB_h==0&&cntB_l==0) begin
- flag<=1;
- cntA_h<=0;
- cntA_l<=5;
- cntB_h<=0;
- cntB_l<=5;
- end
- else if(!cntB_h==0&&cntB_l==0) begin
- cntB_h<=cntB_h-1;
- cntB_l<=9;
- end
- else if(!cntA_h==0&&cntA_l==0) begin
- cntA_h<=cntA_h-1;
- cntA_l<=9;
- end
- else begin
- cntA_l<=cntA_l-1;
- cntB_l<=cntB_h-1;
- end
- end
- s1:begin
- flag<=0;
- led<=6'b100_010;//Ared Byellow 5s
- if(cntB_h==0&&cntB_l==0&&cntB_h==0&&cntB_l==0) begin
- flag<=1;
- cntA_h<=4;
- cntA_l<=5;
- cntB_h<=5;
- cntB_l<=0;
- end
- else if(!cntB_h==0&&cntB_l==0) begin
- cntB_h<=cntB_h-1;
- cntB_l<=9;
- end
- else if(!cntA_h==0&&cntA_l==0) begin
- cntA_h<=cntA_h-1;
- cntA_l<=9;
- end
- else begin
- cntA_l<=cntA_l-1;
- cntB_l<=cntB_h-1;
- end
- end
- s2:begin
- flag<=0;
- led<=6'b001_100;//Agreen Bred 45s
- if(cntB_h==0&&cntB_l==0&&cntB_h==0&&cntB_l==0) begin
- flag<=1;
- cntA_h<=0;
- cntA_l<=5;
- cntB_h<=0;
- cntB_l<=5;
- end
- else if(!cntB_h==0&&cntB_l==0) begin
- cntB_h<=cntB_h-1;
- cntB_l<=9;
- end
- else if(!cntA_h==0&&cntA_l==0) begin
- cntA_h<=cntA_h-1;
- cntA_l<=9;
- end
- else begin
- cntA_l<=cntA_l-1;
- cntB_l<=cntB_h-1;
- end
- end
- s3:begin
- flag<=0;
- led<=6'b100_010;//Ayellow Bred
- if(cntB_h==0&&cntB_l==0&&cntB_h==0&&cntB_l==0) begin
- flag<=1;
- cntA_h<=5;
- cntA_l<=0;
- cntB_h<=4;
- cntB_l<=5;
- end
- else if(!cntB_h==0&&cntB_l==0) begin
- cntB_h<=cntB_h-1;
- cntB_l<=9;
- end
- else if(!cntA_h==0&&cntA_l==0) begin
- cntA_h<=cntA_h-1;
- cntA_l<=9;
- end
- else begin
- cntA_l<=cntA_l-1;
- cntB_l<=cntB_h-1;
- end
- end
- endcase
- end
- endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。