完整功能:

实现主干道和支干道的红绿灯,并实现时间显示功能;(前两位显示东西的     后两位显示南北的)

实现绿灯,黄灯,红灯的持续时间固定的交通控制功能;
(状态机切换三段的显示 )

当东西或南北两路中任一道上出现特殊情况,交通控制系统应可由交警手动控制立即进入特殊运行状态的功能;(控制一个SW[0]—->  en 计数器计数半秒使能半秒)

实现绿灯,黄灯,红灯的持续时间可调的交通控制功能
(按键key_up 控制加  按键key_down 控制减);
 

top.v改变为:

module top(ext_clk_25m,ext_rst_n,switch1,switch2,key_upup,key_down,key_entr,dtube_cs_n,dtube_data,led);
//顶层控制模块input ext_clk_25m; //时钟信号25MHzinput ext_rst_n;  //复位信号input switch1;input switch2; input key_upup;input key_entr;input key_down;output [3:0] dtube_cs_n;	//段选数据位output [6:0] dtube_data;//位选数据位output [7:0] led;wire [3:0] TimeL;wire [3:0] TimeH;wire [3:0] TimeL1;wire [3:0] TimeH1;wire [7:0] red;wire [7:0] green;wire [7:0] yellow;wire [3:0] timesh;wire [3:0] timesl;wire en1;wire en2;wire set_en;wire clk;//中间变量//控制电路模块control con1(.ext_clk_25m(ext_clk_25m),.ext_rst_n(ext_rst_n),.switch1(switch1),.switch2(switch2),.en1(en1),.en2(en2),.set_en(set_en));//设置时间模块set set1(.ext_clk_25m(ext_clk_25m),.ext_rst_n(ext_rst_n),.set_en(set_en),.key_upup(key_upup),.key_down(key_down),.key_entr(key_entr),.red(red),.yellow(yellow),.green(green),.led(led[7:6]),.times1(timesh),.times2(timesl));//分频25MHZ变为1HZdiv d1(.ext_clk_25m(ext_clk_25m),.ext_rst_n(ext_rst_n),.mclk(clk));//倒计时计数模块(东西)counter c1(.ext_clk_25m(ext_clk_25m),.mclk(clk),.ext_rst_n(ext_rst_n),.cnt_en(en2),.set_en(set_en),.red(red),.green(green),.yellow(yellow),.TimeH(TimeH),.TimeL(TimeL),.led(led[2:0]));//倒计时计数模块(南北)counter1 c2(.ext_clk_25m(ext_clk_25m),.mclk(clk),.ext_rst_n(ext_rst_n),.cnt_en(en2),.set_en(set_en),.red(red),.green(green),.yellow(yellow),.TimeH1(TimeH1),.TimeL1(TimeL1),.led(led[5:3]));//数码管显示模块(东西,南北)seg s1(.ext_clk_25m(ext_clk_25m),		.ext_rst_n(ext_rst_n),	.seg_en(en1),.set_en(set_en),.set_segh(timesh),.set_segl(timesl),.TimeH(TimeH),.TimeL(TimeL),.TimeH1(TimeH1),.TimeL1(TimeL1),.dtube_cs_n(dtube_cs_n),	.dtube_data(dtube_data)	);
endmodule

 

控制电路模块:

module control(ext_clk_25m,ext_rst_n,switch1,switch2,en1,en2,set_en);input       ext_clk_25m;		//输入时钟input       ext_rst_n  ;		//复位信号input       switch1    ;		//特殊状态开关input       switch2    ;        //设置状态开关output  reg en1        ;		//数码管使能位output  reg en2        ;		//交通灯使能位output  reg set_en     ;        //设置使能位reg  [24:0] cnt        ;        //存放计数器的值parameter TIME = 25'd2500_0000;//数码管特殊状态闪烁计数器模块always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)begincnt <=25'd0;endelse if(cnt ==TIME-1'b1)begincnt <=1'b0;endelse begincnt <=cnt + 1'b1;endend//开关控制设置的开启always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginset_en <=1'b0;endelse if(switch2==1'b0)beginset_en <=1'b1;endelse beginset_en <=1'b0;endend//数码管闪烁模块always @(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginen1<=1'b0;endelse if(switch1==1'b0)beginif(cnt<(TIME/2-1'b1))beginen1<=1'b1;endelse beginen1<=1'b0;endendelse beginen1<=1'b0;endend//停止计数器计时模块always @(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginen2<=1'b0;endelse if(switch1==1'b0)beginen2<=1'b1;endelse beginen2<=1'b0;endendendmodule

分频模块:

module div(ext_clk_25m,ext_rst_n,mclk);input           ext_clk_25m    ;//输入时钟input           ext_rst_n      ;//复位端口output      reg mclk           ;//输出1Hzreg      [23:0] cnt            ;//存放计数器的值parameter TIME=   24'd1250_0000;//时钟25MHz
//分频模块,使得输入时钟为25MHz输出时钟为1Hzalways@ (posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)beginmclk <=1'b0;cnt <=24'd0;endelse if(cnt ==TIME-1'b1)beginmclk <=~mclk;cnt <=1'b0;endelse begincnt <=cnt + 1'b1;endend
endmodule

counter.v

module counter(ext_clk_25m,mclk,ext_rst_n,cnt_en,set_en,red,green,yellow,TimeH,TimeL,led);input           ext_clk_25m       ;//系统时钟input           mclk              ;//时钟信号input           ext_rst_n         ;//复位信号input           cnt_en            ;input           set_en            ;input     [7:0] red               ;input     [7:0] green             ;input     [7:0] yellow            ;output reg[3:0] TimeH             ;//两位数码管显示高位output reg[3:0] TimeL             ;//两位数码管显示低位output reg[2:0] led               ;//led指示状态reg       [2:0] state_c           ;reg       [2:0] state_n           ;reg       [7:0] times;parameter [2:0] IDLE =      3'b001,S1   =      3'b010,S2   =      3'b100;//状态机实现三种状态切换模块always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)beginstate_c <=IDLE;endelse if(set_en==1'b1)beginstate_c <= IDLE;endelse if(cnt_en==1'b1)beginstate_c <= state_c;endelse beginstate_c <= state_n;endend//状态切换always@(*)begincase(state_c)IDLE:beginif({TimeH,TimeL}==8'h01)beginstate_n=S1;endelse beginstate_n=IDLE;endendS1:beginif({TimeH,TimeL}==8'h01)beginstate_n=S2;endelse beginstate_n=S1;endendS2:beginif({TimeH,TimeL}==8'h01)beginstate_n=IDLE;endelse beginstate_n=S2;endenddefault:state_n=state_c;endcaseend	always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)begintimes <=8'd00;endelse if(set_en==1'b1)begintimes <=8'd00;endelse if(state_c==IDLE)begintimes <=red;endelse if(state_c==S1)begintimes <=green;endelse if(state_c==S2)begintimes <=yellow;endelse ;endalways@(posedge mclk or negedge ext_rst_n)beginif(!ext_rst_n)beginled <=3'b111;endelse if(state_c==IDLE)beginled<=3'b110;endelse if(state_c==S1)beginled<=3'b101;endelse if(state_c==S2)beginled<=3'b011;endelse beginled<=3'b111;endend
//计数器模块高位always@(posedge mclk or negedge ext_rst_n)beginif(!ext_rst_n)beginTimeH <=times[7:4];		//计数器赋初值endelse if(set_en==1'b1)beginTimeH <=times[7:4];endelse if(cnt_en==1'b1)beginTimeH <=TimeH;endelse if({TimeH,TimeL}==8'h00)beginTimeH <=times[7:4]; endelse if(TimeL==4'h0)beginTimeH <=TimeH-1'b1;endelse beginTimeH <=TimeH;endend//计数器模块低位always@(posedge mclk or negedge ext_rst_n)beginif(!ext_rst_n)beginTimeL <=times[3:0];endelse if(set_en==1'b1)beginTimeL <=times[3:0];endelse if(cnt_en==1'b1)beginTimeL <=TimeL;endelse if({TimeH,TimeL}==8'h00) beginTimeL <=times[3:0];endelse if(TimeL==4'h0)beginTimeL <=4'h9;endelse beginTimeL <=TimeL-1'b1;endend
endmodule

counter1.v

module counter1(ext_clk_25m,mclk,ext_rst_n,cnt_en,set_en,red,green,yellow,TimeH1,TimeL1,led);input           ext_clk_25m       ;//系统时钟input           mclk              ;//时钟信号input           ext_rst_n         ;//复位信号input           cnt_en            ;//使能信号input           set_en            ;input     [7:0] red               ;input     [7:0] green             ;input     [7:0] yellow            ;output reg[3:0] TimeH1            ;//两位数码管显示高位output reg[3:0] TimeL1            ;//两位数码管显示低位output reg[5:3] led               ;reg       [2:0] state_c           ;reg       [2:0] state_n           ;reg       [7:0] times1            ;parameter [2:0] IDLE =      3'b001,S1   =      3'b010,S2   =      3'b100;//状态切换模块always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)beginstate_c <=IDLE;endelse if(set_en==1'b1)beginstate_c <=IDLE;endelse if(cnt_en==1'b1)beginstate_c <= state_c;endelse beginstate_c <= state_n;endend//状态切换always@(*)begincase(state_c)IDLE:beginif({TimeH1,TimeL1}==8'h01)beginstate_n=S1;endelse beginstate_n=IDLE;endendS1:beginif({TimeH1,TimeL1}==8'h01)beginstate_n=S2;endelse beginstate_n=S1;endendS2:beginif({TimeH1,TimeL1}==8'h01)beginstate_n=IDLE;endelse beginstate_n=S2;endenddefault:state_n=state_c;endcaseend		always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)begintimes1 <=8'd00;endelse if(set_en==1'b1)begintimes1 <=8'd00;endelse if(state_c==IDLE)begintimes1 <=green;endelse if(state_c==S1)begintimes1 <=yellow;endelse if(state_c==S2)begintimes1 <=red;endelse ;endalways@(posedge mclk or negedge ext_rst_n)beginif(!ext_rst_n)beginled <=3'b111;endelse if(state_c==IDLE)beginled<=3'b101;endelse if(state_c==S1)beginled<=3'b011;endelse if(state_c==S2)beginled<=3'b110;endelse beginled<=3'b111;endend//计数器模块高位always@(posedge mclk or negedge ext_rst_n)beginif(!ext_rst_n)beginTimeH1 <=times1[7:4]; //计数器赋初值endelse if(set_en==1'b1)beginTimeH1<=TimeH1;endelse if(cnt_en==1'b1)beginTimeH1<=TimeH1;endelse if({TimeH1,TimeL1}==8'h00)beginTimeH1 <=times1[7:4]; //计数器赋初值endelse if(TimeL1==4'h0)beginTimeH1 <=TimeH1-1'b1;endelse beginTimeH1 <=TimeH1;endend//计数器模块低位always@(posedge mclk or negedge ext_rst_n)beginif(!ext_rst_n)beginTimeL1 <=times1[3:0];endelse if(set_en==1'b1)beginTimeL1 <=times1[3:0];endelse if(cnt_en==1'b1)beginTimeL1 <=TimeL1;endelse if({TimeH1,TimeL1}==8'h00)beginTimeL1 <=times1[3:0];endelse if(TimeL1==4'h0)beginTimeL1 <=4'h9;endelse beginTimeL1 <=TimeL1-1'b1;endend
endmodule

seg.v

module seg(ext_clk_25m,ext_rst_n,seg_en,set_en,set_segh,set_segl,TimeH,TimeL,TimeH1,TimeL1,dtube_cs_n,dtube_data);input           ext_clk_25m    ;//时钟信号25MHzinput           ext_rst_n      ;//复位信号input           seg_en         ;//使能信号input           set_en         ;//设置使能信号input    [ 3:0] set_segh       ;//设置信号显示高位input    [ 3:0] set_segl       ;//设置信号显示高位input    [ 3:0] TimeH          ;//两位输入高位  [0]input    [ 3:0] TimeL          ;//两位输入低位  [1]input    [ 3:0] TimeH1         ;//两位输入高位  [2]input    [ 3:0] TimeL1         ;//两位输入低位  [3]output   [ 3:0] dtube_cs_n     ;//段选数据位output   [ 6:0] dtube_data     ;//位选数据位reg      [ 3:0] dtube_cs_n     ;reg      [ 6:0] dtube_data     ;reg      [ 3:0] display_num    ;//当前显示数据reg      [16:0] div_cnt        ;//延时计数器计数位//延时计数器模块always@ (posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n) begindiv_cnt <= 8'd0;endelse if(seg_en==1'b1)begindiv_cnt <= 8'd0;endelse if(div_cnt==17'd80000)begindiv_cnt <= 8'd0;		endelse begindiv_cnt <= div_cnt+1'b1;endend//显示当前的数据模块always @(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)begin display_num <= 4'h0;endelse if(div_cnt < 17'd20000)beginif(set_en==1'b0)begindisplay_num <= TimeL;endelse begindisplay_num <=set_segl;endendelse if((div_cnt>17'd20000)&(div_cnt <17'd40000))beginif(set_en==1'b0)begindisplay_num <= TimeH;endelse begindisplay_num<=set_segh;endendelse if((div_cnt>17'd40000)&(div_cnt < 17'd60000))begindisplay_num <=TimeL1;endelse begindisplay_num <=TimeH1;endend//段选数据译码模块(共阴数码管)always @(*)beginif(!ext_rst_n)begin dtube_data <= 8'h00;endelse begincase(display_num) 4'h0: dtube_data <= 8'h3f;4'h1: dtube_data <= 8'h06;4'h2: dtube_data <= 8'h5b;4'h3: dtube_data <= 8'h4f;4'h4: dtube_data <= 8'h66;4'h5: dtube_data <= 8'h6d;4'h6: dtube_data <= 8'h7d;4'h7: dtube_data <= 8'h07;4'h8: dtube_data <= 8'h7f;4'h9: dtube_data <= 8'h6f;default:dtube_data <= 8'h00;endcaseendend
//位选选译模块always @(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n) begindtube_cs_n <=  4'b1111;endelse if(seg_en==1'b1)begindtube_cs_n <=  4'b1111;endelse if(div_cnt <= 17'd20000)begindtube_cs_n <= 4'b1110;endelse if((div_cnt>17'd20000)&(div_cnt <=17'd40000))begindtube_cs_n <= 4'b1101;end else if((div_cnt>17'd40000)&(div_cnt <=17'd60000)&(set_en==1'b0))begindtube_cs_n <= 4'b1011;endelse if((div_cnt>17'd60000)&(div_cnt <=17'd80000)&(set_en==1'b0))begindtube_cs_n <=4'b0111;endelse begindtube_cs_n <=  4'b1111;endendendmodule

设置时间模块

module set(ext_clk_25m,ext_rst_n,set_en,key_upup,key_down,key_entr,red,yellow,green,led,times1,times2);input ext_clk_25m;input ext_rst_n;input set_en;input key_down;input key_entr;input key_upup;output reg[7:0] red;output reg[7:0] green;output reg[7:0] yellow;output reg[3:0] times1;output reg[3:0] times2;output reg[7:6] led;//按键抖动判断逻辑wire key;  //所有的按键相与的结果,用于按键触发判断reg[3:0]keyr ; //按键值key的缓冲寄存器assign key =key_down&key_entr&key_upup;always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)keyr <=4'b1111;elsekeyr <={keyr[2:0],key};endwire key_neg;wire key_pos;assign key_neg=~keyr[2] &keyr [3];//有按键被按下assign key_pos=keyr[2] &~keyr [3];//	有按键被释放//定时器计数逻辑,用于对按键的消抖的判断reg [19:0] cnt;always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)begincnt <=20'd0;endelse if(key_pos||key_neg)begincnt <=20'd0;endelse if(cnt <20'd999_999)begincnt <= cnt +1'b1;endelse begincnt <=20'd0;endendreg[2:0]key_value_c;reg[2:0]key_value_n;//定时采取按键值always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginkey_value_c <=3'b111;key_value_n <=3'b111;endelse beginkey_value_n <=key_value_c;if(cnt ==20'd999_999)beginkey_value_c <={key_upup,key_entr,key_down};endelse;end	endwire [2:0]key_press;assign key_press=key_value_n & ~key_value_c;always@(*)beginif(ext_rst_n==1'b0)begintimes1=red[7:4];endelse begintimes1=times[7:4];endendalways@(*)beginif(ext_rst_n==1'b0)begintimes2=red[3:0];endelse begintimes2=times[3:0];endend//显示控制模块reg [1:0]state;//设置状态always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginstate<=2'b00;endelse if((key_press[1]==1'b1)&set_en==1'b1)beginif(state==2'b10)beginstate<=2'b00;endelse beginstate<=state+1'b1;endendendreg [7:0]times;//显示的状态模块always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)begintimes<=red;endelse if(state==2'b00)begintimes<=red;endelse if(state==2'b01)begintimes<=green;endelse if(state==2'b10)begintimes<=yellow;endelse begintimes<=8'h00;endend//led指示模式模式always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(!ext_rst_n)beginled <=2'b11;endelse if(state==2'b00&set_en==1'b1)beginled<=2'b10;endelse if(state==2'b01&set_en==1'b1)beginled<=2'b01;endelse if(state==2'b10&set_en==1'b1)beginled<=2'b00;endelse beginled<=2'b11;endend//按键加减控制模块(低位)  红always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginred[3:0]<=4'h0;endelse if(state==2'b00)beginif(key_press[2]==1'b1)beginif(red==8'h99) beginred[3:0]<=4'h0;endelse if(red[3:0]==4'h9)beginred[3:0]<=4'h0;endelse beginred[3:0]<=red[3:0]+1'b1;endendelse if(key_press[0]==1'b1)beginif(red==8'h00)beginred[3:0] <=4'h9; endelse if(red[3:0]==4'h0)beginred[3:0]<=4'h9;endelse beginred[3:0]<=red[3:0]-1'b1;endendelse beginred[3:0]<=red[3:0];endendelse beginred[3:0]<=red[3:0];endend//按键加减控制模块(高位)  红always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginred[7:4]<=4'h2;endelse if(state==2'b00)beginif(key_press[2]==1'b1)beginif(red==8'h99) beginred[7:4]<=4'h0;endelse if(red[3:0]==4'h9)beginred[7:4]<=red[7:4]+1'b1;endelse beginred[7:4]<=red[7:4];endendelse if(key_press[0]==1'b1)beginif(red==8'h00)beginred[7:4]<=4'h9; endelse if(red[3:0]==4'h0)beginred[7:4] <=red[7:4]-1'b1;endelse beginred[7:4] <=red[7:4];endendelse beginred[7:4]<=red[7:4];endendelse beginred[7:4]<=red[7:4];endend//按键加减控制模块(低位)  绿always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)begingreen[3:0]<=4'h5;endelse if(state==2'b01)beginif(key_press[2]==1'b1)beginif(green==8'h99) begingreen[3:0]<=4'h0;endelse if(green[3:0]==4'h9)begingreen[3:0]<=4'h0;endelse begingreen[3:0]<=green[3:0]+1'b1;endendelse if(key_press[0]==1'b1)beginif(green==8'h00)begingreen[3:0] <=4'h9; endelse if(green[3:0]==4'h0)begingreen[3:0]<=4'h9;endelse begingreen[3:0]<=green[3:0]-1'b1;endendelse begingreen[3:0]<=green[3:0];endendelse begingreen[3:0]<=green[3:0];endend//按键加减控制模块(高位)  绿always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)begingreen[7:4]<=4'h1;endelse if(state==2'b01)beginif(key_press[2]==1'b1)beginif(green==8'h99) begingreen[7:4]<=4'h0;endelse if(green[3:0]==4'h9)begingreen[7:4]<=green[7:4]+1'b1;endelse begingreen[7:4]<=green[7:4];endendelse if(key_press[0]==1'b1)beginif(green==8'h00)begingreen[7:4]<=4'h9; endelse if(green[3:0]==4'h0)begingreen[7:4] <=green[7:4]-1'b1;endelse begingreen[7:4] <=green[7:4];endendelse begingreen[7:4]<=green[7:4];endendelse begingreen[7:4]<=green[7:4];endend//按键加减控制模块(低位)  黄always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginyellow[3:0]<=4'h5;endelse if(state==2'b10)beginif(key_press[2]==1'b1)beginif(yellow==8'h99) beginyellow[3:0]<=4'h0;endelse if(yellow[3:0]==4'h9)beginyellow[3:0]<=4'h0;endelse beginyellow[3:0]<=yellow[3:0]+1'b1;endendelse if(key_press[0]==1'b1)beginif(yellow==8'h00)beginyellow[3:0] <=4'h9; endelse if(yellow[3:0]==4'h0)beginyellow[3:0]<=4'h9;endelse beginyellow[3:0]<=yellow[3:0]-1'b1;endendelse beginyellow[3:0]<=yellow[3:0];end	endelse beginyellow[3:0]<=yellow[3:0];endend//按键加控制模块(高位)  黄always@(posedge ext_clk_25m or negedge ext_rst_n)beginif(ext_rst_n==1'b0)beginyellow[7:4]<=4'h0;endelse if(state==2'b10)beginif(key_press[2]==1'b1)beginif(yellow==8'h99) beginyellow[7:4]<=4'h0;endelse if(yellow[3:0]==4'h9)beginyellow[7:4]<=yellow[7:4]+1'b1;endelse beginyellow[7:4]<=yellow[7:4];endendelse if(key_press[0]==1'b1)beginif(yellow==8'h00)beginyellow[7:4]<=4'h9; endelse if(yellow[3:0]==4'h0)beginyellow[7:4] <=yellow[7:4]-1'b1;endelse beginyellow[7:4] <=yellow[7:4];endendelse beginyellow[7:4]<=yellow[7:4];endendelse beginyellow[7:4]<=yellow[7:4];endend 
endmodule

设计顶层模块的RTL图

FPGA-任务五、十字路口交通控制灯器系统设计(二)-编程知识网