预分频之三
半分频(N+0.5)
波形分析(4.5分频)
分析可知,9 = 4.5 + 4.5 = 4 + 5 = 5 + 4 = (1.5 + 3) * 2。
先使用两个信号pre9与pre9_inv将9划分为两种实现方式,然后再通过错位的波形运算得到4.5分频。
参考代码
verilog code
module decimalprescaler(
output prescaler,
input clk,
input rstn
);
parameter N = 9; //4.5分频
reg [7:0] cnt;
reg [7:0] cnt_next;
reg pre9;
reg pre9_inv;
reg pre9_inv_reg;
//计数器
always@(posedge clk,negedge rstn)
begin
if(!rstn)
cnt <= 7'b0;
else
cnt <= cnt_next;
end
always@(*)
begin
if(cnt == (N - 1'b1)) //周期设定( 0 - N-1 ) N分频
cnt_next = 0;
else
cnt_next = cnt + 1'b1;
end
//产生pre9
always@(posedge clk,negedge rstn)
if(!rstn)
begin
pre9 <= 1'b0;
end
else
begin if(cnt == 7'b1000 || cnt == 7'b0100) //注意计数到(N - 1)
pre9 <= 1'b1;
else if(cnt == 7'b0000 || cnt == 7'b0101)
pre9 <= 1'b0;
end
//产生pre9_inv
always@(posedge clk,negedge rstn)
if(!rstn)
begin
pre9_inv <= 1'b0;
end
else
begin if(cnt == 7'b1000 || cnt == 7'b0011)
pre9_inv <= 1'b1;
else if(cnt == 7'b0000 || cnt == 7'b0100)
pre9_inv <= 1'b0;
end
//使用下降沿处理得到0.5拍
always @ (negedge clk,negedge rstn) //注意使用下降沿
begin
if(!rstn)
pre9_inv_reg <= 1'b0;
else
pre9_inv_reg <= pre9_inv;
end
assign prescaler = pre9 | pre9_inv_reg;
endmodule
testbench
module decimalprescaler_tb;
reg clk;
reg rstn;
wire prescaler;
initial
begin
clk = 0;
rstn = 0;
@(posedge clk) rstn = 1;
repeat(100) @(posedge clk);
@(posedge clk) $finish;
end
always #5 clk = ~clk;
initial begin
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars();
end
decimalprescaler u_decimalprescaler(
.prescaler(prescaler),
.clk(clk),
.rstn(rstn)
);
endmodule
仿真结果
学习更多
4.5分频的另一种方法(更接近50%占空比)
波形分析
分析可知,4.5 = 2 + 2.5,我们可以得到上文中更宽的有效边沿,以接近50%占空比。
部分参考代码
verilog code
//产生pre9
always@(posedge clk,negedge rstn)
if(!rstn)
begin
pre9 <= 1'b0;
end
else
begin if(cnt == 7'b0001 || cnt == 7'b0110)
pre9 <= 1'b1;
else if(cnt == 7'b0011 || cnt == 7'b1000)
pre9 <= 1'b0;
end
//产生pre9_inv
always@(posedge clk,negedge rstn)
if(!rstn)
begin
pre9_inv <= 1'b0;
end
else
begin if(cnt == 7'b0001 || cnt == 7'b0101)
pre9_inv <= 1'b1;
else if(cnt == 7'b0011 || cnt == 7'b0111)
pre9_inv <= 1'b0;
end
testbench 与上文同一个testbench
仿真结果
5.5分频
波形分析
分析思路,11 = 5.5 + 5.5 = 5 + 6 = 6 + 5 = (1.5 + 4) + (1.5 + 4)
参考代码
verilog code
module decimalprescaler(
output prescaler,
input clk,
input rstn
);
parameter N = 11; //5.5分频
reg [7:0] cnt;
reg [7:0] cnt_next;
reg pre11;
reg pre11_inv;
reg pre11_inv_reg;
//计数器
always@(posedge clk,negedge rstn)
begin
if(!rstn)
cnt <= 7'b0;
else
cnt <= cnt_next;
end
always@(*)
begin
if(cnt == (N - 1'b1)) //周期设定( 0 - N-1 ) N分频
cnt_next = 0;
else
cnt_next = cnt + 1'b1;
end
//产生pre11
always@(posedge clk,negedge rstn)
if(!rstn)
begin
pre11 <= 1'b0;
end
else
begin if(cnt == 7'b1010 || cnt == 7'b0101) //注意计数到(N-1)
pre11 <= 1'b1;
else if(cnt == 7'b0000 || cnt == 7'b0110)
pre11 <= 1'b0;
end
//产生pre11_inv
always@(posedge clk,negedge rstn)
if(!rstn)
begin
pre11_inv <= 1'b0;
end
else
begin if(cnt == 7'b1010 || cnt == 7'b0100)
pre11_inv <= 1'b1;
else if(cnt == 7'b0000 || cnt == 7'b0101)
pre11_inv <= 1'b0;
end
//使用下降沿处理得到0.5拍
always @ (negedge clk,negedge rstn) //注意使用下降沿
begin
if(!rstn)
pre11_inv_reg <= 1'b0;
else
pre11_inv_reg <= pre11_inv;
end
assign prescaler = pre11 | pre11_inv_reg;
endmodule
testbech 同上文
仿真结果
问题思考:可以像4.5分频使用两种方法吗?
参考资料
[1]. 用Verilog语言实现奇数倍分频电路3分频、5分频、7分频
[2]. 基于Verilog的奇数偶数小数分频器设计
形而上者谓之道 形而下者谓之器。