頻率計設計

此頻率計是用 50MHz 作採樣,所以解析度以 20us 為一個單位,其構思為抓取量測訊號的正緣,直到下一個正緣來臨前使用計數器計數,下一個正緣到達時則清空計數器且重新計算,而計數器的長度決定可以抓取多慢的週期。

實作方法如下圖,PL 負責抓取資料透過 AXI-Lite 傳送資料至 PS,PS 負責把 raw data 轉為頻率或週期。

測試架構(黃框處)

PL 的 RTL 如下 :

module freq_cnt (
    input clk,
    input rstN,

    input iClkDet,
    output [23:0] ovClkCnt
);

reg [1:0] rvEdge_d, rvEdge_q;
wire wRising;
reg [23:0] rvCnt_d, rvCnt_q;
wire AddCnt, KeepCnt, ClrCnt;
reg [23:0] rvLatchCnt_d, rvLatchCnt_q;

//edge detection
always @(posedge clk or negedge rstN) begin
    if(!rstN)
        rvEdge_q <= 2'h0;
    else
        rvEdge_q <= rvEdge_d;
end

always @(*) begin
    rvEdge_d = {rvEdge_q[0], iClkDet};
end
assign wRising = (rvEdge_q == 2'b01) ? 1'b1 : 1'b0;

//period counter
assign AddCnt  = 1'b1;
assign KeepCnt = rvCnt_q == (24'hFFFFFF - 1'h1);
assign ClrCnt  = wRising;
always @(posedge clk or negedge rstN) begin
    if(!rstN)
        rvCnt_q <= 24'h0;
    else
        rvCnt_q <= rvCnt_d;
end

always @(*) begin
    if(ClrCnt)
        rvCnt_d = 24'h0;
    else if(KeepCnt)
        rvCnt_d = rvCnt_q;
    else if(AddCnt)
        rvCnt_d = rvCnt_q + 1'b1;
    else
        rvCnt_d = rvCnt_q;
end

//latch data
always @(posedge clk or negedge rstN) begin
    if(!rstN)
        rvLatchCnt_q <= 24'h0;
    else
        rvLatchCnt_q <= rvLatchCnt_d;
end

always @(*) begin
    if(KeepCnt)
        rvLatchCnt_d = 24'h0;
    else if(wRising)
        rvLatchCnt_d = rvCnt_q;
    else
        rvLatchCnt_d = rvLatchCnt_q;
end
assign ovClkCnt = rvLatchCnt_q;

endmodule

有了PS的加持讓我可以容易處理週期及頻率的轉換,測試效果看起來還可以,測試如下:

(1) 測試1

PS 計算週期約 48.62 ms
示波器量測週期約 48.3 ms

(2) 測試2

PS 計算週期約 10.11 ms
示波器量測週期約 10.04 ms

(3) 測試3

PS 計算週期約 4.9 ms

示波器量測週期約 4.92 ms

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *