完整功能:
实现主干道和支干道的红绿灯,并实现时间显示功能;(前两位显示东西的 后两位显示南北的)实现绿灯,黄灯,红灯的持续时间固定的交通控制功能;切换三段的显示 )状态机(当东西或南北两路中任一道上出现特殊情况,交通控制系统应可由交警手动控制立即进入特殊运行状态的功能;(控制一个SW[0]----> en 计数器计数半秒使能半秒)实现绿灯,黄灯,红灯的持续时间可调的交通控制功能(按键key_up 控制加 按键key_down 控制减);top.v改变为:
moduletop(ext_clk_25m,ext_rst_n,switch1,switch2,key_upup,key_down,key_entr,dtube_cs_n,dtube_data,led ); //顶层控制模块inputext_clk_25m; //时钟信号25MHzinputext_rst_n; //复位信号inputswitch1; inputswitch2; inputkey_upup; inputkey_entr; inputkey_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; wireen1; wireen2; wireset_en; wireclk;//中间变量//控制电路模块controlcon1( .ext_clk_25m(ext_clk_25m), .ext_rst_n(ext_rst_n), .switch1(switch1), .switch2(switch2), .en1(en1), .en2(en2), .set_en(set_en) ); //设置时间模块setset1( .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变为1HZdivd1( .ext_clk_25m(ext_clk_25m), .ext_rst_n(ext_rst_n), .mclk(clk) ); //倒计时计数模块(东西)counterc1( .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]) ); //倒计时计数模块(南北)counter1c2( .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]) ); //数码管显示模块(东西,南北)segs1( .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
控制电路模块:
modulecontrol(ext_clk_25m,ext_rst_n,switch1,switch2,en1,en2,set_en ); inputext_clk_25m; //输入时钟inputext_rst_n ; //复位信号inputswitch1 ; //特殊状态开关inputswitch2 ; //设置状态开关outputregen1 ; //数码管使能位outputregen2 ; //交通灯使能位outputregset_en ; //设置使能位reg [24:0] cnt ; //存放计数器的值parameterTIME=25'd2500_0000;//数码管特殊状态闪烁计数器模块always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)begincnt<=25'd0;endelseif(cnt==TIME-1'b1)begincnt<=1'b0;endelsebegincnt<=cnt+1'b1;endend//开关控制设置的开启always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginset_en<=1'b0;endelseif(switch2==1'b0)beginset_en<=1'b1;endelsebeginset_en<=1'b0;endend//数码管闪烁模块always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginen1<=1'b0;endelseif(switch1==1'b0)beginif(cnt<(TIME/2-1'b1))beginen1<=1'b1;endelsebeginen1<=1'b0;endendelsebeginen1<=1'b0;endend//停止计数器计时模块always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginen2<=1'b0;endelseif(switch1==1'b0)beginen2<=1'b1;endelsebeginen2<=1'b0;endendendmodule
分频模块:
modulediv(ext_clk_25m,ext_rst_n,mclk ); inputext_clk_25m ;//输入时钟inputext_rst_n ;//复位端口outputregmclk ;//输出1Hzreg [23:0] cnt ;//存放计数器的值parameterTIME=24'd1250_0000;//时钟25MHz//分频模块,使得输入时钟为25MHz输出时钟为1Hzalways (posedgeext_clk_25mornegedgeext_rst_n)beginif(!ext_rst_n)beginmclk<=1'b0;cnt<=24'd0;endelseif(cnt==TIME-1'b1)beginmclk<=~mclk; cnt<=1'b0;endelsebegincnt<=cnt+1'b1;endendendmodule
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)begin if(!ext_rst_n)begin state_c <=IDLE; end else if(set_en==1'b1)begin state_c <= IDLE; end else if(cnt_en==1'b1)begin state_c <= state_c; end else begin state_c <= state_n; end end //状态切换 always@(*) begin case(state_c) IDLE:begin if({TimeH,TimeL}==8'h01)begin state_n=S1; end else begin state_n=IDLE; end end S1:begin if({TimeH,TimeL}==8'h01)begin state_n=S2; end else begin state_n=S1; end end S2:begin if({TimeH,TimeL}==8'h01)begin state_n=IDLE; end else begin state_n=S2; end end default: state_n=state_c; endcase end always@(posedge ext_clk_25m or negedge ext_rst_n) begin if(!ext_rst_n)begin times <=8'd00; end else if(set_en==1'b1)begin times <=8'd00; end else if(state_c==IDLE)begin times <=red; end else if(state_c==S1)begin times <=green; end else if(state_c==S2)begin times <=yellow; end else ; end always@(posedge mclk or negedge ext_rst_n) begin if(!ext_rst_n)begin led <=3'b111; end else if(state_c==IDLE)begin led<=3'b110; end else if(state_c==S1)begin led<=3'b101; end else if(state_c==S2)begin led<=3'b011; end else begin led<=3'b111; end end //计数器模块高位 always@(posedge mclk or negedge ext_rst_n) begin if(!ext_rst_n)begin TimeH <=times[7:4]; //计数器赋初值 end else if(set_en==1'b1)begin TimeH <=times[7:4]; end else if(cnt_en==1'b1)begin TimeH <=TimeH; end else if({TimeH,TimeL}==8'h00)begin TimeH <=times[7:4]; end else if(TimeL==4'h0)begin TimeH <=TimeH-1'b1; end else begin TimeH <=TimeH; end end //计数器模块低位 always@(posedge mclk or negedge ext_rst_n)begin if(!ext_rst_n)begin TimeL <=times[3:0]; end else if(set_en==1'b1)begin TimeL <=times[3:0]; end else if(cnt_en==1'b1)begin TimeL <=TimeL; end else if({TimeH,TimeL}==8'h00) begin TimeL <=times[3:0]; end else if(TimeL==4'h0)begin TimeL <=4'h9; end else begin TimeL <=TimeL-1'b1; end end 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) begin if(!ext_rst_n)begin state_c <=IDLE; end else if(set_en==1'b1)begin state_c <=IDLE; end else if(cnt_en==1'b1)begin state_c <= state_c; end else begin state_c <= state_n; end end //状态切换 always@(*)begin case(state_c) IDLE:begin if({TimeH1,TimeL1}==8'h01)begin state_n=S1; end else begin state_n=IDLE; end end S1:begin if({TimeH1,TimeL1}==8'h01)begin state_n=S2; end else begin state_n=S1; end end S2:begin if({TimeH1,TimeL1}==8'h01)begin state_n=IDLE; end else begin state_n=S2; end end default: state_n=state_c; endcase end always@(posedge ext_clk_25m or negedge ext_rst_n) begin if(!ext_rst_n)begin times1 <=8'd00; end else if(set_en==1'b1)begin times1 <=8'd00; end else if(state_c==IDLE)begin times1 <=green; end else if(state_c==S1)begin times1 <=yellow; end else if(state_c==S2)begin times1 <=red; end else ; end always@(posedge mclk or negedge ext_rst_n) begin if(!ext_rst_n)begin led <=3'b111; end else if(state_c==IDLE)begin led<=3'b101; end else if(state_c==S1)begin led<=3'b011; end else if(state_c==S2)begin led<=3'b110; end else begin led<=3'b111; end end //计数器模块高位 always@(posedge mclk or negedge ext_rst_n)begin if(!ext_rst_n)begin TimeH1 <=times1[7:4]; //计数器赋初值 end else if(set_en==1'b1)begin TimeH1<=TimeH1; end else if(cnt_en==1'b1)begin TimeH1<=TimeH1; end else if({TimeH1,TimeL1}==8'h00)begin TimeH1 <=times1[7:4]; //计数器赋初值 end else if(TimeL1==4'h0)begin TimeH1 <=TimeH1-1'b1; end else begin TimeH1 <=TimeH1; end end //计数器模块低位 always@(posedge mclk or negedge ext_rst_n) begin if(!ext_rst_n)begin TimeL1 <=times1[3:0]; end else if(set_en==1'b1)begin TimeL1 <=times1[3:0]; end else if(cnt_en==1'b1)begin TimeL1 <=TimeL1; end else if({TimeH1,TimeL1}==8'h00)begin TimeL1 <=times1[3:0]; end else if(TimeL1==4'h0)begin TimeL1 <=4'h9; end else begin TimeL1 <=TimeL1-1'b1; end end endmodule
seg.v
moduleseg(ext_clk_25m,ext_rst_n,seg_en,set_en,set_segh,set_segl,TimeH,TimeL,TimeH1,TimeL1,dtube_cs_n,dtube_data ); inputext_clk_25m ;//时钟信号25MHzinputext_rst_n ;//复位信号inputseg_en ;//使能信号inputset_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 (posedgeext_clk_25mornegedgeext_rst_n)beginif(!ext_rst_n) begindiv_cnt<=8'd0;endelseif(seg_en==1'b1)begindiv_cnt<=8'd0;endelseif(div_cnt==17'd80000)begindiv_cnt<=8'd0; endelsebegindiv_cnt<=div_cnt+1'b1;endend//显示当前的数据模块always (posedgeext_clk_25mornegedgeext_rst_n)beginif(!ext_rst_n)begindisplay_num<=4'h0;endelseif(div_cnt<17'd20000)beginif(set_en==1'b0)begindisplay_num<=TimeL; endelsebegindisplay_num<=set_segl; endendelseif((div_cnt>17'd20000)&(div_cnt <17'd40000))beginif(set_en==1'b0)begindisplay_num<=TimeH; endelsebegindisplay_num<=set_segh; endendelseif((div_cnt>17'd40000)&(div_cnt < 17'd60000))begindisplay_num<=TimeL1; endelsebegindisplay_num<=TimeH1; endend//段选数据译码模块(共阴数码管)always (*)beginif(!ext_rst_n)begindtube_data<=8'h00;endelsebegincase(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 (posedgeext_clk_25mornegedgeext_rst_n)beginif(!ext_rst_n) begindtube_cs_n<=4'b1111;endelseif(seg_en==1'b1)begindtube_cs_n<=4'b1111;endelseif(div_cnt<=17'd20000)begindtube_cs_n<=4'b1110;endelseif((div_cnt>17'd20000)&(div_cnt <=17'd40000))begindtube_cs_n<=4'b1101;endelseif((div_cnt>17'd40000)&(div_cnt <=17'd60000)&(set_en==1'b0))begindtube_cs_n<=4'b1011;endelseif((div_cnt>17'd60000)&(div_cnt <=17'd80000)&(set_en==1'b0))begindtube_cs_n<=4'b0111;endelsebegindtube_cs_n<=4'b1111;endendendmodule
设置时间模块
moduleset(ext_clk_25m,ext_rst_n,set_en,key_upup,key_down,key_entr,red,yellow,green,led,times1,times2 ); inputext_clk_25m; inputext_rst_n; inputset_en; inputkey_down; inputkey_entr; inputkey_upup; outputreg[7:0] red; outputreg[7:0] green; outputreg[7:0] yellow; outputreg[3:0] times1; outputreg[3:0] times2; outputreg[7:6] led; //按键抖动判断逻辑wirekey; //所有的按键相与的结果,用于按键触发判断reg[3:0]keyr ; //按键值key的缓冲寄存器assignkey=key_down&key_entr&key_upup; always (posedgeext_clk_25mornegedgeext_rst_n)beginif(!ext_rst_n) keyr<=4'b1111;elsekeyr<={keyr[2:0],key}; endwirekey_neg; wirekey_pos; assignkey_neg=~keyr[2] &keyr [3];//有按键被按下assignkey_pos=keyr[2] &~keyr [3];// 有按键被释放//定时器计数逻辑,用于对按键的消抖的判断reg [19:0] cnt; always (posedgeext_clk_25mornegedgeext_rst_n)beginif(!ext_rst_n)begincnt<=20'd0;endelseif(key_pos||key_neg)begincnt<=20'd0;endelseif(cnt<20'd999_999)begincnt<=cnt+1'b1;endelsebegincnt<=20'd0;endendreg[2:0]key_value_c; reg[2:0]key_value_n; //定时采取按键值always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginkey_value_c<=3'b111;key_value_n<=3'b111;endelsebeginkey_value_n<=key_value_c; if(cnt==20'd999_999)beginkey_value_c<={key_upup,key_entr,key_down}; endelse; endendwire [2:0]key_press; assignkey_press=key_value_n&~key_value_c; always (*)beginif(ext_rst_n==1'b0)begintimes1=red[7:4]; endelsebegintimes1=times[7:4]; endendalways (*)beginif(ext_rst_n==1'b0)begintimes2=red[3:0]; endelsebegintimes2=times[3:0]; endend//显示控制模块reg [1:0]state; //设置状态always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginstate<=2'b00;endelseif((key_press[1]==1'b1)&set_en==1'b1)beginif(state==2'b10)beginstate<=2'b00;endelsebeginstate<=state+1'b1;endendendreg [7:0]times; //显示的状态模块always (posedgeext_clk_25mornegedgeext_rst_n)beginif(!ext_rst_n)begintimes<=red; endelseif(state==2'b00)begintimes<=red; endelseif(state==2'b01)begintimes<=green; endelseif(state==2'b10)begintimes<=yellow; endelsebegintimes<=8'h00;endend//led指示模式模式always (posedgeext_clk_25mornegedgeext_rst_n)beginif(!ext_rst_n)beginled<=2'b11;endelseif(state==2'b00&set_en==1'b1)beginled<=2'b10;endelseif(state==2'b01&set_en==1'b1)beginled<=2'b01;endelseif(state==2'b10&set_en==1'b1)beginled<=2'b00;endelsebeginled<=2'b11;endend//按键加减控制模块(低位) 红always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginred[3:0]<=4'h0;endelseif(state==2'b00)beginif(key_press[2]==1'b1)beginif(red==8'h99) beginred[3:0]<=4'h0;endelseif(red[3:0]==4'h9)beginred[3:0]<=4'h0;endelsebeginred[3:0]<=red[3:0]+1'b1;endendelseif(key_press[0]==1'b1)beginif(red==8'h00)beginred[3:0] <=4'h9; endelseif(red[3:0]==4'h0)beginred[3:0]<=4'h9;endelsebeginred[3:0]<=red[3:0]-1'b1;endendelsebeginred[3:0]<=red[3:0]; endendelsebeginred[3:0]<=red[3:0]; endend//按键加减控制模块(高位) 红always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginred[7:4]<=4'h2;endelseif(state==2'b00)beginif(key_press[2]==1'b1)beginif(red==8'h99) beginred[7:4]<=4'h0;endelseif(red[3:0]==4'h9)beginred[7:4]<=red[7:4]+1'b1;endelsebeginred[7:4]<=red[7:4]; endendelseif(key_press[0]==1'b1)beginif(red==8'h00)beginred[7:4]<=4'h9; endelseif(red[3:0]==4'h0)beginred[7:4] <=red[7:4]-1'b1;endelsebeginred[7:4] <=red[7:4]; endendelsebeginred[7:4]<=red[7:4]; endendelsebeginred[7:4]<=red[7:4]; endend//按键加减控制模块(低位) 绿always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)begingreen[3:0]<=4'h5;endelseif(state==2'b01)beginif(key_press[2]==1'b1)beginif(green==8'h99) begingreen[3:0]<=4'h0;endelseif(green[3:0]==4'h9)begingreen[3:0]<=4'h0;endelsebegingreen[3:0]<=green[3:0]+1'b1;endendelseif(key_press[0]==1'b1)beginif(green==8'h00)begingreen[3:0] <=4'h9; endelseif(green[3:0]==4'h0)begingreen[3:0]<=4'h9;endelsebegingreen[3:0]<=green[3:0]-1'b1;endendelsebegingreen[3:0]<=green[3:0]; endendelsebegingreen[3:0]<=green[3:0]; endend//按键加减控制模块(高位) 绿always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)begingreen[7:4]<=4'h1;endelseif(state==2'b01)beginif(key_press[2]==1'b1)beginif(green==8'h99) begingreen[7:4]<=4'h0;endelseif(green[3:0]==4'h9)begingreen[7:4]<=green[7:4]+1'b1;endelsebegingreen[7:4]<=green[7:4]; endendelseif(key_press[0]==1'b1)beginif(green==8'h00)begingreen[7:4]<=4'h9; endelseif(green[3:0]==4'h0)begingreen[7:4] <=green[7:4]-1'b1;endelsebegingreen[7:4] <=green[7:4]; endendelsebegingreen[7:4]<=green[7:4]; endendelsebegingreen[7:4]<=green[7:4]; endend//按键加减控制模块(低位) 黄always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginyellow[3:0]<=4'h5;endelseif(state==2'b10)beginif(key_press[2]==1'b1)beginif(yellow==8'h99) beginyellow[3:0]<=4'h0;endelseif(yellow[3:0]==4'h9)beginyellow[3:0]<=4'h0;endelsebeginyellow[3:0]<=yellow[3:0]+1'b1;endendelseif(key_press[0]==1'b1)beginif(yellow==8'h00)beginyellow[3:0] <=4'h9; endelseif(yellow[3:0]==4'h0)beginyellow[3:0]<=4'h9;endelsebeginyellow[3:0]<=yellow[3:0]-1'b1;endendelsebeginyellow[3:0]<=yellow[3:0]; endendelsebeginyellow[3:0]<=yellow[3:0]; endend//按键加控制模块(高位) 黄always (posedgeext_clk_25mornegedgeext_rst_n)beginif(ext_rst_n==1'b0)beginyellow[7:4]<=4'h0;endelseif(state==2'b10)beginif(key_press[2]==1'b1)beginif(yellow==8'h99) beginyellow[7:4]<=4'h0;endelseif(yellow[3:0]==4'h9)beginyellow[7:4]<=yellow[7:4]+1'b1;endelsebeginyellow[7:4]<=yellow[7:4]; endendelseif(key_press[0]==1'b1)beginif(yellow==8'h00)beginyellow[7:4]<=4'h9; endelseif(yellow[3:0]==4'h0)beginyellow[7:4] <=yellow[7:4]-1'b1;endelsebeginyellow[7:4] <=yellow[7:4]; endendelsebeginyellow[7:4]<=yellow[7:4]; endendelsebeginyellow[7:4]<=yellow[7:4]; endendendmodule
设计顶层模块的RTL图