PS:此文章仅供参考
前言
本文介绍了使用VHDL语言实现一个FIR滤波器的设计
以下是本篇文章正文内容,代码可供参考
一、什么是FIR滤波器?
通常数字滤波器常用于修正或改变时域中信号的属性。学过信号与系统的同学应该知道,最为普通的数字滤波器就是 线性时不变量(LTI)滤波器,线性时不变量滤波器又分为两大类:有限脉冲响应(FIR)滤波器和无线脉冲响应(IIR)滤波器,FIR滤波器的组成结构如下图所示,该滤波器的优点在于其不再需要给X[n]提供额外的移位寄存器。
简单的来说就是
二、程序编写
1.顶层程序DTFIR.vhd
代码如下:
--顶层
LIBRARY LPM;
USE LPM.LPM_COMPONENTS.ALL;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY DTFIR IS
PORT(K:IN STD_LOGIC;
CLK:IN STD_LOGIC;
CLK2:IN STD_LOGIC;
COM:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY DTFIR;
ARCHITECTURE ART OF DTFIR IS
COMPONENT KG IS
PORT(CLK:IN STD_LOGIC;
K:IN STD_LOGIC;
TIMES:OUT STD_LOGIC);
END COMPONENT KG;
COMPONENT CLKGEN IS
PORT(CLK: IN STD_LOGIC;
NEWCLK: OUT STD_LOGIC);
END COMPONENT CLKGEN;
COMPONENT KZSR IS
PORT(CLK:IN STD_LOGIC;
XOUT:OUT STD_LOGIC_VECTOR(8 DOWNTO 0);
LOAD:OUT STD_LOGIC;
COUT:OUT STD_LOGIC_VECTOR(8 DOWNTO 0));
END COMPONENT KZSR;
COMPONENT FIR IS
GENERIC(W1:INTEGER:=9;
W2:INTEGER:=18;
W3:INTEGER:=19;
W4:INTEGER:=11;
L:INTEGER:=4;
MPIPE:INTEGER:=3);
PORT(CLK,LOAD_X:IN STD_LOGIC;
X_IN,C_IN:IN STD_LOGIC_VECTOR(W1-1 DOWNTO 0);
Y_OUT:OUT STD_LOGIC_VECTOR(W4-1 DOWNTO 0));
END COMPONENT FIR;
COMPONENT XSKZQ IS
PORT (ABCD:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
G,S,B,Q:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END COMPONENT XSKZQ;
COMPONENT CTRLS IS
PORT(CLK: IN STD_LOGIC;
SEL: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END COMPONENT CTRLS;
COMPONENT DISPLAY IS
PORT(SEL: IN STD_LOGIC_VECTOR(2 DOWNTO 0);
G,S,B,Q: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
COM: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG: OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT DISPLAY;
SIGNAL CK:STD_LOGIC;
SIGNAL S0,S1,S2:STD_LOGIC;
SIGNAL SD:STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL SL:STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL SM:STD_LOGIC_VECTOR(10 DOWNTO 0);
SIGNAL A,B,C,D:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL SE:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
U0: KG PORT MAP(CLK=>CLK,K=>K,TIMES=>S0);
U1: CLKGEN PORT MAP(S0,CK);
U2: KZSR PORT MAP(CK,SD,S1,SL);
U3: FIR PORT MAP(CK,S1,SD,SL,SM);
U4: XSKZQ PORT MAP(SM,A,B,C,D);
U5: CTRLS PORT MAP(CLK2,SE);
U6: DISPLAY PORT MAP(SE,A,B,C,D,COM,SEG);
END ARCHITECTURE ART;
顶层代码也可采用原理图输入的方法,这里简单介绍一下在Quartus II软件中,顶层程序原理图输入使用。
第一步:将所需工程的各种底层模块代码编写完毕,并验证其是否正确。
第二步:右键程序文件,点击Create Symbol File for Current file 创建一个原理图模块
生成好的原理图模块如下图所示:
之后在工程目录中新建一个原理图工程.bdf后缀的文件,之后添加各个模块,连线编译就可以了,此次工程的原理图输入如下图所示:
2.开关控制程序 KG.vhd
使用一个外部拨码开关控制外部输入时钟信号,达到滤波器的启动停止功能。
外部输入 KG.vhd 代码如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY KG IS
PORT(CLK:IN STD_LOGIC;
K:IN STD_LOGIC;
TIMES:OUT STD_LOGIC);
END ENTITY KG;
ARCHITECTURE ART OF KG IS
BEGIN
PROCESS(CLK,K)IS
BEGIN
IF K='1' THEN
TIMES<=CLK;
ELSE
TIMES<='0';
END IF;
END PROCESS;`
END ARCHITECTURE ART;
3.数码管的控制程序 KZSR.vhd
此程序为FIR滤波器的前级程序,使用1Hz的时钟信号同步控制,在时钟下降沿的时候将FIR滤波器的所需的系数C_IN与变量X_IN装载进FIR.vhd程序中,其中可根据自己的所需设定不同的XOUT的值输入进FIR.vhd 程序中进行运算。
程序源码如下,可自行参考:
--数码管控制文件
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY KZSR IS
PORT(CLK:IN STD_LOGIC;
XOUT:OUT STD_LOGIC_VECTOR(8 DOWNTO 0);
LOAD:OUT STD_LOGIC;
COUT:OUT STD_LOGIC_VECTOR(8 DOWNTO 0));
END ENTITY KZSR;
ARCHITECTURE ART OF KZSR IS
SIGNAL SEL:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL A:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(SEL,CLK)
BEGIN
IF CLK'EVENT AND CLK='0' THEN
SEL<=SEL+'1';
ELSE
NULL;
END IF;
IF CLK'EVENT AND CLK='0' THEN
A<=A+'1';
ELSE NULL;
END IF;
CASE A IS
WHEN "0000"=>LOAD<='0';
WHEN "0001"=>LOAD<='0';
WHEN "0010"=>LOAD<='0';
WHEN "0011"=>LOAD<='0';
WHEN OTHERS=>LOAD<='1';
END CASE;
CASE SEL IS
WHEN "0000"=>COUT<="001111100";XOUT<="000000000";
WHEN "0001"=>COUT<="011010110";XOUT<="000000000";
WHEN "0010"=>COUT<="000111001";XOUT<="000000000";
WHEN "0011"=>COUT<="111011111";XOUT<="000000000";
WHEN "0100"=>XOUT<="001100100";COUT<="000000000";
WHEN "0101"=>XOUT<="010010110";COUT<="000000000";
WHEN "0110"=>XOUT<="011001000";COUT<="000000000";
WHEN "0111"=>XOUT<="011111010";COUT<="000000000";
WHEN OTHERS=>XOUT<="000000000";COUT<="000000000";
END CASE;
END PROCESS;
END ARCHITECTURE ART;
4.FIR滤波器程序 FIR.vhd
--FIR滤波器设计
LIBRARY LPM;
USE LPM.LPM_COMPONENTS.ALL;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY FIR IS
GENERIC(W1:INTEGER:=9;
W2:INTEGER:=18;
W3:INTEGER:=19;
W4:INTEGER:=11;
L:INTEGER:=4;
MPIPE:INTEGER:=3);
PORT(CLK,LOAD_X:IN STD_LOGIC;
X_IN,C_IN:IN STD_LOGIC_VECTOR(W1-1 DOWNTO 0);
Y_OUT:OUT STD_LOGIC_VECTOR(W4-1 DOWNTO 0));
END ENTITY FIR;
ARCHITECTURE ART OF FIR IS
SUBTYPE N1BIT IS STD_LOGIC_VECTOR(W1-1 DOWNTO 0);
SUBTYPE N2BIT IS STD_LOGIC_VECTOR(W2-1 DOWNTO 0);
SUBTYPE N3BIT IS STD_LOGIC_VECTOR(W3-1 DOWNTO 0);
TYPE ARRAY_N1BIT IS ARRAY(0 TO L-1)OF N1BIT;
TYPE ARRAY_N2BIT IS ARRAY(0 TO L-1)OF N2BIT;
TYPE ARRAY_N3BIT IS ARRAY(0 TO L-1)OF N3BIT;
SIGNAL X:N1BIT;
SIGNAL Y:N3BIT;
SIGNAL C:ARRAY_N1BIT; --系数C的数组
SIGNAL P:ARRAY_N2BIT; --单项乘积数组
SIGNAL A:ARRAY_N3BIT; --加法矩阵
BEGIN
LOAD:PROCESS IS
BEGIN
WAIT UNTIL CLK='1';
IF(LOAD_X='0')THEN
C(L-1)<=C_IN;
FOR I IN L-2 DOWNTO 0 LOOP
C(I)<=C(I+1);
END LOOP;
ELSE
X<=X_IN;
END IF;
END PROCESS LOAD;
SOP:PROCESS(CLK)IS
BEGIN
IF CLK'EVENT AND (CLK='1') THEN
FOR I IN 0 TO L-2 LOOP
A(I)<=(P(I)(W2-1)&P(I))+A(I+1);
END LOOP;
A(L-1)<=P(L-1)(W2-1)&P(L-1);
END IF;
Y<=A(0);
END PROCESS SOP;
--流水线乘法器
MULGEN:FOR I IN 0 TO L-1 GENERATE
MULS:LPM_MULT
GENERIC MAP(LPM_WIDTHA=>W1,LPM_WIDTHB=>W1,
LPM_PIPELINE=>MPIPE,LPM_REPRESENTATION=>"SIGNED",
LPM_WIDTHP=>W2,LPM_WIDTHS=>W2)
PORT MAP(CLOCK=>CLK,DATAA=>X,DATAB=>C(I),RESULT=>P(I));
END GENERATE;
Y_OUT<=Y(W3-1 DOWNTO W3-W4);
END ARCHITECTURE ART;
仿真显示如下:
5.数码管显示控制程序 XSKZQ.vhd
--数码管显示控制电路文件
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY XSKZQ IS
PORT (ABCD:IN STD_LOGIC_VECTOR(10 DOWNTO 0);
G,S,B,Q:OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END ENTITY XSKZQ;
ARCHITECTURE ART OF XSKZQ IS
SIGNAL TEMP1,TEMP2,TEMP3,TEMP4:INTEGER RANGE 0 TO 9;
SIGNAL T0,T1,T2,T3:INTEGER RANGE 0 TO 10#9999#;
BEGIN
PROCESS (ABCD) IS
BEGIN
T0<=CONV_INTEGER(ABCD);T1<=T0-T0/1000*1000;T2<=T1-T1/100*100;T3<=T2-T2/10*10;
TEMP1<=T3;
TEMP2<=(T2-T3)/10;
TEMP3<=(T1-T2)/100;
TEMP4<=(T0-T1)/1000;
CASE TEMP1 IS
WHEN 0 =>G<="0000";
WHEN 1 =>G<="0001";
WHEN 2 =>G<="0010";
WHEN 3 =>G<="0011";
WHEN 4 =>G<="0100";
WHEN 5 =>G<="0101";
WHEN 6 =>G<="0110";
WHEN 7 =>G<="0111";
WHEN 8 =>G<="1000";
WHEN 9 =>G<="1001";
WHEN OTHERS=>G<="0000";
END CASE;
CASE TEMP2 IS
WHEN 0 =>S<="0000";
WHEN 1 =>S<="0001";
WHEN 2 =>S<="0010";
WHEN 3 =>S<="0011";
WHEN 4 =>S<="0100";
WHEN 5 =>S<="0101";
WHEN 6 =>S<="0110";
WHEN 7 =>S<="0111";
WHEN 8 =>S<="1000";
WHEN 9 =>S<="1001";
WHEN OTHERS=>S<="0000";
END CASE;
CASE TEMP3 IS
WHEN 0 =>B<="0000" ;
WHEN 1 =>B<="0001";
WHEN 2 =>B<="0010";
WHEN 3 =>B<="0011";
WHEN 4 =>B<="0100";
WHEN 5 =>B<="0101";
WHEN 6 =>B<="0110";
WHEN 7 =>B<="0111";
WHEN 8 =>B<="1000";
WHEN 9 =>B<="1001";
WHEN OTHERS=>B<="0000";
END CASE;
CASE TEMP4 IS
WHEN 0 =>Q<="0000" ;
WHEN 1 =>Q<="0001";
WHEN 2 =>Q<="0010";
WHEN 3 =>Q<="0011";
WHEN 4 =>Q<="0100";
WHEN 5 =>Q<="0101";
WHEN 6 =>Q<="0110";
WHEN 7 =>Q<="0111";
WHEN 8 =>Q<="1000";
WHEN 9 =>Q<="1001";
WHEN OTHERS=>Q<="0000";
END CASE;
END PROCESS;
END ARCHITECTURE ART;
6、RTL图显示结果
其中后面的DISPLAY.vhd与CTRL.vhd数码管显示驱动程序文件比较常见这里就不再赘述,大家可自行查阅资料。文章来源:https://www.toymoban.com/news/detail-412281.html
总结
以上就是今天要讲的内容,本文仅仅简单介绍了使用VHDL语言设计FIR滤波器,同过使用FPGA进行逻辑综合实现FIR滤波器的数字化显示功能。
最后,非常感谢学长们对我的指导和帮助,让我完成了此次的FIR滤波器的设计。有更好方案的也希望大家在评论去留言。文章来源地址https://www.toymoban.com/news/detail-412281.html
到了这里,关于【VHDL笔记】 FIR滤波器的设计(基于Quartus II软件)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!