該項目介紹了如何使用 Verilog 實現具有預生成系數的簡單 FIR 濾波器。
緒論
不起眼的 FIR 濾波器是 FPGA 數字信號處理中最基本的模塊之一,因此了解如何將具有給定抽頭數及其相應系數值的基本模塊組合在一起非常重要。因此,在這個關于 FPGA 上 DSP 基礎實用入門的教程中,將從一個簡單的 15 抽頭低通濾波器 FIR 開始,在 Matlab 中為其生成初始系數值,然后轉換這些值用于編寫 Verilog 模塊。
有限脈沖響應或 FIR 濾波器定義為脈沖響應在特定時間段內穩定為零值的濾波器。脈沖響應穩定到零所花費的時間與濾波器階數(抽頭數)直接相關,濾波器階數是 FIR 的基礎傳遞函數多項式的階數。FIR 的傳遞函數不包含反饋,因此如果輸入一個值為 1 的脈沖,然后輸入一串零值,輸出將只是濾波器的系數值。
濾波器的作用基本都是用于信號調節,主要集中在選擇濾除或允許通過哪些頻率。最簡單的例子之一是低通濾波器,它允許低于某個閾值(截止頻率)的頻率通過,同時大大衰減高于該閾值的頻率,如下圖所示。
該項目的主要重點是在 HDL(具體為 Verilog)中實現 FIR,它可以分解為三個主要邏輯組件:一個循環緩沖器,用于將每個樣本計時到適當地考慮了串行輸入的延遲、每個抽頭系數值的乘法器以及每個抽頭輸出的求和結果的累加器。
由于本項目專注于 FPGA 邏輯中 FIR 的設計機制,所以只是使用 Simulink 中的 FDA 工具和 Matlab 為低通濾波器插入一些簡單參數,然后使用生成的系數值放到 Verilog 模塊中完成濾波器的設計(在后面的步驟中完成)。
選擇實現一個簡單的 15 抽頭低通濾波器 FIR,采樣率為 1Ms/s,通帶頻率為 200kHz,阻帶頻率為 355kHz,得到以下系數:
-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 模塊創建設計文件
在 Vivado 項目中添加源文件。
在確定 FIR 的順序(抽頭數)并獲得系數值后,接下來需要定義的下一組參數就是輸入樣本、輸出樣本和系數本身的位寬。
對于這個 FIR,選擇將輸入樣本和系數寄存器設置為 16 位寬,并將輸出樣本寄存器設置為 32 位,因為兩個 16 位值的乘積是一個 32 位值(兩個值的寬度相乘得到乘積的寬度,所以如果選擇了 8 位抽頭的 16 位輸入樣本,那么輸出樣本將為 24 位寬)。
這些值也都是帶符號的,因此 MSB 用作符號位,在選擇輸入樣本寄存器的初始寬度時一定要記住這一點。要在 Verilog 中將這些值設置為有符號數據類型,使用關鍵字signed :
regsigned[15:0]register_name;
接下來要解決的是如何在 Verilog 中處理系數值,小數點值需要轉換為定點值。由于所有系數值都小于 1,因此寄存器的所有 15 位(總共 16 位,MSB 是有符號位)都可以用于小數位。通常,必須決定要將寄存器中的多少位用于數字的整數部分與數字的小數部分。因此,轉換分數值抽頭的數學是:(fractional coefficient value)*(2^(15))該乘積的小數值被四舍五入,并且如果系數為負,則計算該值的二進制補碼:
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
現在我們終于準備好關注 FIR 模塊的邏輯,第一個是循環緩沖區,它引入串行輸入樣本流并為濾波器的 15 個抽頭創建一個包含 15 個輸入樣本的數組。
always@(posedgeclk) 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
接下來,乘法階段將每個樣本乘以每個系數值:
/*MultiplystageofFIR*/ always@(posedgeclk) 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
乘法階段的結果值通過加法累加到寄存器中,最終成為濾波器的輸出數據流。
/*AccumulatestageofFIR*/ always@(posedgeclk) 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
最后,邏輯的最后一部分是將數據流進和流出 FIR 模塊的接口。AXI Stream 接口是最常見的接口之一。關鍵方面是允許控制上游和下游設備之間的數據流的tready和tvalid信號。這意味著 FIR 模塊需要向其下游設備提供tvalid信號以指示其輸出是有效數據,并且如果下游設備解除其tready信號,則能夠暫停(但仍保留)其輸出。FIR 模塊還必須能夠與其主端接口上的上游設備以同樣的方式運行。
以下是 FIR 模塊的邏輯設計概述:
請注意tready和tvalid信號如何設置輸入循環緩沖器的使能值和 FIR 的乘法級以及數據或系數通過的每個寄存器都被聲明為有符號的。
FIR模塊Verilog代碼:
`timescale1ns/1ps moduleFIR( inputclk, inputreset, inputsigned[15:0]s_axis_fir_tdata, input[3:0]s_axis_fir_tkeep, inputs_axis_fir_tlast, inputs_axis_fir_tvalid, inputm_axis_fir_tready, outputregm_axis_fir_tvalid, outputregs_axis_fir_tready, outputregm_axis_fir_tlast, outputreg[3:0]m_axis_fir_tkeep, outputregsigned[31:0]m_axis_fir_tdata ); always@(posedgeclk) 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
創建仿真文件
要測試 FIR 模塊,需要創建一個測試平臺作為其仿真源:
在 FIR 模塊中有兩個主要的東西需要測試:濾波器算法和 AXI 流接口。為實現這一點,測試臺中創建了一個狀態機,它生成一個簡單的 200kHz 正弦波,并切換從屬端的有效信號和 FIR 接口主控端的tready信號。
FIR 模塊的測試平臺:
`timescale1ns/1ps moduletb_FIR; regclk,reset,s_axis_fir_tvalid,m_axis_fir_tready; regsigned[15:0]s_axis_fir_tdata; wirem_axis_fir_tvalid; wire[3:0]m_axis_fir_tkeep; wire[31:0]m_axis_fir_tdata; /* *100Mhz(10ns)clock */ alwaysbegin clk=1;#5; clk=0;#5; end alwaysbegin reset=1;#20; reset=0;#50; reset=1;#1000000; end alwaysbegin 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 alwaysbegin m_axis_fir_tready=1;#1500; m_axis_fir_tready=0;#100; m_axis_fir_tready=1;#998400; end /*InstantiateFIRmoduletotest.*/ FIRFIR_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; parameterwvfm_period=4'd4; parameterinit=5'd0; parametersendSample0=5'd1; parametersendSample1=5'd2; parametersendSample2=5'd3; parametersendSample3=5'd4; parametersendSample4=5'd5; parametersendSample5=5'd6; parametersendSample6=5'd7; parametersendSample7=5'd8; /*Thisstatemachinegeneratesa200kHzsinusoid.*/ always@(posedgeclkorposedgereset) 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 選項。
如行為仿真所示,FIR 正確過濾信號并正確響應 AXI 流信號。
總結
代碼都在上面大家有興趣可以自行運行,但是大家可能會注意到,這個 FIR 模塊在設計上運行綜合和實現時時序應該是不能通過的。我們將在下一篇文章中詳細介紹如何在無法滿足時序要求時重新設計你的設計~
審核編輯:湯梓紅
-
FPGA
+關注
關注
1626文章
21678瀏覽量
602040 -
濾波器
+關注
關注
160文章
7749瀏覽量
177737 -
數字信號處理
+關注
關注
15文章
559瀏覽量
45801 -
FIR
+關注
關注
4文章
146瀏覽量
33123 -
Verilog
+關注
關注
28文章
1345瀏覽量
109996
原文標題:FPGA 的數字信號處理:Verilog 實現簡單的 FIR 濾波器
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論