【Verilog HDL 训练】第 11 天(分频电路)
【摘要】 设计一个占空比50%的三分频电路。
针对这个分频器,博文的末尾会给出一个反面教材,这是我上次写的一个分频器,看起来很好,其实是不能综合的。针对其中的错误,我令立博文记录之:【 Verilog 】always@()的敏感源中为什么不能双边沿触发?为什么不能双时钟触发?
感谢学习道路上的前辈给予的指导:下面的分频器思路是:
画了个草图:
给出Verilog HD...
设计一个占空比50%的三分频电路。
针对这个分频器,博文的末尾会给出一个反面教材,这是我上次写的一个分频器,看起来很好,其实是不能综合的。针对其中的错误,我令立博文记录之:【 Verilog 】always@()的敏感源中为什么不能双边沿触发?为什么不能双时钟触发?
感谢学习道路上的前辈给予的指导:下面的分频器思路是:
画了个草图:
给出Verilog HDL描述:
-
module Freq_divide(
-
input clk,
-
input rst_n,
-
output clk_divide
-
-
);
-
-
//先写一个占空比为1/3的分频时钟
-
-
reg clk_1_3;
-
reg [2:0] count;
-
-
always@(posedge clk or negedge rst_n) begin
-
if(!rst_n) begin
-
count <= 0;
-
clk_1_3 <= 0;
-
end
-
else if(count == 1) begin
-
clk_1_3 <= ~clk_1_3;
-
count <= count + 1;
-
end
-
else if(count == 2) begin
-
count <= 0;
-
clk_1_3 <= ~clk_1_3;
-
end
-
else begin
-
count <= count + 1;
-
clk_1_3 <= clk_1_3;
-
end
-
-
end
-
-
reg clk_1_3_r;
-
//下降沿采样上述时钟
-
always@(negedge clk or negedge rst_n) begin
-
if(!rst_n) begin
-
clk_1_3_r <= 0;
-
end
-
else begin
-
clk_1_3_r <= clk_1_3;
-
end
-
-
end
-
-
//产生分频时钟
-
assign clk_divide = clk_1_3 | clk_1_3_r;
-
-
-
-
-
-
endmodule
再给出testbench文件以及行为仿真时序图:
-
`timescale 1ns / 1ps
-
-
module clk_divide_tb(
-
-
);
-
reg clk;
-
reg rst_n;
-
wire clk_divide;
-
-
-
initial begin
-
clk = 0;
-
forever
-
#2 clk = ~clk;
-
end
-
-
initial begin
-
-
rst_n = 0;
-
-
#10
-
rst_n = 1;
-
-
-
-
end
-
-
Freq_divide u0(
-
.clk(clk),
-
.rst_n(rst_n),
-
.clk_divide(clk_divide)
-
);
-
-
-
endmodule
可见,功能完好;
再给出RTL电路图:
3分频占空比为50的分频器到底为止,下面是一个反面教材:
记住,这种写法万万不可!
对于奇分频电路,我的思路是:
以3分频为例,那么周期为原来的3倍,那么对原时钟clk,经历1.5个时钟上升沿,分频时钟翻转一次即可。
可是这里有一个问题就是如何实现1.5时钟上升沿呢?(上升沿和下降沿都算?)
我们先对原时钟取反,即相位相差180°,得到时钟clk_reverse;之后对时钟clk和clk_reverse的上升沿计数,计数到2,分频时钟翻转一次即可。
Verilog描述为:
-
module Freq_divide(
-
input clk,
-
input rst_n,
-
output reg clk_divide
-
-
);
-
-
wire clk_reverse;
-
assign clk_reverse = ~clk;
-
-
reg [3:0] count;
-
always @ (posedge clk or posedge clk_reverse or negedge rst_n) begin
-
if(!rst_n) begin
-
count <= 0;
-
end
-
else if(count < 2) begin
-
count <= count + 1;
-
end
-
else begin
-
count <= 0;
-
end
-
end
-
-
always @ (posedge clk or posedge clk_reverse or negedge rst_n) begin
-
if(!rst_n) begin
-
clk_divide <= 0;
-
end
-
else if(count == 2) begin
-
clk_divide <= ~clk_divide;
-
end
-
else begin
-
clk_divide <= clk_divide;
-
end
-
-
end
-
-
-
-
endmodule
仿真文件:
-
`timescale 1ns / 1ps
-
-
module clk_divide_tb(
-
-
);
-
reg clk;
-
reg rst_n;
-
wire clk_divide;
-
-
-
initial begin
-
clk = 0;
-
forever
-
#2 clk = ~clk;
-
end
-
-
initial begin
-
-
rst_n = 0;
-
-
#10
-
rst_n = 1;
-
-
-
-
end
-
-
Freq_divide u0(
-
.clk(clk),
-
.rst_n(rst_n),
-
.clk_divide(clk_divide)
-
);
-
-
-
endmodule
行为仿真时序图:
可见,分频时钟clk_divide周期为原时钟clk的3倍,即完成了3分频的工作。
文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。
原文链接:reborn.blog.csdn.net/article/details/90215383
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)