之二:PWM小模块设计
时间:10-02
整理:3721RD
点击:
唉,真正上手烧FPGA才发现代码的各种问题。接下来的代码可能会有点乱,但是差的风格不影响它的功能。
PWM是主流MCU必备的功能。一般带有频率调节和占空比调节。我所写的这个小模块只有频率调节功能,占空比固定为50%。
//此版仅做1:1占空比的频率调整。
//21位数字码来计数,反转一次需要2M个周期,则一个出口时钟周期需要4M个周期,也就是分频结果是12Hz。
module lab2(//Controled_divider
input clk0,
input en,
input [3:0]num,
output div);
reg [4:0]cou3;//用来将div1h和div2拉回0的计数器
reg [3:0]cou2;//用来通知neg ck将div1拉高的计数器
reg [3:0]cou1;//用作偶数分频的计数器
reg [3:0]cou;//分频值的缓存;
wire div0;
reg en0;
reg div1;//奇数分频
reg div2;//偶数分频
reg div2_0;
reg div2_1;
wire tag_half;//如果奇数分频,例如7分频,先等待3个周期之后,把该位置1,下一个下降沿时检测到这个tag为1,将tag换为0;7个周期之后ck上升沿将div1拉低。
reg tag_half0;
reg tag_half1;
wire tag;//tag用来标注是奇数分频还是偶数分频
reg [20:0]counter;
reg ck;//内部使用的12Hz时钟
always@(posedge clk0)begin
counter >1)-1))div2_0 >1)-1))tag_half0<=0;
else begin
tag_half0<=1;
end
end
always@(negedge ck)begin
if(tag_half)div1<=1;
else div1<=0;
end
endmodule
//总结:千万不要做在两个always块中操作同一个寄存器的事情。
//此处的解决方法是原本一个变量分出三个,两个always各操作一个,
//第三个变量为前两个变量的与。偶数分频中,
//二分之一计数器控制上升沿,总计数器控制下降沿。
程序主体分为两块,一个是50MHz的分频,为了便于LED来观测其频率变化,分出的频率约为12Hz。
另一个是分频模块,利用复位按键的上升沿将四个按键所设置的分频比打入寄存器。分频电路主要分为三部分。一是计数器积满到设定值,将输出拉回低电平。二是如果是偶数分频,在计数值的一半时,将输出拉高;三是如果是奇数分频,例如7分频,则在第三个周期的下降沿将输出拉高,保证50%的占空比。
下载到FPGA后,按下KEY5-KEY8的某几个键并保持,再按一下复位键,则复位键上升时将分频比保存了下来。分频输出开始。
总结:这段代码风格极差,所幸效果还不错,上照片的话也不过是一个亮着的LED,所以不上图了。风格差的一个主要原因是:要同时处理时钟的上升沿和下降沿。下次应该把这个模块和时钟分频分别直接调用。下一波搞搞接口电路、遥控器和signaltap。
PWM是主流MCU必备的功能。一般带有频率调节和占空比调节。我所写的这个小模块只有频率调节功能,占空比固定为50%。
//此版仅做1:1占空比的频率调整。
//21位数字码来计数,反转一次需要2M个周期,则一个出口时钟周期需要4M个周期,也就是分频结果是12Hz。
module lab2(//Controled_divider
input clk0,
input en,
input [3:0]num,
output div);
reg [4:0]cou3;//用来将div1h和div2拉回0的计数器
reg [3:0]cou2;//用来通知neg ck将div1拉高的计数器
reg [3:0]cou1;//用作偶数分频的计数器
reg [3:0]cou;//分频值的缓存;
wire div0;
reg en0;
reg div1;//奇数分频
reg div2;//偶数分频
reg div2_0;
reg div2_1;
wire tag_half;//如果奇数分频,例如7分频,先等待3个周期之后,把该位置1,下一个下降沿时检测到这个tag为1,将tag换为0;7个周期之后ck上升沿将div1拉低。
reg tag_half0;
reg tag_half1;
wire tag;//tag用来标注是奇数分频还是偶数分频
reg [20:0]counter;
reg ck;//内部使用的12Hz时钟
always@(posedge clk0)begin
counter >1)-1))div2_0 >1)-1))tag_half0<=0;
else begin
tag_half0<=1;
end
end
always@(negedge ck)begin
if(tag_half)div1<=1;
else div1<=0;
end
endmodule
//总结:千万不要做在两个always块中操作同一个寄存器的事情。
//此处的解决方法是原本一个变量分出三个,两个always各操作一个,
//第三个变量为前两个变量的与。偶数分频中,
//二分之一计数器控制上升沿,总计数器控制下降沿。
程序主体分为两块,一个是50MHz的分频,为了便于LED来观测其频率变化,分出的频率约为12Hz。
另一个是分频模块,利用复位按键的上升沿将四个按键所设置的分频比打入寄存器。分频电路主要分为三部分。一是计数器积满到设定值,将输出拉回低电平。二是如果是偶数分频,在计数值的一半时,将输出拉高;三是如果是奇数分频,例如7分频,则在第三个周期的下降沿将输出拉高,保证50%的占空比。
下载到FPGA后,按下KEY5-KEY8的某几个键并保持,再按一下复位键,则复位键上升时将分频比保存了下来。分频输出开始。
总结:这段代码风格极差,所幸效果还不错,上照片的话也不过是一个亮着的LED,所以不上图了。风格差的一个主要原因是:要同时处理时钟的上升沿和下降沿。下次应该把这个模块和时钟分频分别直接调用。下一波搞搞接口电路、遥控器和signaltap。
可以配上仿真或者调试的结果图
谢谢小编分享,辛苦了。