**
**
此信号灯主要应用在主路与次路相交的交叉口处,信号灯共分为4个不同的状态,利用Moore型状态机实现,用六个灯代表主路与次路的六个信号灯(红、绿、黄),高电平时信号灯亮,低电平时灭。同时用4个数码管分别显示主路与次路当前信号状态下的剩余时间,并设置复位信号按键rst。
**
**
整个电路可以分为4个部分,分别是时钟模块、BCD码与二进制转换模块、状态机模块、数码管显示模块。Zero1为复位按键,cp为输入的100MHZ时钟信号,red1、yellow1、green1、red2、yellow2、green2为输出的信号灯状态,1代表亮,0代表灭。a_to_g则分别对应于数码管的显示,an则是数码管的位选端,下面分别介绍这几个模块的具体功能。
此模块的输入为EGO1开发板上的100MHZ时钟,对应着P17管脚,可将时钟信号进行分频,数码管显示需要200HZ的时钟信号,状态机需要1HZ的时钟信号,没有时钟信号,整个系统也将无法正常工作,时钟模块的核心代码如下所示:(时钟模块代码不需要这么长,这里粘贴的是100MHZ的大部分分频,方便后续复习)
module clk_div(
input CP_100MHz,
output clk_100MHz,
output clk_1kHz,
output clk_200Hz,
output clk_100Hz,
output clk_50Hz,
output clk_20Hz,
output clk_10Hz,
output clk_5Hz,
output clk_2Hz,
output clk_1Hz
);
reg [16 : 0] cnt_1kHz;
reg [2 : 0] cnt1_200Hz;
reg [2: 0] cnt2_200Hz;
reg [2 : 0] cnt_100Hz;
reg [3 : 0] cnt_50Hz;
reg [4 : 0] cnt_20Hz;
reg [5 : 0] cnt_10Hz;
reg [6 : 0] cnt_5Hz;
reg [7 : 0] cnt_2Hz;
reg [8 : 0] cnt_1Hz;
reg clk_1kHz_reg;
//reg clk_200Hz_reg;
reg clk_200Hz_reg1;
reg clk_200Hz_reg2;
reg clk_100Hz_reg;
reg clk_50Hz_reg;
reg clk_20Hz_reg;
reg clk_10Hz_reg;
reg clk_5Hz_reg;
reg clk_2Hz_reg;
reg clk_1Hz_reg;
initial
begin
cnt_1kHz=0;
cnt_100Hz=0;
cnt_50Hz=0;
cnt_20Hz=0;
cnt_10Hz=0;
cnt_5Hz=0;
cnt_2Hz=0;
cnt_1Hz=0;
clk_1kHz_reg=0;
clk_200Hz_reg1=0;
clk_200Hz_reg2=0;
clk_100Hz_reg=0;
clk_50Hz_reg=0;
clk_20Hz_reg=0;
clk_10Hz_reg=0;
clk_5Hz_reg=0;
clk_2Hz_reg=0;
clk_1Hz_reg=0;
end
always @ (posedge CP_100MHz)
begin
if (cnt_1kHz < 17'd100000/2-1)//17'h186A0=100000
begin
cnt_1kHz <= cnt_1kHz + 1;
clk_1kHz_reg <= clk_1kHz_reg;
end
else
begin
cnt_1kHz = 0;
clk_1kHz_reg <= ~clk_1kHz_reg;
end
end
//200Hz
always @ (posedge clk_1kHz)
begin
if (cnt1_200Hz < 3'd5-1)
cnt1_200Hz <= cnt1_200Hz + 1;
else
cnt1_200Hz <= 0;
end
always @ (posedge clk_1kHz)
begin
if (cnt1_200Hz < 3'd5/2)
clk_200Hz_reg1 <= 1;
else
clk_200Hz_reg1 <= 0;
end
always @ (negedge clk_1kHz)
begin
if (cnt2_200Hz < 3'd5-1)
cnt2_200Hz <= cnt2_200Hz + 1;
else
cnt2_200Hz <= 0;
end
always @ (negedge clk_1kHz)
begin
if (cnt2_200Hz < 3'd5/2)
clk_200Hz_reg2 <= 1;
else
clk_200Hz_reg2 = 0;
end
assign clk_200Hz=clk_200Hz_reg1|clk_200Hz_reg2;
//100Hz
always @ (posedge clk_1kHz)
begin
if (cnt_100Hz < 4'd10/2-1)
begin
cnt_100Hz <= cnt_100Hz + 1;
clk_100Hz_reg <= clk_100Hz_reg;
end
else
begin
cnt_100Hz = 0;
clk_100Hz_reg <= ~clk_100Hz_reg;
end
end
//50Hz
always @ (posedge clk_1kHz)
begin
if (cnt_50Hz < 5'd20/2-1)
begin
cnt_50Hz <= cnt_50Hz + 1;
clk_50Hz_reg <= clk_50Hz_reg;
end
else
begin
cnt_50Hz = 0;
clk_50Hz_reg <= ~clk_50Hz_reg;
end
end
//20Hz
always @ (posedge clk_1kHz)
begin
if (cnt_20Hz < 6'd50/2-1)
begin
cnt_20Hz <= cnt_20Hz + 1;
clk_20Hz_reg <= clk_20Hz_reg;
end
else
begin
cnt_20Hz = 0;
clk_20Hz_reg <= ~clk_20Hz_reg;
end
end
//10Hz
always @ (posedge clk_1kHz)
begin
if (cnt_10Hz < 7'd100/2-1)
begin
cnt_10Hz <= cnt_10Hz + 1;
clk_10Hz_reg <= clk_10Hz_reg;
end
else
begin
cnt_10Hz = 0;
clk_10Hz_reg <= ~clk_10Hz_reg;
end
end
//5Hz
always @ (posedge clk_1kHz)
begin
if (cnt_5Hz < 8'd200/2-1)
begin
cnt_5Hz <= cnt_5Hz + 1;
clk_5Hz_reg <= clk_5Hz_reg;
end
else
begin
cnt_5Hz = 0;
clk_5Hz_reg <= ~clk_5Hz_reg;
end
end
//2Hz
always @ (posedge clk_1kHz)
begin
if (cnt_2Hz < 9'd500/2-1)
begin
cnt_2Hz <= cnt_2Hz + 1;
clk_2Hz_reg <= clk_2Hz_reg;
end
else
begin
cnt_2Hz = 0;
clk_2Hz_reg <= ~clk_2Hz_reg;
end
end
//1Hz
always @ (posedge clk_1kHz)
begin
if (cnt_1Hz < 10'd1000/2-1)
begin
cnt_1Hz <= cnt_1Hz + 1;
clk_1Hz_reg <= clk_1Hz_reg;
end
else
begin
cnt_1Hz = 0;
clk_1Hz_reg <= ~clk_1Hz_reg;
end
end
assign clk_100MHz = CP_100MHz;
assign clk_1kHz = clk_1kHz_reg;
assign clk_100Hz = clk_100Hz_reg;
assign clk_50Hz = clk_50Hz_reg;
assign clk_20Hz = clk_20Hz_reg;
assign clk_10Hz = clk_10Hz_reg;
assign clk_5Hz = clk_5Hz_reg;
assign clk_2Hz = clk_2Hz_reg;
assign clk_1Hz = clk_1Hz_reg;
endmodule
**
**
此模块的输入为复位信号rst以及时钟信号clk,输出为red1,yellow1,green1;red2,
yellow2,green2。高电平时亮,低电平时灭,利用Moore型状态机实现,整个信号灯周期共分为4个状态,状态表如下图所示:
利用Verilog语言实现过程如下:
module state( input rst,clk,
output red1,yellow1,green1,red2,yellow2,green2,
output [7:0] counter_x,counter_y);
reg red1,yellow1,green1,red2,yellow2,green2;
reg [3:0] current_state,next_state;
reg [7:0] counter,counter_x,counter_y,timeover,timeover_x,timeover_y;
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
parameter time1 = 'd24, time2 = 'd4;
//状态转换
always @(posedge clk or negedge rst)
if(!rst)
begin
current_state <= S0;
counter <= time1;
counter_x <= 'd24;
counter_y <= 'd29;
end
else
begin
if(counter == 0)
begin
current_state <= next_state;
counter <= timeover;
counter_x <= timeover_x;
counter_y <= timeover_y;
end
else
begin
counter <= counter - 1;
counter_x <= counter_x - 1;
counter_y <= counter_y -1;
end
end
//状态改变
always @(current_state)
begin
case(current_state)
S0:begin //横向绿灯,纵向红灯
red1 = 0; yellow1 = 0; green1 = 1;
red2 = 1; yellow2 = 0; green2 = 0;
next_state <= S1; timeover <= time2;
timeover_x <= 'd4;
timeover_y <= 'd4;
end
S1:begin //横向黄灯,纵向红灯
red1 = 0; yellow1 = 1; green1 = 0;
red2 = 1; yellow2 = 0; green2 = 0;
next_state <= S2; timeover <= time1;
timeover_x <= 'd29;
timeover_y <= 'd24;
end
S2:begin //横向红灯,纵向绿灯
red1 = 1; yellow1 = 0; green1 = 0;
red2 = 0; yellow2 = 0; green2 = 1;
next_state <= S3; timeover <= time2;
timeover_x <= 'd4;
timeover_y <= 'd4;
end
S3:begin //横向红灯,纵向黄灯
red1 = 1; yellow1 = 0; green1 = 0;
red2 = 0; yellow2 = 1; green2 = 0;
next_state <= S1; timeover <= time1;
timeover_x <= 'd24;
timeover_y <= 'd29;
end
default:begin //横向绿灯,纵向红灯
red1 = 0; yellow1 = 0; green1 = 1;
red2 = 1; yellow2 = 0; green2 = 0;
next_state <= S1; timeover <= time2;
timeover_x <= 'd4;
timeover_y <= 'd4;
end
endcase
end
endmodule
此模块的输入为状态机模块的counter_x与counter_y输出,分别表示主路与次路当前状态下所剩余的时间,但它们均是由二进制数表示的,为了让数码管可以正常显示,需要借助BCD码来实现,也就是将二进制转换成BCD码,此次设计采用大4加3移位算法,算法原理如下:
利用Verilog语言实现的过程如下:
module binbcd8 (
input wire [7:0] b,
output reg [9:0] p
);
// 中间变量
reg [17:0] z;//8位输入,10位输出,共18个数
integer i;
always @ ( * ) //always模块中的任何一个输入信号或电平发生变化时,该语句下方的模块将被执行
begin
for (i = 0; i <=17; i = i + 1)
z[i] = 0;
z[10:3] = b; // 向左移3位,8421码,左移两位均不会大于等于5
repeat (5) // 重复5次
begin
if (z[11:8] > 4) // 如果个位大于4
z[11:8] = z[11:8] +3; // 加3
if (z[15:12] > 4) // 如果十位大于4
z[15:12] = z[15:12] +3; // 加3
z[17:1] = z[16:0]; // 左移一位
end
p = z[17:8]; // BCD
end
endmodule
此模块的输入为二进制转换为BCD码模块的输出,用来使数码管正确的显示十进制数,也就是此次实验设计中的各个信号灯所剩余的时间,利用Verilog语言实现的过程如下:
module hx7seg(
input wire [11:0] x,//4的倍数,12位
input wire cclk,//保证有一个足够的频率。一般工作在200HZ
input wire clr,//清零端
output reg [6:0] a_to_g,
output reg [1:0] an//位选端,控制数码管的选择
);
reg s;
reg [3:0] digit;
// 2-位计数器
always @ (posedge cclk or posedge clr)
begin
if (clr ==1)//高电平清零
s <= 0;
else
s <= s + 1;
end
// Quad 4-to-1 MUX: mux44
always @ ( * )//always模块中的任何一个输入信号或电平发生变化时,该语句下方的模块将被执行。
case (s)//本项目中的所有时间均是两位数,因此s有两种状态即可
0: digit = x[3:0];
1: digit = x[7:4];
default: digit = x[11:8];
endcase
// 选择数码管
always @ ( * )
begin
an = 2'b00;
an[s] = 1;
end
// 7段解码器:hex7seg
always @ ( * )
case (digit)
0: a_to_g = 7'b1111110;
1: a_to_g = 7'b0110000;
2: a_to_g = 7'b1101101;
3: a_to_g = 7'b1111001;
4: a_to_g = 7'b0110011;
5: a_to_g = 7'b1011011;
6: a_to_g = 7'b1011111;
7: a_to_g = 7'b1110000;
8: a_to_g = 7'b1111111;
9: a_to_g = 7'b1111011;
'hA: a_to_g = 7'b1110111;
'hB: a_to_g = 7'b0011111;
'hC: a_to_g = 7'b1001110;
'hD: a_to_g = 7'b0111101;
'hE: a_to_g = 7'b1001111;
'hF: a_to_g = 7'b1000111;
default: a_to_g = 7'b0000000; // 空白
endcase
endmodule
set_property IOSTANDARD LVCMOS33 [get_ports zero1]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g0[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g0[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g0[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g0[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g0[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g0[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g0[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g1[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g1[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g1[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g1[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g1[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g1[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {a_to_g1[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an0[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an0[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an1[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {an1[0]}]
set_property PACKAGE_PIN P5 [get_ports zero1]
set_property PACKAGE_PIN P4 [get_ports zero2]
set_property IOSTANDARD LVCMOS33 [get_ports cp]
set_property IOSTANDARD LVCMOS33 [get_ports green1]
set_property IOSTANDARD LVCMOS33 [get_ports red1]
set_property IOSTANDARD LVCMOS33 [get_ports green2]
set_property IOSTANDARD LVCMOS33 [get_ports red2]
set_property IOSTANDARD LVCMOS33 [get_ports yellow2]
set_property IOSTANDARD LVCMOS33 [get_ports yellow1]
set_property IOSTANDARD LVCMOS33 [get_ports zero2]
set_property PACKAGE_PIN P17 [get_ports cp]
set_property PACKAGE_PIN J3 [get_ports red1]
set_property PACKAGE_PIN J2 [get_ports yellow1]
set_property PACKAGE_PIN K2 [get_ports green1]
set_property PACKAGE_PIN L1 [get_ports red2]
set_property PACKAGE_PIN M1 [get_ports yellow2]
set_property PACKAGE_PIN K3 [get_ports green2]
set_property PACKAGE_PIN C1 [get_ports {an0[1]}]
set_property PACKAGE_PIN H1 [get_ports {an0[0]}]
set_property PACKAGE_PIN E1 [get_ports {an1[1]}]
set_property PACKAGE_PIN G6 [get_ports {an1[0]}]
set_property PACKAGE_PIN B4 [get_ports {a_to_g0[6]}]
set_property PACKAGE_PIN A4 [get_ports {a_to_g0[5]}]
set_property PACKAGE_PIN A3 [get_ports {a_to_g0[4]}]
set_property PACKAGE_PIN B1 [get_ports {a_to_g0[3]}]
set_property PACKAGE_PIN A1 [get_ports {a_to_g0[2]}]
set_property PACKAGE_PIN B3 [get_ports {a_to_g0[1]}]
set_property PACKAGE_PIN B2 [get_ports {a_to_g0[0]}]
set_property PACKAGE_PIN D4 [get_ports {a_to_g1[6]}]
set_property PACKAGE_PIN E3 [get_ports {a_to_g1[5]}]
set_property PACKAGE_PIN D3 [get_ports {a_to_g1[4]}]
set_property PACKAGE_PIN F4 [get_ports {a_to_g1[3]}]
set_property PACKAGE_PIN F3 [get_ports {a_to_g1[2]}]
set_property PACKAGE_PIN E2 [get_ports {a_to_g1[1]}]
set_property PACKAGE_PIN D2 [get_ports {a_to_g1[0]}]
视频链接如下所示:
视频展示
项目在Vivado运行一切正常,实验所用设备为EGO1开发板,源文件链接如下:(bit流文件与记忆文件均已生成,在traffic文件中,下载后可正常测试)
百度网盘链接分享
提取码:0000
–来自百度网盘超级会员V4的分享
首次blog,多多关照!!!