verilog入门实例<一>分频器,信号灯
verilog入门实例一
- 分频器设计,要求:对输入时钟clk,进行分2、5、10分频。例如输入时钟50Mhz,输出时钟就是25、10、5Mhz。
主要思路:
偶数分频:假设偶数为EVEN,对时钟信号周期进行计数,则先写一个模(EVEN)的计数器,只要计数至EVEN-1则使输出信号翻转,便形成了偶数分频。
奇数分频:由两个信号作或运算而成。假设奇数为ODD。第一个信号,以时钟信号的上跳沿进行计数,形成一个模(ODD)的计数器,令计数至0,1,2...(EVEN-3)/2全部为高电平,其他为低电平,形成一个占空比不为0.5的信号。第二个信号,以时钟的下跳沿进行计数,形成一个模(ODD)的计数器令计数至0,1,2...(EVEN-1)/2全部为高电平,其他为低电平,形成一个占空比不为0.5的信号。这两个信号做或运算则可形成奇数分频。举例:5分频。以时钟上跳沿计数,计数为0,1时为高电平,计数为2,3,4为低电平,如此形成一个信号1。同理以时钟下跳沿进行计数,计数为0,1时为高电平,计数为2,3,4为低电平,如此形成一个信号2。两个信号做或运算可以形成奇数分频信号。
module divider(
input clk;
input rst_n;
output clk_div2;
output clk_div5;
output clk_div10
);
reg [3:0]cnt1;
reg [3:0]cnt2;
reg [3:0]cnt3;
reg clk_div51,clk_div52;
parameter NUM_DIV_ODD ==5;
parameter NUM_DIV_EVEN ==10;
//二分频
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_div2 <= 1'b0;
else
clk_div2 <= ~clk_div2;
end
//奇数五分频由两个占空比为0.4的信号相和而成
//第一个上跳沿计数的信号clk_div51
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt1 <= 1'b0;
else if (cnt < NUM_DIV - 1)
cnt1 <= cnt1+1'b1;
else
cnt1 <= 1'b0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_div51 <= 1'b0;
else if(cnt1<NUM_DIV/2)
clk_div51 <=1'b1;
else
clk_div51 <= 1'b0;
end
//第二个下跳沿计数的信号clk_div52
always@(negedge clk or negedge rst_n)
begin
if(!rst_n)
cnt2 <= 1'b0;
else if (cnt < NUM_DIV -1 )
cnt2 <= cnt2 + 1'b1;
else
cnt <= 1'b0;
end
always@(negedge clk or negedge rst_n)
begin
if(!rst_n)
clk_div52 <= 1'b0;
else if (cnt2 < NUM_DIV/2)
clk_div52 <= 1'b1;
else
clk_div52 <= 1'b0;
end
assign clk_div5 <= clk_div51 | clk_div52;
//十分频
always@(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
clk_div10 <= 1'b0;
cnt3 <=0;
end
else if (cnt3 < NUM_DIV_EVEN/2)
begin
cnt3 <= cnt3 + 1'b1;
clk_div10 <= clk_div10;
end
else
begin
cnt3 <= 1'b0;
clk_div10 <= ~clk_div10;
end
end
endmodule
testbench
`timescale 1ns/1ps
module tb_divider;
reg clk;
reg rst_n;
wire clk_div2;
wire clk_div5;
wire clk_div10;
parameter TIME = 20;
divider uut(
.clk(clk),
.rst_div(rst_n),
.clk_div2(clk_div2),
.clk_div5(clk_div5),
.clk_div10(clk_div10)
);
always@ #(TIME/2) clk = ~clk;
initial
begin
clk = 0;
rst_n = 0;
#TIME rst_n = 1;
#(TiME * 80000) $finish;
end
endmodule
仿真效果:
其中clk_div51和clk_div52是奇数5分频的信号1和信号2。
- 信号灯
要求:东西方向和南北方向各有四盏灯,分别为左拐灯、绿灯、黄灯和红灯
东西方向信号灯的时间为:红灯55s,黄灯5s,绿灯40s,左拐灯15s;
南北方向信号灯的时间为:红灯65,黄灯5,绿灯30,左拐灯15s;
思路:把信号灯分为以上7种状态,由于有时间要求,则以5s记一次数,信号灯跑完整个过程,需要120s,则形成一个模24计数器,下面流程图中白色中的数字就是计数值。
真值表:
Light_ns(南北信号灯) | Light_ew(东西信号灯) | 状态 |
---|---|---|
左 绿 黄 红 | 左 绿 黄 红 | |
0 0 1 0 | 0 0 1 0 | IDLE |
1 0 0 0 | 0 0 0 1 | S1 |
0 1 0 0 | 0 0 0 1 | S2 |
0 0 1 0 | 0 0 0 1 | S3 |
0 0 0 1 | 1 0 0 0 | S4 |
0 0 0 1 | 0 1 0 0 | S5 |
0 0 0 1 | 0 0 1 0 | S6 |
流程图:
![](https://img2020.cnblogs.com/blog/2060646/202007/2060646-20200731120137356-89849863.png)
design
module signal_light(clk,rst_n,light_ns,light_ew,count);
input clk,rst_n;
output light_ns,light_ew;//ns:north sourth,ew:east west
output count;
//output clk_count;
reg[3:0]light_ns,light_ew;
reg[4:0]count;
reg[2:0]current_state,next_state;
parameter IDLE=3'b000;
parameter S1=3'b001;
parameter S2=3'b010;
parameter S3=3'b011;
parameter S4=3'b100;
parameter S5=3'b101;
parameter S6=3'b110;
// reg clk_count;
//reg count1;
//parameter T=9'd250000000;
/*
always@(posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
clk_count <= 1'b0;
cnt1 <=0;
end
else if (cnt1 < T/2)
begin
cnt1 <= cnt1 + 1'b1;
clk_count <= clk_count;
end
else
begin
cnt1 <= 1'b0;
clk_count <= ~clk_count;
end
end
*/
//counter
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
count<=1'b0;
else if(count==5'b10111)
count<=1'd0;
else
count<=count+1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
current_state<=IDLE;
else
current_state<=next_state;
end
always@(*)
begin
case(current_state)
IDLE:if(!count)next_state=S1;
else next_state=IDLE;
S1:if(count==2)next_state=S2;
else next_state=S3;
S2:if(count==9)next_state=S3;
else next_state=S2;
S3:begin
if(count==3)next_state=S2;
else
begin
if(count==10)next_state=S4;
else next_state=S3;
end
end
S4:if(count==13)next_state=S6;
else next_state=S4;
S5:if(count==22)next_state=S6;
else next_state=S5;
S6:begin
if(count==14)next_state=S5;
else
begin
if(count==23)next_state=S1;
else next_state=S6;
end
end
default:next_state=IDLE;
endcase
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
light_ns<=4'b0010;
light_ew<=4'b0010;
end
else
case(next_state)
IDLE :begin
light_ns<=4'b0010;
light_ew<=4'b0010;
end
S1 :begin
light_ns<=4'b1000;
light_ew<=4'b0001;
end
S2 :begin
light_ns<=4'b0100;
light_ew<=4'b0001;
end
S3 :begin
light_ns<=4'b0010;
light_ew<=4'b0001;
end
S4 :begin
light_ns<=4'b0001;
light_ew<=4'b1000;
end
S5 :begin
light_ns<=4'b0001;
light_ew<=4'b0100;
end
S6 :begin
light_ns<=4'b0001;
light_ew<=4'b0010;
end
default:begin
light_ns<=4'b0010;
light_ew<=4'b0010;
end
endcase
end
endmodule
testbench
`timescale 1ns/1ps
module tb_signal_light;
reg clk;
reg rst_n;
wire [4:0]count;
wire [3:0]light_ew;
wire [3:0]light_ns;
//wire clk_count;
parameter TIME=20;
signal_light uut(
.clk(clk),
.rst_n(rst_n),
.light_ns(light_ns),
.light_ew(light_ew),
.count(count)
//.clk_count(clk_count)
);
always #10 clk = ~clk;
initial
begin
clk = 0;
rst_n = 0;
#TIME rst_n = 1;
//#(TiME * 80000) $finish;
end
endmodule
仿真结果:
结果中还有一个问题就是未分频,应该是要写一个周期的5s的时钟信号。
分类:
Verilog
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!