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

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

 

你可能感兴趣的:(FPGA逻辑篇)