完整功能:
实现主干道和支干道的红绿灯,并实现时间显示功能;(前两位显示东西的 后两位显示南北的)
实现绿灯,黄灯,红灯的持续时间固定的交通控制功能;
(状态机切换三段的显示 )
当东西或南北两路中任一道上出现特殊情况,交通控制系统应可由交警手动控制立即进入特殊运行状态的功能;(控制一个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图