最近我在学习FPGA时,写了一个时钟分频程序,想用来产生3种不同频率的时钟,因为我都是写的单片机程序,所以就想着用函数传递形参的方式,从而用模块例化产生不同频率的时钟,但是例化时要求传入常量,所以只能重复例化3次,用rst_n的决定哪个时钟输出。
一开始我的想法如下:
wire CS8416_OMCK;
reg [3:0] div = 4;
reg [2:0] cs8416_clk_rst_r = 3'b010; //对应选择哪个频率作为输出先说明,这里是错误的,
//本来想通过一个变量传递给.DIV,就不用重复写几遍,
Clk_Div #(
.WIDTH (3), //分频系数的宽度,最大分频值为2^3-1
.DIV (div)) //分频系数,div分频 这里是错误的,不能传递形参
u_clk_1ms(
.clkin (EXTERNAL_CLK),
.clkout (CS8416_OMCK),
.rst_n (cs8416_clk_rst_r>>1) //低电平不输出时钟
);
编译器报错后,我改成了以下程序:
wire CS8416_OMCK;
reg [3:0] div = 4;
reg [2:0] cs8416_clk_rst_r = 3'b010; //对应选择哪个频率作为输出先说明,这里是错误的,
//不分频
Clk_Div #(
.WIDTH (3), //分频系数的宽度,最大分频值为2^3-1
.DIV (1)) //分频系数,1分频
u_clk_1ms(
.clkin (EXTERNAL_CLK),
.clkout (CS8416_OMCK),
.rst_n (cs8416_clk_rst_r>>0) //低电平不输出时钟
);
//2分频
Clk_Div #(
.WIDTH (3), //分频系数的宽度,最大分频值为2^3-1
.DIV (2)) //分频系数,2分频
u_clk_1ms(
.clkin (EXTERNAL_CLK),
.clkout (CS8416_OMCK),
.rst_n (cs8416_clk_rst_r>>1) //低电平不输出时钟
);
//4分频
Clk_Div #(
.WIDTH (3), //分频系数的宽度,最大分频值为2^3-1
.DIV (4)) //分频系数,4分频
u_clk_1ms(
.clkin (EXTERNAL_CLK),
.clkout (CS8416_OMCK),
.rst_n (cs8416_clk_rst_r>>2) //低电平不输出时钟
);
然后编译下载完后,无论我怎么设置cs8416_clk_rst_r的值,怎么进行移位操作,编译器都直接认为.rst_n()传进去的都是0,映射到.rst(作为输入)的信号不能是reg类型,要改为wire类型,并用assign改变其值,正确方法如下:
wire CS8416_OMCK;
wire [3:0] cs8416_clk_rst_r;
assign cs8416_clk_rst_r = 4'b0010;
分频程序参考FPGA时钟分频的几种方法