一个简单的PWM发生和捕获Verilog IP设计
这次IP的设计是有一个非常现实的应用需求的,在测试系统中,我们需要对芯片出来的PWM进行捕获或者对芯片出来的频率信号进行计算,另外还需要产生一定的PWM波形激励,用于测试芯片的PWM捕获功能,不过这里只是提供简单的PWM输出,诸如对称PWM,多通道同步等功能,这里暂时没有实现。
首先我们来看看PWM波形捕获的设计,具体的需求是要计算输入信号的频率和占空比信息。简单的想法就是用一个计数器对波形进行计数就可以了。对于频率的计算,一般通过计数也可以实现,不过这种方式只能捕获频率低于我们时钟输入频率的信号(一般只能到四分之一左右)。另外一种方法我称为双时钟计数法,也就是用两个时钟驱动两个计数器,计数到一定时间之后,对比两个计数器的计数结果就可以得到两个频率的关系,这种方式可以用一个比较低的时钟测量一个很高频率的时钟,不过对于FPGA来说,会有多驱动的问题,所以这里就不用这种方式了。
采用计数器对波形进行计数的方式,我们可以很容易的写出下面的Verilog代码:
module pwm_in(
input clk,
input rst_n,
input pwm,
output [31:0]pos_out,
output [31:0]neg_out
);
reg [31:0] pos_out;
reg [31:0] neg_out;
reg [31:0] pos_cnt;
reg [31:0] neg_cnt;
reg pwm_r1, pwm_r2;
wire pwm_rising_edge;
wire pwm_falling_edge;
assign pwm_rising_edge = pwm_r1 & (~pwm_r2);
assign pwm_falling_edge = pwm_r2 & (~pwm_r1);
always@(posedge clk) begin
pwm_r1 <= pwm;
pwm_r2 <= pwm_r1;
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
pos_cnt <= 32'h0;
pos_out <= 32'h0;
neg_cnt <= 32'h0;
neg_out <= 32'h0;
end
else begin
// when reaches rising edge, load counter value to read buffer
neg_out <= pwm_rising_edge ? neg_cnt : neg_out;
pos_out <= pwm_falling_edge ? pos_cnt : pos_out;
// neg_cnt increase when input keeps low
neg_cnt <= pwm_rising_edge ? 32'h0 : (neg_cnt + !pwm);
pos_cnt <= pwm_falling_edge ? 32'h0 : (pos_cnt + pwm);
end
end
endmodule
这里采用了打两拍的方式对波形的边沿进行采集,并将边沿的脉冲信号作为计数器清零和计数结果保存的触发信号。模块功能简单,够用就好,这里针对正负沿都用了一组计数器,这样做的好处是可以采集正负脉冲信号。
对于PWM波形的输出就更为简单了,直接上代码:
module pwm_out(
input clk,
input rst_n,
input [31:0]mod_value,
input [31:0]compare_value,
output pwm_out
);
reg [31:0] counter;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
counter <= 32'h0;
else
counter <= (counter == mod_value) ? 32'h0 : (counter + 1'b1);
end
assign pwm_out = compare_value > counter;
endmodule
直接一个模计数器,计数结果和比较值进行比较就好了,简单粗暴,没有烦恼。并且计数器位宽足够,也就省去了分频的麻烦了。
最后更新于 2020-02-26 13:50:32 并被添加「FPGA Verilog IP」标签,已有 4035 位童鞋阅读过。
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。