Verilog实现交通灯(数电课设)----------旧

2019-04-13 14:28发布

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