前言
本文为Verilog实例开发的第二弹,缺少Verilog代码练手或者有些生疏的可以在这里参考一些设计实例进行练习。
本系列导航:
Verilog设计实例(一):自动售货机设计实例
交通信号灯设计实例
设计一个交通灯控制电路,红灯30s后转为绿灯。共x,y方向两组交通灯,每组红绿灯各一个,红灯亮30s,绿灯亮30s,设系统时钟频率为50MHz,要求用数码管显示计时结果。
状态转换图
实现框架
信号灯结构框架如图所示,需要实现的模块有分频器、计数器、BCD码以及译码器,还包括状态转换和状态输出部分。
Verilog实现
定义模块和IO端口
`timescale 1ns / 1ps
module trafficlight(
clk_1Hz,
rst,
ledR_H,
ledG_H,
ledR_V,
ledG_V,
seg7_VH, //数码管显示-高位
seg7_VL, //数码管显示-低位
led15 //状态指示
);
parameter S1 = 1;//x方向红灯亮,y方向绿灯亮
parameter S2 = 0;//x方向绿灯亮,y方向红灯亮
input clk_50M,rst;
output reg ledG_H,ledG_V,ledR_H,ledR_V;
output wire [6:0] seg7_VH;
output wire [6:0] seg7_VL;
output wire led15;
实现分频器
reg clk_1Hz; //1Hz的分频器
reg [31:0] cnt_1Hz;
always@(posedge clk_50M or negedge rst)
begin
if(!rst)
begin
cnt_1Hz <= 1;
clk_1Hz <= 1;
end
else
begin
if(cnt_1Hz>=25000000)
begin
cnt_1Hz <= 1;
clk_1Hz <= ~clk_1Hz;
end
else
cnt_1Hz <= cnt_1Hz + 1;
end
end
实现计数器
reg [7:0] cnt30; //计数器
always @(posedge clk_1Hz or negedge rst)
begin
if(!rst)
begin
cnt30 <= 0;
end
else
begin
if (cnt30>=30)
begin
cnt30 <= 0;
end
else
cnt30 <= cnt30 + 1;
end
end
实现BCD码转换
reg [7:0] cntDis; //BCD码转换
always @(posedge clk_50M)
begin
if(cnt30 > 29)
begin
cntDis[7:4] <= 3;
cntDis[3:0] <= cnt30-30;
end
else if (cnt30 > 19)
begin
cntDis[7:4] <= 2;
cntDis[3:0] <= cnt30-20;
end
else if (cnt30 > 9)
begin
cntDis[7:4] <= 1;
cntDis[3:0] <= cnt30-10;
end
else
cntDis <= cnt30;
end
调用数码管译码器
数码管译码器实现(SEG7_LUT.v)
module SEG7_LUT (
input [3:0] iDIG,
output reg [6:0] oSEG
);
always@(iDIG)
begin
case(iDIG)
4'h1: oSEG = 7'b1111001; // ---t----
4'h2: oSEG = 7'b0100100; // | |
4'h3: oSEG = 7'b0110000; // lt rt
4'h4: oSEG = 7'b0011001; // | |
4'h5: oSEG = 7'b0010010; // ---m----
4'h6: oSEG = 7'b0000010; // | |
4'h7: oSEG = 7'b1111000; // lb rb
4'h8: oSEG = 7'b0000000; // | |
4'h9: oSEG = 7'b0011000; // ---b----
4'ha: oSEG = 7'b0001000;
4'hb: oSEG = 7'b0000011;
4'hc: oSEG = 7'b1000110;
4'hd: oSEG = 7'b0100001;
4'he: oSEG = 7'b0000110;
4'hf: oSEG = 7'b0001110;
default: oSEG = 7'b1000000;
endcase
end
endmodule
调用译码器实例
SEG7_LUT hex1(cntDis[3:0], seg7_VL[6:0]);
SEG7_LUT hex2(cntDis[7:4], seg7_VH[6:0]);
实现状态机
//状态转换
reg state;
always @(posedge clk_1Hz)
begin
case(state)
S1:
if (cnt30 >= 30) state <= S2;
S2:
if (cnt30 >= 30) state <= S1;
default:
state <= S1;
endcase
end
always @(posedge clk_50M or negedge rst)
begin
if(!rst)
begin
ledG_H <= 0;
ledG_V <= 0;
ledR_H <= 0;
ledR_V <= 0;
end
else
begin
case(state)
S1: //横向红灯亮,纵向绿灯亮
begin
ledG_H <= 0;
ledG_V <= 1;
ledR_H <= 1;
ledR_V <= 0;
end
S2: //横向绿灯,纵向红灯
begin
ledG_H <= 1;
ledG_V <= 0;
ledR_H <= 0;
ledR_V <= 1;
end
default:
begin
ledG_H <= 0;
ledG_V <= 0;
ledR_H <= 0;
ledR_V <= 0;
end
endcase
end
end
assign led15 = state; //状态指示
简单的TestBench编写
这里我没上板子跑,所以没用50MHz的时钟,直接给定了1Hz的时钟输入,有需要的可以自行修改。
module TL_tb();
reg clk_1Hz;
reg rst;
wire ledR_H;
wire ledG_H;
wire ledR_V;
wire ledG_V;
wire [6:0] seg7_VH; //数码管显示-高位
wire [6:0] seg7_VL; //数码管显示-低位
wire led15; //状态指示
trafficlight tl1(
.clk_1Hz(clk_1Hz),
.rst(rst),
.ledR_H(ledR_H),
.ledG_H(ledG_H),
.ledR_V(ledR_V),
.ledG_V(ledG_V),
.seg7_VH(seg7_VH),
.seg7_VL(seg7_VL),
.led15(led15)
);
initial begin
clk_1Hz = 0;
rst = 0;
#20;rst = 1;
//vivado中默认跑1000ns
end
always #5 clk_1Hz = ~clk_1Hz;
endmodule
测试波形
波形中,复位信号失效后,每三十个时钟周期,横向和纵向红绿灯的显示会交替。
文章来源:https://www.toymoban.com/news/detail-768809.html
总结
这是一个简单的红绿灯交替的例子,在此基础上,还可以添加黄灯状态,感兴趣的朋友可以自行尝试。本实例在时序逻辑电路的基础上还涉及到了分频器和BCD码、数码管等的实现,是一个比较典型的学习例子。文章来源地址https://www.toymoban.com/news/detail-768809.html
到了这里,关于Verilog设计实例(二):交通信号灯设计实例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!