赞
踩
本文为Verilog实例开发的第二弹,缺少Verilog代码练手或者有些生疏的可以在这里参考一些设计实例进行练习。
本系列导航:
Verilog设计实例(一):自动售货机设计实例
设计一个交通灯控制电路,红灯30s后转为绿灯。共x,y方向两组交通灯,每组红绿灯各一个,红灯亮30s,绿灯亮30s,设系统时钟频率为50MHz,要求用数码管显示计时结果。
信号灯结构框架如图所示,需要实现的模块有分频器、计数器、BCD码以及译码器,还包括状态转换和状态输出部分。
`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
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
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; //状态指示
这里我没上板子跑,所以没用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
波形中,复位信号失效后,每三十个时钟周期,横向和纵向红绿灯的显示会交替。
这是一个简单的红绿灯交替的例子,在此基础上,还可以添加黄灯状态,感兴趣的朋友可以自行尝试。本实例在时序逻辑电路的基础上还涉及到了分频器和BCD码、数码管等的实现,是一个比较典型的学习例子。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。