該項目介紹了如何使用 Verilog 實現(xiàn)具有預生成系數(shù)的簡單 FIR 濾波器。

緒論
不起眼的 FIR 濾波器是 FPGA 數(shù)字信號處理中最基本的模塊之一,因此了解如何將具有給定抽頭數(shù)及其相應系數(shù)值的基本模塊組合在一起非常重要。因此,在這個關于 FPGA 上 DSP 基礎實用入門的教程中,將從一個簡單的 15 抽頭低通濾波器 FIR 開始,在 Matlab 中為其生成初始系數(shù)值,然后轉換這些值用于編寫 Verilog 模塊。
有限脈沖響應或 FIR 濾波器定義為脈沖響應在特定時間段內(nèi)穩(wěn)定為零值的濾波器。脈沖響應穩(wěn)定到零所花費的時間與濾波器階數(shù)(抽頭數(shù))直接相關,濾波器階數(shù)是 FIR 的基礎傳遞函數(shù)多項式的階數(shù)。FIR 的傳遞函數(shù)不包含反饋,因此如果輸入一個值為 1 的脈沖,然后輸入一串零值,輸出將只是濾波器的系數(shù)值。
濾波器的作用基本都是用于信號調(diào)節(jié),主要集中在選擇濾除或允許通過哪些頻率。最簡單的例子之一是低通濾波器,它允許低于某個閾值(截止頻率)的頻率通過,同時大大衰減高于該閾值的頻率,如下圖所示。

該項目的主要重點是在 HDL(具體為 Verilog)中實現(xiàn) FIR,它可以分解為三個主要邏輯組件:一個循環(huán)緩沖器,用于將每個樣本計時到適當?shù)乜紤]了串行輸入的延遲、每個抽頭系數(shù)值的乘法器以及每個抽頭輸出的求和結果的累加器。

由于本項目專注于 FPGA 邏輯中 FIR 的設計機制,所以只是使用 Simulink 中的 FDA 工具和 Matlab 為低通濾波器插入一些簡單參數(shù),然后使用生成的系數(shù)值放到 Verilog 模塊中完成濾波器的設計(在后面的步驟中完成)。

選擇實現(xiàn)一個簡單的 15 抽頭低通濾波器 FIR,采樣率為 1Ms/s,通帶頻率為 200kHz,阻帶頻率為 355kHz,得到以下系數(shù):
-0.0265?
0?
0.0441?
0?
-0.0934?
0?
0.3139?
0.5000?
0.3139?
0?
-0.0934?
0?
0.0441?
0?
-0.0265
為 FIR 模塊創(chuàng)建設計文件
在 Vivado 項目中添加源文件。

在確定 FIR 的順序(抽頭數(shù))并獲得系數(shù)值后,接下來需要定義的下一組參數(shù)就是輸入樣本、輸出樣本和系數(shù)本身的位寬。
對于這個 FIR,選擇將輸入樣本和系數(shù)寄存器設置為 16 位寬,并將輸出樣本寄存器設置為 32 位,因為兩個 16 位值的乘積是一個 32 位值(兩個值的寬度相乘得到乘積的寬度,所以如果選擇了 8 位抽頭的 16 位輸入樣本,那么輸出樣本將為 24 位寬)。
這些值也都是帶符號的,因此 MSB 用作符號位,在選擇輸入樣本寄存器的初始寬度時一定要記住這一點。要在 Verilog 中將這些值設置為有符號數(shù)據(jù)類型,使用關鍵字signed :
reg?signed?[15:0]?register_name;
接下來要解決的是如何在 Verilog 中處理系數(shù)值,小數(shù)點值需要轉換為定點值。由于所有系數(shù)值都小于 1,因此寄存器的所有 15 位(總共 16 位,MSB 是有符號位)都可以用于小數(shù)位。通常,必須決定要將寄存器中的多少位用于數(shù)字的整數(shù)部分與數(shù)字的小數(shù)部分。因此,轉換分數(shù)值抽頭的數(shù)學是:(fractional coefficient value)*(2^(15))該乘積的小數(shù)值被四舍五入,并且如果系數(shù)為負,則計算該值的二進制補碼:
tap0?=?twos(-0.0265?*?32768)?=?0xFC9C
tap1?=?0
tap2?=?0.0441?*?32768?=?1445.0688?=?1445?=?0x05A5
tap3?=?0
tap4?=?twos(-0.0934?*?32768)?=?0xF40C
tap5?=?0
tap6?=?0.3139?*?32768?=?10285.8752?=?10285?=?0x282D
tap7?=?0.5000?*?32768?=?16384?=?0x4000
tap8?=?0.3139?*?32768?=?10285.8752?=?10285?=?0x282D
tap9?=??0
tap10?=?twos(-0.0934?*?32768)?=?0xF40C
tap11?=?0
tap12?=?0.0441?*?32768?=?1445.0688?=?1445?=?0x05A5
tap13?=?0
tap14?=?twos(-0.0265?*?32768)?=?0xFC9C
現(xiàn)在我們終于準備好關注 FIR 模塊的邏輯,第一個是循環(huán)緩沖區(qū),它引入串行輸入樣本流并為濾波器的 15 個抽頭創(chuàng)建一個包含 15 個輸入樣本的數(shù)組。
always?@?(posedge?clk)
????????begin
????????????if(enable_buff?==?1'b1)
????????????????begin
????????????????????buff0?<=?in_sample;
????????????????????buff1?<=?buff0;????????
????????????????????buff2?<=?buff1;?????????
????????????????????buff3?<=?buff2;??????
????????????????????buff4?<=?buff3;??????
????????????????????buff5?<=?buff4;???????
????????????????????buff6?<=?buff5;????
????????????????????buff7?<=?buff6;???????
????????????????????buff8?<=?buff7;???????
????????????????????buff9?<=?buff8;???????
????????????????????buff10?<=?buff9;????????
????????????????????buff11?<=?buff10;???????
????????????????????buff12?<=?buff11;???????
????????????????????buff13?<=?buff12;???????
????????????????????buff14?<=?buff13;????
????????????????end
????????end
接下來,乘法階段將每個樣本乘以每個系數(shù)值:
/*?Multiply?stage?of?FIR?*/
????always?@?(posedge?clk)
????????begin
????????????if?(enable_fir?==?1'b1)
????????????????begin
????????????????????acc0?<=?tap0?*?buff0;
????????????????????acc1?<=?tap1?*?buff1;
????????????????????acc2?<=?tap2?*?buff2;
????????????????????acc3?<=?tap3?*?buff3;
????????????????????acc4?<=?tap4?*?buff4;
????????????????????acc5?<=?tap5?*?buff5;
????????????????????acc6?<=?tap6?*?buff6;
????????????????????acc7?<=?tap7?*?buff7;
????????????????????acc8?<=?tap8?*?buff8;
????????????????????acc9?<=?tap9?*?buff9;
????????????????????acc10?<=?tap10?*?buff10;
????????????????????acc11?<=?tap11?*?buff11;
????????????????????acc12?<=?tap12?*?buff12;
????????????????????acc13?<=?tap13?*?buff13;
????????????????????acc14?<=?tap14?*?buff14;
????????????????end
????????end
乘法階段的結果值通過加法累加到寄存器中,最終成為濾波器的輸出數(shù)據(jù)流。
/*?Accumulate?stage?of?FIR?*/???
????always?@?(posedge?clk)?
????????begin
????????????if?(enable_fir?==?1'b1)
????????????????begin
????????????????????m_axis_fir_tdata?<=?acc0?+?acc1?+?acc2?+?acc3?+?acc4?+?acc5?+?acc6?+?acc7?+?acc8?+?acc9?+?acc10?+?acc11?+?acc12?+?acc13?+?acc14;
????????????????end
????????end
最后,邏輯的最后一部分是將數(shù)據(jù)流進和流出 FIR 模塊的接口。AXI Stream 接口是最常見的接口之一。關鍵方面是允許控制上游和下游設備之間的數(shù)據(jù)流的tready和tvalid信號。這意味著 FIR 模塊需要向其下游設備提供tvalid信號以指示其輸出是有效數(shù)據(jù),并且如果下游設備解除其tready信號,則能夠暫停(但仍保留)其輸出。FIR 模塊還必須能夠與其主端接口上的上游設備以同樣的方式運行。

以下是 FIR 模塊的邏輯設計概述:

請注意tready和tvalid信號如何設置輸入循環(huán)緩沖器的使能值和 FIR 的乘法級以及數(shù)據(jù)或系數(shù)通過的每個寄存器都被聲明為有符號的。
FIR模塊Verilog代碼:
`timescale?1ns?/?1ps
module?FIR(
????input?clk,
????input?reset,
????input?signed?[15:0]?s_axis_fir_tdata,?
????input?[3:0]?s_axis_fir_tkeep,
????input?s_axis_fir_tlast,
????input?s_axis_fir_tvalid,
????input?m_axis_fir_tready,
????output?reg?m_axis_fir_tvalid,
????output?reg?s_axis_fir_tready,
????output?reg?m_axis_fir_tlast,
????output?reg?[3:0]?m_axis_fir_tkeep,
????output?reg?signed?[31:0]?m_axis_fir_tdata
????);
????always?@?(posedge?clk)
????????begin
????????????m_axis_fir_tkeep?<=?4'hf;
????????end
????????
????always?@?(posedge?clk)
????????begin
????????????if?(s_axis_fir_tlast?==?1'b1)
????????????????begin
????????????????????m_axis_fir_tlast?<=?1'b1;
????????????????end
????????????else
????????????????begin
????????????????????m_axis_fir_tlast?<=?1'b0;
????????????????end
????????end
????
????//?15-tap?FIR?
????reg?enable_fir,?enable_buff;
????reg?[3:0]?buff_cnt;
????reg?signed?[15:0]?in_sample;?
????reg?signed?[15:0]?buff0,?buff1,?buff2,?buff3,?buff4,?buff5,?buff6,?buff7,?buff8,?buff9,?buff10,?buff11,?buff12,?buff13,?buff14;?
????wire?signed?[15:0]?tap0,?tap1,?tap2,?tap3,?tap4,?tap5,?tap6,?tap7,?tap8,?tap9,?tap10,?tap11,?tap12,?tap13,?tap14;?
????reg?signed?[31:0]?acc0,?acc1,?acc2,?acc3,?acc4,?acc5,?acc6,?acc7,?acc8,?acc9,?acc10,?acc11,?acc12,?acc13,?acc14;?
????
????/*?Taps?for?LPF?running?@?1MSps?with?a?cutoff?freq?of?400kHz*/
????assign?tap0?=?16'hFC9C;??//?twos(-0.0265?*?32768)?=?0xFC9C
????assign?tap1?=?16'h0000;??//?0
????assign?tap2?=?16'h05A5;??//?0.0441?*?32768?=?1445.0688?=?1445?=?0x05A5
????assign?tap3?=?16'h0000;??//?0
????assign?tap4?=?16'hF40C;??//?twos(-0.0934?*?32768)?=?0xF40C
????assign?tap5?=?16'h0000;??//?0
????assign?tap6?=?16'h282D;??//?0.3139?*?32768?=?10285.8752?=?10285?=?0x282D
????assign?tap7?=?16'h4000;??//?0.5000?*?32768?=?16384?=?0x4000
????assign?tap8?=?16'h282D;??//?0.3139?*?32768?=?10285.8752?=?10285?=?0x282D
????assign?tap9?=?16'h0000;??//?0
????assign?tap10?=?16'hF40C;?//?twos(-0.0934?*?32768)?=?0xF40C
????assign?tap11?=?16'h0000;?//?0
????assign?tap12?=?16'h05A5;?//?0.0441?*?32768?=?1445.0688?=?1445?=?0x05A5
????assign?tap13?=?16'h0000;?//?0
????assign?tap14?=?16'hFC9C;?//?twos(-0.0265?*?32768)?=?0xFC9C
????
????/*?This?loop?sets?the?tvalid?flag?on?the?output?of?the?FIR?high?once?
?????*?the?circular?buffer?has?been?filled?with?input?samples?for?the?
?????*?first?time?after?a?reset?condition.?*/
????always?@?(posedge?clk?or?negedge?reset)
????????begin
????????????if?(reset?==?1'b0)?//if?(reset?==?1'b0?||?tvalid_in?==?1'b0)
????????????????begin
????????????????????buff_cnt?<=?4'd0;
????????????????????enable_fir?<=?1'b0;
????????????????????in_sample?<=?8'd0;
????????????????end
????????????else?if?(m_axis_fir_tready?==?1'b0?||?s_axis_fir_tvalid?==?1'b0)
????????????????begin
????????????????????enable_fir?<=?1'b0;
????????????????????buff_cnt?<=?4'd15;
????????????????????in_sample?<=?in_sample;
????????????????end
????????????else?if?(buff_cnt?==?4'd15)
????????????????begin
????????????????????buff_cnt?<=?4'd0;
????????????????????enable_fir?<=?1'b1;
????????????????????in_sample?<=?s_axis_fir_tdata;
????????????????end
????????????else
????????????????begin
????????????????????buff_cnt?<=?buff_cnt?+?1;
????????????????????in_sample?<=?s_axis_fir_tdata;
????????????????end
????????end???
????always?@?(posedge?clk)
????????begin
????????????if(reset?==?1'b0?||?m_axis_fir_tready?==?1'b0?||?s_axis_fir_tvalid?==?1'b0)
????????????????begin
????????????????????s_axis_fir_tready?<=?1'b0;
????????????????????m_axis_fir_tvalid?<=?1'b0;
????????????????????enable_buff?<=?1'b0;
????????????????end
????????????else
????????????????begin
????????????????????s_axis_fir_tready?<=?1'b1;
????????????????????m_axis_fir_tvalid?<=?1'b1;
????????????????????enable_buff?<=?1'b1;
????????????????end
????????end
????
????/*?Circular?buffer?bring?in?a?serial?input?sample?stream?that?
?????*?creates?an?array?of?15?input?samples?for?the?15?taps?of?the?filter.?*/
????always?@?(posedge?clk)
????????begin
????????????if(enable_buff?==?1'b1)
????????????????begin
????????????????????buff0?<=?in_sample;
????????????????????buff1?<=?buff0;????????
????????????????????buff2?<=?buff1;?????????
????????????????????buff3?<=?buff2;??????
????????????????????buff4?<=?buff3;??????
????????????????????buff5?<=?buff4;???????
????????????????????buff6?<=?buff5;????
????????????????????buff7?<=?buff6;???????
????????????????????buff8?<=?buff7;???????
????????????????????buff9?<=?buff8;???????
????????????????????buff10?<=?buff9;????????
????????????????????buff11?<=?buff10;???????
????????????????????buff12?<=?buff11;???????
????????????????????buff13?<=?buff12;???????
????????????????????buff14?<=?buff13;????
????????????????end
????????????else
????????????????begin
????????????????????buff0?<=?buff0;
????????????????????buff1?<=?buff1;????????
????????????????????buff2?<=?buff2;?????????
????????????????????buff3?<=?buff3;??????
????????????????????buff4?<=?buff4;??????
????????????????????buff5?<=?buff5;???????
????????????????????buff6?<=?buff6;????
????????????????????buff7?<=?buff7;???????
????????????????????buff8?<=?buff8;???????
????????????????????buff9?<=?buff9;???????
????????????????????buff10?<=?buff10;????????
????????????????????buff11?<=?buff11;???????
????????????????????buff12?<=?buff12;???????
????????????????????buff13?<=?buff13;???????
????????????????????buff14?<=?buff14;
????????????????end
????????end
????????
????/*?Multiply?stage?of?FIR?*/
????always?@?(posedge?clk)
????????begin
????????????if?(enable_fir?==?1'b1)
????????????????begin
????????????????????acc0?<=?tap0?*?buff0;
????????????????????acc1?<=?tap1?*?buff1;
????????????????????acc2?<=?tap2?*?buff2;
????????????????????acc3?<=?tap3?*?buff3;
????????????????????acc4?<=?tap4?*?buff4;
????????????????????acc5?<=?tap5?*?buff5;
????????????????????acc6?<=?tap6?*?buff6;
????????????????????acc7?<=?tap7?*?buff7;
????????????????????acc8?<=?tap8?*?buff8;
????????????????????acc9?<=?tap9?*?buff9;
????????????????????acc10?<=?tap10?*?buff10;
????????????????????acc11?<=?tap11?*?buff11;
????????????????????acc12?<=?tap12?*?buff12;
????????????????????acc13?<=?tap13?*?buff13;
????????????????????acc14?<=?tap14?*?buff14;
????????????????end
????????end????
????????
?????/*?Accumulate?stage?of?FIR?*/???
????always?@?(posedge?clk)?
????????begin
????????????if?(enable_fir?==?1'b1)
????????????????begin
????????????????????m_axis_fir_tdata?<=?acc0?+?acc1?+?acc2?+?acc3?+?acc4?+?acc5?+?acc6?+?acc7?+?acc8?+?acc9?+?acc10?+?acc11?+?acc12?+?acc13?+?acc14;
????????????????end
????????end?????
????
????
endmodule
創(chuàng)建仿真文件
要測試 FIR 模塊,需要創(chuàng)建一個測試平臺作為其仿真源:

在 FIR 模塊中有兩個主要的東西需要測試:濾波器算法和 AXI 流接口。為實現(xiàn)這一點,測試臺中創(chuàng)建了一個狀態(tài)機,它生成一個簡單的 200kHz 正弦波,并切換從屬端的有效信號和 FIR 接口主控端的tready信號。
FIR 模塊的測試平臺:
`timescale?1ns?/?1ps
module?tb_FIR;
????reg?clk,?reset,?s_axis_fir_tvalid,?m_axis_fir_tready;
????reg?signed?[15:0]?s_axis_fir_tdata;
????wire?m_axis_fir_tvalid;
????wire?[3:0]?m_axis_fir_tkeep;
????wire?[31:0]?m_axis_fir_tdata;
????
????/*
?????*?100Mhz?(10ns)?clock?
?????*/
????always?begin
????????clk?=?1;?#5;
????????clk?=?0;?#5;
????end
????
????always?begin
????????reset?=?1;?#20;
????????reset?=?0;?#50;
????????reset?=?1;?#1000000;
????end
????
????always?begin
????????s_axis_fir_tvalid?=?0;?#100;
????????s_axis_fir_tvalid?=?1;?#1000;
????????s_axis_fir_tvalid?=?0;?#50;
????????s_axis_fir_tvalid?=?1;?#998920;
????end
????
????always?begin
????????m_axis_fir_tready?=?1;?#1500;
????????m_axis_fir_tready?=?0;?#100;
????????m_axis_fir_tready?=?1;?#998400;
????end
????
????/*?Instantiate?FIR?module?to?test.?*/
????FIR?FIR_i(
????????.clk(clk),
????????.reset(reset),
????????.s_axis_fir_tdata(s_axis_fir_tdata),???
????????.s_axis_fir_tkeep(s_axis_fir_tkeep),???
????????.s_axis_fir_tlast(s_axis_fir_tlast),???
????????.s_axis_fir_tvalid(s_axis_fir_tvalid),?
????????.m_axis_fir_tready(m_axis_fir_tready),
????????.m_axis_fir_tvalid(m_axis_fir_tvalid),?
????????.s_axis_fir_tready(s_axis_fir_tready),?
????????.m_axis_fir_tlast(m_axis_fir_tlast),???
????????.m_axis_fir_tkeep(m_axis_fir_tkeep),???
????????.m_axis_fir_tdata(m_axis_fir_tdata));??
????????
????reg?[4:0]?state_reg;
????reg?[3:0]?cntr;
????
????parameter?wvfm_period?=?4'd4;
????
????parameter?init???????????????=?5'd0;
????parameter?sendSample0????????=?5'd1;
????parameter?sendSample1????????=?5'd2;
????parameter?sendSample2????????=?5'd3;
????parameter?sendSample3????????=?5'd4;
????parameter?sendSample4????????=?5'd5;
????parameter?sendSample5????????=?5'd6;
????parameter?sendSample6????????=?5'd7;
????parameter?sendSample7????????=?5'd8;
????
????/*?This?state?machine?generates?a?200kHz?sinusoid.?*/
????always?@?(posedge?clk?or?posedge?reset)
????????begin
????????????if?(reset?==?1'b0)
????????????????begin
????????????????????cntr?<=?4'd0;
????????????????????s_axis_fir_tdata?<=?16'd0;
????????????????????state_reg?<=?init;
????????????????end
????????????else
????????????????begin
????????????????????case?(state_reg)
????????????????????????init?:?//0
????????????????????????????begin
????????????????????????????????cntr?<=?4'd0;
????????????????????????????????s_axis_fir_tdata?<=?16'h0000;
????????????????????????????????state_reg?<=?sendSample0;
????????????????????????????end
????????????????????????????
????????????????????????sendSample0?:?//1
????????????????????????????begin
????????????????????????????????s_axis_fir_tdata?<=?16'h0000;
????????????????????????????????
????????????????????????????????if?(cntr?==?wvfm_period)
????????????????????????????????????begin
????????????????????????????????????????cntr?<=?4'd0;
????????????????????????????????????????state_reg?<=?sendSample1;
????????????????????????????????????end
????????????????????????????????else
????????????????????????????????????begin?
????????????????????????????????????????cntr?<=?cntr?+?1;
????????????????????????????????????????state_reg?<=?sendSample0;
????????????????????????????????????end
????????????????????????????end?
????????????????????????
????????????????????????sendSample1?:?//2
????????????????????????????begin
????????????????????????????????s_axis_fir_tdata?<=?16'h5A7E;?
????????????????????????????????
????????????????????????????????if?(cntr?==?wvfm_period)
????????????????????????????????????begin
????????????????????????????????????????cntr?<=?4'd0;
????????????????????????????????????????state_reg?<=?sendSample2;
????????????????????????????????????end
????????????????????????????????else
????????????????????????????????????begin?
????????????????????????????????????????cntr?<=?cntr?+?1;
????????????????????????????????????????state_reg?<=?sendSample1;
????????????????????????????????????end
????????????????????????????end?
????????????????????????
????????????????????????sendSample2?:?//3
????????????????????????????begin
????????????????????????????????s_axis_fir_tdata?<=?16'h7FFF;
????????????????????????????????
????????????????????????????????if?(cntr?==?wvfm_period)
????????????????????????????????????begin
????????????????????????????????????????cntr?<=?4'd0;
????????????????????????????????????????state_reg?<=?sendSample3;
????????????????????????????????????end
????????????????????????????????else
????????????????????????????????????begin?
????????????????????????????????????????cntr?<=?cntr?+?1;
????????????????????????????????????????state_reg?<=?sendSample2;
????????????????????????????????????end
????????????????????????????end?
????????????????????????
????????????????????????sendSample3?:?//4
????????????????????????????begin
????????????????????????????????s_axis_fir_tdata?<=?16'h5A7E;
????????????????????????????????
????????????????????????????????if?(cntr?==?wvfm_period)
????????????????????????????????????begin
????????????????????????????????????????cntr?<=?4'd0;
????????????????????????????????????????state_reg?<=?sendSample4;
????????????????????????????????????end
????????????????????????????????else
????????????????????????????????????begin?
????????????????????????????????????????cntr?<=?cntr?+?1;
????????????????????????????????????????state_reg?<=?sendSample3;
????????????????????????????????????end
????????????????????????????end?
????????????????????????
????????????????????????sendSample4?:?//5
????????????????????????????begin
????????????????????????????????s_axis_fir_tdata?<=?16'h0000;
????????????????????????????????
????????????????????????????????if?(cntr?==?wvfm_period)
????????????????????????????????????begin
????????????????????????????????????????cntr?<=?4'd0;
????????????????????????????????????????state_reg?<=?sendSample5;
????????????????????????????????????end
????????????????????????????????else
????????????????????????????????????begin?
????????????????????????????????????????cntr?<=?cntr?+?1;
????????????????????????????????????????state_reg?<=?sendSample4;
????????????????????????????????????end
????????????????????????????end?
????????????????????????
????????????????????????sendSample5?:?//6
????????????????????????????begin
????????????????????????????????s_axis_fir_tdata?<=?16'hA582;?
????????????????????????????????
????????????????????????????????if?(cntr?==?wvfm_period)
????????????????????????????????????begin
????????????????????????????????????????cntr?<=?4'd0;
????????????????????????????????????????state_reg?<=?sendSample6;
????????????????????????????????????end
????????????????????????????????else
????????????????????????????????????begin?
????????????????????????????????????????cntr?<=?cntr?+?1;
????????????????????????????????????????state_reg?<=?sendSample5;
????????????????????????????????????end
????????????????????????????end?
????????????????????????
????????????????????????sendSample6?:?//6
????????????????????????????begin
????????????????????????????????s_axis_fir_tdata?<=?16'h8000;?
????????????????????????????????
????????????????????????????????if?(cntr?==?wvfm_period)
????????????????????????????????????begin
????????????????????????????????????????cntr?<=?4'd0;
????????????????????????????????????????state_reg?<=?sendSample7;
????????????????????????????????????end
????????????????????????????????else
????????????????????????????????????begin?
????????????????????????????????????????cntr?<=?cntr?+?1;
????????????????????????????????????????state_reg?<=?sendSample6;
????????????????????????????????????end
????????????????????????????end?
????????????????????????
????????????????????????sendSample7?:?//6
????????????????????????????begin
????????????????????????????????s_axis_fir_tdata?<=?16'hA582;?
????????????????????????????????
????????????????????????????????if?(cntr?==?wvfm_period)
????????????????????????????????????begin
????????????????????????????????????????cntr?<=?4'd0;
????????????????????????????????????????state_reg?<=?sendSample0;
????????????????????????????????????end
????????????????????????????????else
????????????????????????????????????begin?
????????????????????????????????????????cntr?<=?cntr?+?1;
????????????????????????????????????????state_reg?<=?sendSample7;
????????????????????????????????????end
????????????????????????????end?????????????????????
????????????????????
????????????????????endcase
????????????????end
????????end
????
endmodule
運行行為仿真
FIR 模塊及其測試平臺文件就位后,從 Flow Navigator 窗口啟動 Vivado 中的仿真器,選擇 Run Behavioral Simulation 選項。

如行為仿真所示,F(xiàn)IR 正確過濾信號并正確響應 AXI 流信號。文章來源:http://www.zghlxwxcb.cn/news/detail-489537.html

總結
代碼都在上面大家有興趣可以自行運行,但是大家可能會注意到,這個 FIR 模塊在設計上運行綜合和實現(xiàn)時時序應該是不能通過的。我們將在下一篇文章中詳細介紹如何在無法滿足時序要求時重新設計你的設計~文章來源地址http://www.zghlxwxcb.cn/news/detail-489537.html

到了這里,關于FPGA 的數(shù)字信號處理:Verilog 實現(xiàn)簡單的 FIR 濾波器的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!