描述
设计一个同时输出7分频的时钟分频器,占空比要求为50%
注意rst为低电平复位
信号示意图:
波形示意图:
输入描述:
输入信号 clk_in rst
类型 wire
输出描述:
输出信号 clk_out7
类型 wire
题意整理
对于奇数分频电路,主要难点在于50%占空比的实现。单触发沿在奇数分频中是没有办法实现50%占空比的,因此需要考虑使用双边沿加组合逻辑实现50%占空比
题解主体
通过简单的状态转移表就能够得出,clkout7的翻转第一次是在上升沿,第二次是在下降沿。
clkin | clkout7 | cnt |
0 | 0 | 0 |
1 | 1 | 1 |
0 | 1 | 1 |
1 | 1 | 2 |
0 | 1 | 2 |
1 | 1 | 3 |
0 | 1 | 3 |
1 | 1 | 4 |
0 | 0 | 4 |
1 | 0 | 5 |
0 | 0 | 5 |
1 | 0 | 6 |
0 | 0 | 6 |
1 | 0 | 7 |
0 | 0 | 7 |
1 | 1 | 8 |
要让两个不同的时钟边沿触发的分频信号进行组合逻辑,分析应该有下面的时许构成:
很容易看出,做法应该是将两个信号进行或操作
将逻辑转换成Verilog代码描述如下
reg [3:0] cnt ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
cnt <= 'b0 ;
end
else if (cnt == N-1) begin
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
reg clkp ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
clkp <= 1'b0 ;
end
else if (cnt == (N>>1)) begin
clkp <= 1 ;
end
else if (cnt == N-1) begin
clkp <= 0 ;
end
end
reg clkn ;
always @(negedge clk_in or negedge rst) begin
if (!rst) begin
clkn <= 1'b0 ;
end
else if (cnt == (N>>1) ) begin
clkn <= 1 ;
end
else if (cnt == N-1) begin
clkn <= 0 ;
end
end
assign clk_out7 = clkp | clkn ;
因此实现方式为如下的电路,综合得到:
`timescale 1ns/1ns
module odo_div_or
#(parameter N = 7)
(
input wire rst ,
input wire clk_in,
output wire clk_out7
);
reg [3:0] cnt ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
cnt <= 'b0 ;
end
else if (cnt == N-1) begin
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
reg clkp ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
clkp <= 1'b0 ;
end
else if (cnt == (N>>1)) begin
clkp <= 1 ;
end
else if (cnt == N-1) begin
clkp <= 0 ;
end
end
reg clkn ;
always @(negedge clk_in or negedge rst) begin
if (!rst) begin
clkn <= 1'b0 ;
end
else if (cnt == (N>>1) ) begin
clkn <= 1 ;
end
else if (cnt == N-1) begin
clkn <= 0 ;
end
end
assign clk_out7 = clkp | clkn ;
endmodule
方法二
四个下降沿高电平 四个上升沿低电平 一个计数器记录电平变换,并控制计数器工作
reg [2:0] count1 = 0;
reg [2:0] count2 = 0;
reg flag = 0;
reg waveout = 0;
assign clk_out7 = flag;
always@(posedge clk_in or negedge rst)begin // low
if(rst == 1'b0)begin
count1 <= 3'd0;
end
else begin
if(count1 >= 3'd3)begin
count1 <= 3'd0;
flag <= 1'b0;
end
else begin
if(flag == 1'b1)
count1 <= count1 + 1;
end
end
end
always@(negedge clk_in or negedge rst)begin // high
if(rst == 1'b0)begin
count2 <= 3'd0;
flag <= 1'b0;
end
else begin
if(count2 >= 3'd3)begin
count2 <= 3'd0;
flag <= 1'b1;
end
else begin
if(flag == 1'b0)
count2 <= count2 + 1;
end
end
end