2008-04-30
任意分频的 Verilog 实现
0 Comments | 14:00 | Verilog | Edit该模块实现任意整数分频,这样偶分频和奇分频就不用写成两个模块了,呵呵。好不容易设计了这么个玩意,结果使用的CPLD资源太大,在毕业设计中,我还是用的简单的偶分频模块,毕竟实现简单,省资源。自己没使上,放在博客上,让有需要的做个参考吧,呵呵。
实现原理,自己上网找吧,这里就不罗嗦了。
module top
(
input rst,
input clk,
output clk_out
);
reg [3:0] factor_reg;
freq_div #(.FACTOR_LEN(4)) freq_div_inst(rst, clk, clk_out, factor_reg);
always
factor_reg = 4'h5;
endmodule
// 实现任意整数分频
// Author: Mingchang Lian
// Date: 2008-4-30
// Revision: 0.1
// Copyright: GPL
// 不要在声明的时候赋初值,仿真和综合都有可能不会赋值,而用随机值
// 仿真建议显式赋值,reg在always里赋值
// 综合建议加个reset信号,来赋初值
module freq_div
(
input rst, // 低电平有效,复位
input clk, // 输入时钟
output clk_out, // 分频输出
input [(FACTOR_LEN - 1):0] factor // 分频倍数
);
reg clk_pos; // 上升沿分频
reg clk_neg; // 下降沿分频
reg [(FACTOR_LEN - 1):0] i; // 计数器
reg [(FACTOR_LEN - 1):0] j; // 计数器
parameter FACTOR_LEN = 8;
// 偶分频输出 clk_pos
// 奇分频将上升沿和下降沿分配相与后输出
// 奇分频的高电平多于低电平用与运算
// 低电平多于高电平用或运算
assign clk_out = (factor[0]) ? (clk_pos & clk_neg) : clk_pos;
always @ (posedge clk)
begin
if (!rst) // 复位
begin
clk_pos <= 1'b0;
i <= {FACTOR_LEN{1'b0}};
end
else
begin
i = i + 1'b1;
if (i == (factor >> 1))
clk_pos <= ~clk_pos; // 翻转
else if (i == factor)
begin
clk_pos <= ~clk_pos;
i <= {FACTOR_LEN{1'b0}};
end
else
/* NOP */;
end
end
always @ (negedge clk)
begin
if (!rst) // 复位
begin
clk_neg <= 1'b0;
j <= {FACTOR_LEN{1'b0}};
end
else
begin
j = j + 1'b1;
if (j == (factor >> 1))
clk_neg <= ~clk_neg;
else if (j == factor)
begin
clk_neg <= ~clk_neg;
j <= {FACTOR_LEN{1'b0}};
end
else
/* NOP */;
end
end
endmodule




