测量占空比
最近嘗試了很多方法測量占空比,雖然說原理簡單,但是測量的時候誤差還是挺大的,凡是沒呢么容易,
最后終于實現了1HZ-5M 占空比的測量,精度小于%0.1
另外發現了一個問題,fpga一條語句如果很復雜的話,可能會出現問題。
例如 assign ?duty_altera = pinlv << 1 + pinlv;也就是pinlv_altera 是頻率的三倍,在sigtab仿真時出錯了,如果把這兩條語句分開寫就沒毛病了。
這說明在200M高速頻率下,這樣寫法不太好,跑不了高速。
程序思路:
設定一個1S鐘的閘門,在閘門有效期間測量高電平持續時間和低電平持續時間,需要注意的是:
在測量時間時需要以邊沿做為開始計數的標志,否則程序容易崩潰。然而實際測量出來,還是有誤差的,經過測量多組數據發現:高電平測量的時間所記錄的個數比實際上少記錄了2*pinlv個,而低電平恰恰相反。經過補償,滿足題目的要求。
module duty(//system interfaceinput clk,input rst_n,//sig interfaceinput sig_in,//pinlv interfaceinput [31:0] pinlv,//user interfaceoutput reg [15:0] duty,output reg [31:0] cnt_high,output reg [31:0] cnt_low,output high_pulse,output low_pulse,output [31:0] duty_alter );//buffer reg sig_in_buffer; reg sig_in_buffer1; always @(posedge clk or negedge rst_n) beginif(!rst_n)beginsig_in_buffer <= 0;sig_in_buffer1 <= 0;endelsebeginsig_in_buffer <= sig_in;sig_in_buffer1 <= sig_in_buffer;end end assign high_pulse = (sig_in_buffer == 1 && sig_in_buffer1 == 0) ? 1 : 0; assign low_pulse = (sig_in_buffer == 0 && sig_in_buffer1 == 1) ? 1 : 0; //parameter CNT_1S = 32'd199_9; parameter CNT_1S = 32'd199_999_999; reg [31:0] cnt_1s; reg fgate;always @(posedge clk or negedge rst_n) beginif(!rst_n)cnt_1s <= 0;else if(cnt_1s >= CNT_1S)cnt_1s <= 0;else cnt_1s <= cnt_1s + 1; endalways @(posedge clk or negedge rst_n) beginif(!rst_n)fgate <= 0;else if(cnt_1s == CNT_1S)fgate <= ~fgate;elsefgate <= fgate; endreg fstart; always @(posedge sig_in_buffer1 or negedge rst_n) beginif(!rst_n)fstart <= 0;else if(fgate)fstart <= 1;elsefstart <= 0; end reg [2:0] state_high; reg [2:0] state_low; //cnt reg [31:0] cnt_high_temp; reg [31:0] cnt_low_temp;always @(posedge clk or negedge rst_n) beginif(!rst_n)state_high <= 0;elsecase(state_high)2'd0 :beginif(high_pulse)state_high <= 2'd1;elsestate_high <= 2'd0;end2'd1 :beginif(low_pulse)state_high <= 2'd0;elsestate_high <= 2'd1;enddefault : ;endcase endalways @(posedge clk or negedge rst_n) beginif(!rst_n)state_low <= 0;elsecase(state_low)2'd0 :beginif(low_pulse)state_low <= 2'd1;elsestate_low <= 2'd0;end2'd1 :beginif(high_pulse)state_low <= 2'd0;elsestate_low <= 2'd1;enddefault : ;endcase end always @(posedge clk or negedge rst_n) beginif(!rst_n)cnt_high_temp <= 0;else if(fstart)beginif(state_high == 1)cnt_high_temp <= cnt_high_temp + 1;elsecnt_high_temp <= cnt_high_temp;endelsecnt_high_temp <= 0; endalways @(posedge clk or negedge rst_n) beginif(!rst_n)cnt_low_temp <= 0;else if(fstart)beginif(state_low == 1)cnt_low_temp <= cnt_low_temp + 1;elsecnt_low_temp <= cnt_low_temp;endelsecnt_low_temp <= 0; end wire [31:0] pinlv1; assign pinlv1 = pinlv << 1; assign duty_alter = pinlv << 1;always @(negedge fstart or negedge rst_n) beginif(!rst_n)begincnt_high <= 0;cnt_low <= 0;endelsebegincnt_high <= cnt_high_temp + duty_alter ;cnt_low <= cnt_low_temp - duty_alter ; end endendmodule?
轉載于:https://www.cnblogs.com/bixiaopengblog/p/6915653.html
總結
- 上一篇: 如何开启APP2SD功能
- 下一篇: 【路径规划】基于matlab蚁群算法栅格