这里是新写的交通灯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