🔈声明:
🔑未经作者允许,禁止转载
🚩推荐一个IC、FPGA新手入门的好网站:👉快 点 击 进 入 学 习 吧👈
# 题目 用verilog实现三分频电路,要求输出50%占空比
设计思路
如果不限制占空比50%的话,那么用counter做3进制计数,每次counter=1拉高,counter=2拉低即可,但是这样的占空比是1/3。
如果要做50占空比的三分频,则需要一个上升沿的六分频和一个下降沿的六分频组合来得到。
类似的奇分频都可以这样实现。
大致有三种组合方式都可以得到:
- 与
- 或
- 异或
后续将上升沿采样记为clk_pos,下降沿采样记为clk_neg
与逻辑分频
- 用与逻辑来组合,需要clk_pos和clk_neg拉高2T,但是其本身有0.5T的时序差
- 那么在cnt=0时,clk_pos拉高2拍
- cnt=0时,clk_neg拉高2拍
- 最后clk_pos & clk_neg 即为分频结果
下面是理论波形图方便理解。
代码
module div_and #(parameter n=5)
(
input clk,
input rstn,
output clk_div
);
reg [15:0] cnt;
reg clk_pos,clk_neg;
assign clk_div = clk_pos & clk_neg;
always @(posedge clk or negedge rstn)begin
if(!rstn)
cnt <= 0;
else if(cnt==n-1)
cnt <= 0;
else
cnt <= cnt + 1;
end
always @(posedge clk or negedge rstn)begin
if(!rstn)
clk_pos <= 1'b0;
else if(cnt==n-1)
clk_pos <= 1'b1;
else if(cnt==(n>>1))
clk_pos <= 1'b0;
end
always @(negedge clk or negedge rstn)begin
if(!rstn)
clk_neg <= 0;
else if(cnt==n-1)
clk_neg <= 1'b1;
else if (cnt==(n>>1))
clk_neg <= 1'b0;
end
endmodule
或逻辑分频
- 用或逻辑来组合,需要clk_pos和clk_neg只拉高1T,但是其本身有0.5T的时序差
- 那么在cnt=2时,clk_pos拉高1拍
- cnt=2时,clk_neg拉高1拍
- 最后clk_pos | clk_neg 即为分频结果
下面是理论波形图方便理解。
代码
module div_or #(parameter n=3)
(
input clk,
input rstn,
output clk_div
);
reg [15:0] cnt;
reg clk_pos,clk_neg;
assign clk_div = clk_pos | clk_neg;
always @(posedge clk or negedge rstn)begin
if(!rstn)
cnt <= 0;
else if(cnt==n-1)
cnt <= 0;
else
cnt <= cnt + 1;
end
always @(posedge clk or negedge rstn)begin
if(!rstn)
clk_pos <= 1'b0;
else if(cnt==n-1)
clk_pos <= 1'b1;
else
clk_pos <= 1'b0;
end
always @(negedge clk or negedge rstn)begin
if(!rstn)
clk_neg <= 0;
else if(cnt==n-1)
clk_neg <= 1'b1;
else
clk_neg <= 1'b0;
end
endmodule
异或逻辑分频
- 用异或逻辑来将两个六分频组合成三分频原理很简单,因为异或是相同为0,不同为1 所以需要将上升沿与下降沿差一半再翻转
- 如果上升沿在cnt=2时翻转,那么下降沿应该在cnt=1翻转
- 这样cnt带来了1T的时序差
- 而上升沿和下降沿自带0.5T的时序差。
下面是理论波形图方便理解。
代码
module div #(parameter n=3)
(
input clk,
input rstn,
output clk_div
);
reg [15:0] cnt;
reg clk_pos,clk_neg;
assign clk_div = clk_pos ^ clk_neg;
always @(posedge clk or negedge rstn)begin
if(!rstn)
cnt <= 0;
else if(cnt==n-1)
cnt <= 0;
else
cnt <= cnt + 1;
end
always @(posedge clk or negedge rstn)begin
if(!rstn)
clk_pos <= 0;
else if(cnt==n-1)
clk_pos <= ~clk_pos;
end
always @(negedge clk or negedge rstn)begin
if(!rstn)
clk_neg <= 0;
else if(cnt==(n>>1))
clk_neg <= ~clk_neg;
end
endmodule
Verilog的学习还是要多以练习为主,想要练习Verilog的同学,推荐可以去nowcoder看看,他们现在的题库内容很丰富,属于国内做的很好的了,而且是课程+刷题+面经+求职+讨论区分享,一站式求职学习网站,最最最重要的里面的资源全部免费