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

网友投稿 273 2022-09-21

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

完整功能:

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

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

当东西或南北两路中任一道上出现特殊情况,交通控制系统应可由交警手动控制立即进入特殊运行状态的功能;(控制一个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; //时钟信号25MHz input 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变为1HZ div 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)begin if(ext_rst_n==1'b0)begin cnt <=25'd0; end else if(cnt ==TIME-1'b1)begin cnt <=1'b0; end else begin cnt <=cnt + 1'b1; end end //开关控制设置的开启 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin set_en <=1'b0; end else if(switch2==1'b0)begin set_en <=1'b1; end else begin set_en <=1'b0; end end //数码管闪烁模块 always @(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin en1<=1'b0; end else if(switch1==1'b0)begin if(cnt<(TIME/2-1'b1))begin en1<=1'b1; end else begin en1<=1'b0; end end else begin en1<=1'b0; end end //停止计数器计时模块 always @(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin en2<=1'b0; end else if(switch1==1'b0)begin en2<=1'b1; end else begin en2<=1'b0; end end endmodule

分频模块:

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

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 endendmodule

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 endendmodule

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 ;//时钟信号25MHz input 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)begin if(!ext_rst_n) begin div_cnt <= 8'd0; end else if(seg_en==1'b1)begin div_cnt <= 8'd0; end else if(div_cnt==17'd80000)begin div_cnt <= 8'd0; end else begin div_cnt <= div_cnt+1'b1; end end //显示当前的数据模块 always @(posedge ext_clk_25m or negedge ext_rst_n)begin if(!ext_rst_n)begin display_num <= 4'h0; end else if(div_cnt < 17'd20000)begin if(set_en==1'b0)begin display_num <= TimeL; end else begin display_num <=set_segl; end end else if((div_cnt>17'd20000)&(div_cnt <17'd40000))begin if(set_en==1'b0)begin display_num <= TimeH; end else begin display_num<=set_segh; end end else if((div_cnt>17'd40000)&(div_cnt < 17'd60000))begin display_num <=TimeL1; end else begin display_num <=TimeH1; end end //段选数据译码模块(共阴数码管) always @(*)begin if(!ext_rst_n)begin dtube_data <= 8'h00; end else begin case(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; endcase end end//位选选译模块 always @(posedge ext_clk_25m or negedge ext_rst_n)begin if(!ext_rst_n) begin dtube_cs_n <= 4'b1111; end else if(seg_en==1'b1)begin dtube_cs_n <= 4'b1111; end else if(div_cnt <= 17'd20000)begin dtube_cs_n <= 4'b1110; end else if((div_cnt>17'd20000)&(div_cnt <=17'd40000))begin dtube_cs_n <= 4'b1101; end else if((div_cnt>17'd40000)&(div_cnt <=17'd60000)&(set_en==1'b0))begin dtube_cs_n <= 4'b1011; end else if((div_cnt>17'd60000)&(div_cnt <=17'd80000)&(set_en==1'b0))begin dtube_cs_n <=4'b0111; end else begin dtube_cs_n <= 4'b1111; end end endmodule

设置时间模块

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)begin if(!ext_rst_n) keyr <=4'b1111; else keyr <={keyr[2:0],key}; end wire 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)begin if(!ext_rst_n)begin cnt <=20'd0; end else if(key_pos||key_neg)begin cnt <=20'd0; end else if(cnt <20'd999_999)begin cnt <= cnt +1'b1; end else begin cnt <=20'd0; end end reg[2:0]key_value_c; reg[2:0]key_value_n; //定时采取按键值 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin key_value_c <=3'b111; key_value_n <=3'b111; end else begin key_value_n <=key_value_c; if(cnt ==20'd999_999)begin key_value_c <={key_upup,key_entr,key_down}; end else; end end wire [2:0]key_press; assign key_press=key_value_n & ~key_value_c; always@(*)begin if(ext_rst_n==1'b0)begin times1=red[7:4]; end else begin times1=times[7:4]; end end always@(*)begin if(ext_rst_n==1'b0)begin times2=red[3:0]; end else begin times2=times[3:0]; end end //显示控制模块 reg [1:0]state; //设置状态 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin state<=2'b00; end else if((key_press[1]==1'b1)&set_en==1'b1)begin if(state==2'b10)begin state<=2'b00; end else begin state<=state+1'b1; end end end reg [7:0]times; //显示的状态模块 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(!ext_rst_n)begin times<=red; end else if(state==2'b00)begin times<=red; end else if(state==2'b01)begin times<=green; end else if(state==2'b10)begin times<=yellow; end else begin times<=8'h00; end end //led指示模式模式 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(!ext_rst_n)begin led <=2'b11; end else if(state==2'b00&set_en==1'b1)begin led<=2'b10; end else if(state==2'b01&set_en==1'b1)begin led<=2'b01; end else if(state==2'b10&set_en==1'b1)begin led<=2'b00; end else begin led<=2'b11; end end //按键加减控制模块(低位) 红 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin red[3:0]<=4'h0; end else if(state==2'b00)begin if(key_press[2]==1'b1)begin if(red==8'h99) begin red[3:0]<=4'h0; end else if(red[3:0]==4'h9)begin red[3:0]<=4'h0; end else begin red[3:0]<=red[3:0]+1'b1; end end else if(key_press[0]==1'b1)begin if(red==8'h00)begin red[3:0] <=4'h9; end else if(red[3:0]==4'h0)begin red[3:0]<=4'h9; end else begin red[3:0]<=red[3:0]-1'b1; end end else begin red[3:0]<=red[3:0]; end end else begin red[3:0]<=red[3:0]; end end //按键加减控制模块(高位) 红 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin red[7:4]<=4'h2; end else if(state==2'b00)begin if(key_press[2]==1'b1)begin if(red==8'h99) begin red[7:4]<=4'h0; end else if(red[3:0]==4'h9)begin red[7:4]<=red[7:4]+1'b1; end else begin red[7:4]<=red[7:4]; end end else if(key_press[0]==1'b1)begin if(red==8'h00)begin red[7:4]<=4'h9; end else if(red[3:0]==4'h0)begin red[7:4] <=red[7:4]-1'b1; end else begin red[7:4] <=red[7:4]; end end else begin red[7:4]<=red[7:4]; end end else begin red[7:4]<=red[7:4]; end end //按键加减控制模块(低位) 绿 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin green[3:0]<=4'h5; end else if(state==2'b01)begin if(key_press[2]==1'b1)begin if(green==8'h99) begin green[3:0]<=4'h0; end else if(green[3:0]==4'h9)begin green[3:0]<=4'h0; end else begin green[3:0]<=green[3:0]+1'b1; end end else if(key_press[0]==1'b1)begin if(green==8'h00)begin green[3:0] <=4'h9; end else if(green[3:0]==4'h0)begin green[3:0]<=4'h9; end else begin green[3:0]<=green[3:0]-1'b1; end end else begin green[3:0]<=green[3:0]; end end else begin green[3:0]<=green[3:0]; end end //按键加减控制模块(高位) 绿 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin green[7:4]<=4'h1; end else if(state==2'b01)begin if(key_press[2]==1'b1)begin if(green==8'h99) begin green[7:4]<=4'h0; end else if(green[3:0]==4'h9)begin green[7:4]<=green[7:4]+1'b1; end else begin green[7:4]<=green[7:4]; end end else if(key_press[0]==1'b1)begin if(green==8'h00)begin green[7:4]<=4'h9; end else if(green[3:0]==4'h0)begin green[7:4] <=green[7:4]-1'b1; end else begin green[7:4] <=green[7:4]; end end else begin green[7:4]<=green[7:4]; end end else begin green[7:4]<=green[7:4]; end end //按键加减控制模块(低位) 黄 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin yellow[3:0]<=4'h5; end else if(state==2'b10)begin if(key_press[2]==1'b1)begin if(yellow==8'h99) begin yellow[3:0]<=4'h0; end else if(yellow[3:0]==4'h9)begin yellow[3:0]<=4'h0; end else begin yellow[3:0]<=yellow[3:0]+1'b1; end end else if(key_press[0]==1'b1)begin if(yellow==8'h00)begin yellow[3:0] <=4'h9; end else if(yellow[3:0]==4'h0)begin yellow[3:0]<=4'h9; end else begin yellow[3:0]<=yellow[3:0]-1'b1; end end else begin yellow[3:0]<=yellow[3:0]; end end else begin yellow[3:0]<=yellow[3:0]; end end //按键加控制模块(高位) 黄 always@(posedge ext_clk_25m or negedge ext_rst_n)begin if(ext_rst_n==1'b0)begin yellow[7:4]<=4'h0; end else if(state==2'b10)begin if(key_press[2]==1'b1)begin if(yellow==8'h99) begin yellow[7:4]<=4'h0; end else if(yellow[3:0]==4'h9)begin yellow[7:4]<=yellow[7:4]+1'b1; end else begin yellow[7:4]<=yellow[7:4]; end end else if(key_press[0]==1'b1)begin if(yellow==8'h00)begin yellow[7:4]<=4'h9; end else if(yellow[3:0]==4'h0)begin yellow[7:4] <=yellow[7:4]-1'b1; end else begin yellow[7:4] <=yellow[7:4]; end end else begin yellow[7:4]<=yellow[7:4]; end end else begin yellow[7:4]<=yellow[7:4]; end end endmodule

设计顶层模块的RTL图

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:私域流量玩家注意了!微信又出新功能,群内直播终于落地!
下一篇:紫光同创PGL22-PDS如何进行安装破解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~