1. FIR Filters with FPGA
Page | 1
FIR Filters with FPGAs
ECE 5211
irvin rynning
10 May 2016
2. FIR Filters with FPGA
Page | 2
Contents:
Front page 1
Contents 2
Part 1
Introduction and Motivation 3
Goals 3
Outside Sources 3
Part 2
Project Description 3
Interface 4
System Diagram 5
Design Flow 5
FIR Filter Design 6
Implementation 8
Part 3
Hardware Design 8
Block Diagram 8
Peripherals 10
Problems 10
Part 4
Discussion and results 11
Conclusion 12
References 13
Summary 14
Code 15
Main Wrapper 16
Digital to Analog 20
Second Wrapper 24
3. FIR Filters with FPGA
Page | 3
This project was motivated by the desire to use a Field Programmable Gate Array (FPGA) to
accomplish a task in which its performance would rival that of an embedded system or
microprocessor. Previously I had experience in using the Texas Instruments TMDSLCDK6748i
,
which provided for sixteen bit, floating point arithmetic with sample rate from 8 kHz to 96 kHz, and
implemented using the Integrated Development Environment (IDE) called Code Composer in the
both Cee programming language and an Assembly language.
On this platform were developed real-time applications such as sweep oscillators, Finite Impulse
Response (FIR) and Infinite Impulse response (IIR) filters, as well as analog equivalents in dynamics
processing (compressors, gates, expanders), and time domain effects such as a “flanger”, chorus, and
digital delay used in musical performance and production. The FIR caught my attention as it
offered incredibly steep cutoffs coupled with minimal phase delay and distortion, processing which
is normally done after the fact — i.e., not in real time — due to the high latency (or time delay) of
the process. For example
Goal
The goal of this project then is three-fold:
1) Development the FPGA to pass audio frequencies from input to output
2) Incorporate a FIR of the several types
a) High pass
b) Low pass
c) Band pass
3) Add more FIRs of increasing depth (stages) to observe real-time performance
This is done on a qualitative basis, and will not measure time delays and real time parameters, nor
use various sample rates to find limitations on performance. Indeed I did not expect to achieve the
results I did.
Outside Sources
Other sources for Verilog programming and fpga implementation are as follows:
Embedded Design Using Programmable Gate Arrays, Dennis Silageii
The Verilog Hardware Description Language, 5th
Edition, Thomas & Moorby.iii
Advanced Digital Design, M Cilletti.iv
Spartan-3E FPGA Starter Kit Board User Guide, Xilinx Incv
.
Core Generator Guide, Xilinx Inc.vi
This project evolved from the Homework Seven of the course in Rapid Prototyping with FPGA, ECE-
5211, taught by Dr D. Perera in the Spring of 2016. In this assignment the embedded preamplifier
4. FIR Filters with FPGA
Page | 4
and analog to digital converter was implemented, and the conversion result displayed on the light
emitting diodes (LEDs), also on the FPGA.
From this I added the digital to analog conversion, setting up timing parameters, and creating an
analog signal on the connecting header called J5 on the circuit board which echoed the input.
Interface
Necessary were two interface designs:
The first was adjusting the input signal to be referenced to ½ the power voltage of +3.3 volts,
shown in figure 1. The connections were made to the 6-pin ADC Header (J7), using the input A, as
well as the GND and VCC pins.
Figure 1 Input circuit
The second was the output from 6-pin DAC Header (J5), using output A and the GND pins, and
shown in figure 2. The Spartan 3E board does not have any low pass filtering for digital to analog
conversion, and thus aliasing is expected. Further work implementing a typical Butterworth analog
filter using a dual operational amplifier (op amp) would be essential.
5. FIR Filters with FPGA
Page | 5
Figure 2 Output circuit
System Diagram
System Diagram
FIRsSignalFlowClocks
Input Interface
Preamp/ADC
SPI Clock
DAC
SPI Clock
Multiplexer
FIRs in
To DAC Out
FIRS
Digital Clock
Manager
Translation to FIRS
50 MHz
CLK FX
×4 ÷5 > 40MHZ
CLX DIV
12½MHz
Everywhere
40MHz/100 = 40kHz
SPI Clock
Output Interface
Slide Switches
Gain
Select FIR
Figure 3 Diagram showing major components
Design Flow
After completing homework seven, and developing a free running analog to digital converter (ADC)
and using an SPI clock of 12.5 MHz — the sample rate Fs was not implemented, other than the
ADCONV signal which was 34 × SPI clock, or — 2.72µs, about 367kHz — I then attacked the
digital to analog convertor (DAC). This first took a translation of the 14 bit signed integer data to
the 12 bit unsigned required by the DAC. This algorithm is as follows, given signals ADC_data and
DAC_data.
wire [13:0] ADC_data;
wire [11:0] DAC_data;
wire [13:0] temp;
always @ ( * ) begin
temp[13] = ~(ADC_data[13]) ;
6. FIR Filters with FPGA
Page | 6
temp[12:0] = ADC_data[12:0] ;
DAC_data = ~( temp[13:2] ;
end
Once good throughput of the incoming analog signal — which was always in the extended audio
frequency range, 10 Hz to 50 kHz — was obtained I then went into FIR filter design.
Fir Filter Design
FIR filters are essentially multiply and add algorithms, with a given set of constants and a buffer of
previous samples. A brief summary of this is given with figure 4. Successive input samples are
loaded into a buffer whose length is the number of stages, each element of the buffer is multiplied
by a constant, and the results are summed to create the output sample. The sample buffer is shifted
with the next being inserted, and the process repeats.
Figure 4 FIR block diagram from Cilletti
7. FIR Filters with FPGA
Page | 7
I investigated the Xilinx CORE development tools, such as floating point conversions and
operations, and block core memories, and then found that there exists a FIR CORE tool,vii
called IP
LogiCORE FIR Compiler, as well as several videos, one of which is referenced hereviii
.
Figure 5 Page 1 of the CORE FIR Compiler
I will not go into detail of the use of this tool other than to mention caveats and issues I had. The
first is the use of a coefficients file— highly recommended, using the MatLab fdatool to create a set
of 16 bit signed integers, as well as giving a graphical display of response. It is noted that the Freq.
Response in above (figure 4) mirrors the one that MatLab creates (figure 5).
8. FIR Filters with FPGA
Page | 8
Figure 6 MatLab Created Response
Additionally there is a setting for input bit width (16) and fractional depth (always 15). When the
latter is set to 0 or 1, there is no output. The control lines for the filters were not implemented, as
this is free running.
Implementation
After getting the throughput working and adding one filter, I then proceeded to add additional ones,
with the use of the slide switches to control the output. I then implemented the network analyzer
(otherwise called a spectrum analyzer) which generated an input of 10 Hz to a maximum of one half
the sample rate. The sample rate was chosen to be arithmetically simple, 1000th
of a 40 MHz clock.
This Fs = 40 kHz has a period of 25 ms, which the ADC, starting on the positive edge of Fs, taking
34× SPI clock < 12.5 ms, as well as the output y[n] sample being determined in time for the DAC to
take place on the negative edge of Fs. No glitches were observed in FIRs as great as some 110
stages.
A block diagram generated using Microsoft’s Visio program is as follows. This shows four FIR
filters being implements, their outputs being selected by the slide switches called SW on the Spartan
3E board. It shows the elements of the code and the hardware, and the interconnections. There is a
discharge path 100kΩ resistor from the input coupling capacitor to ground not shown.
Also not shown are all the clocks, as well as the data path width (number of bits).
the input is marked with a square wave symbol, and the output with a sine wave. This is actually
indicative of the performance of the filter, e.g., when a 1 kHz square is input and the “2 kHz low
pass” filter selected, the output is a sine, for the third harmonic, 3 kHz, is down 40dB.
10. FIR Filters with FPGA
Page | 10
External devices found in the project include a DC shift mixer for the ADC input, implemented
using a resistor divider to create a 50% VCC level, which is added to an AC coupled source from an
oscillator or other signal generating device. The other is a DC blocking capacitor and a minimal
response passive low pass filter on the DAC output. AS the testing was not done with a focus on the
upper octave signals (10 kHz–20 kHz), this was not an issue. A better implementation would include
active devices (op amps) on input to provide isolation and DC level shift, and on the output to
provide a steeper low pass response. It is to be noted that actually listening to a typical tone through
loudspeakers was rather harsh, owing to the aliasing.
Development problems have already been mentioned, but I will reiterate them (and others) here.
Input DC Level Shift:
As discovered in homework seven, the input is clipped if it goes below 0 V with reference to the
GND from the board. Thus a mixer is required, which raises the DC level to 50% of Vcc, 1•65 V
while maintaining impedance and DC isolation.
Signed versus Unsigned
A useful, fast and simple algorithm was needed to translate the ADC data. Without translation, the
output jumped from 0x0000 to 0x3fff when viewing a sine wave, creating an “upside down”
chopped effect.
Data Length Conversion
Significant noise is introduced when altering data lengths from 14 bits to 16, and again from 30 plus
bits from the filters, to the 12 bits needed for DAC. This is noted in the analyzer waveforms.
Output DC level Shift
A simple blocking capacitor, with suitable discharge resistors, was implemented.
Output Low Pass
Only a simple 6dB roll off passive filter was used. This was insufficient to offer a listening, or aural,
quality. Necessary is an active filter, using op amps, which necessitates additional power source(s),
which should measure at least 9V to ensure op amp performance.
11. FIR Filters with FPGA
Page | 11
Three of the FIR cores implemented worked well.
A simple low pass at 100 Hz is shown with theoretical and actual measurement.
Figure 8 100 Hz low pass filter, from MatLab. Figure 9 100 Hz Low pass, measured
Figure 10 Bandpass 2 - 4 kHz from MatLab Figure 11 2-4 kHz bandpass measured
12. FIR Filters with FPGA
Page | 12
Figure 12 2 kHz low passd, from MatLab Figure 13 2 kHz low pass, measured
The use of the Xilinx Core design tool is ripe with confusion. Two filters worked perfectly, a third
had a high noise figure, and two not at all. The lack of a good low pass filter aggravated pictorial
results. I think that tighter control of the filter — as opposed to its free running — might abet the
noise glitches observed. Using the alternative, hard-coded form of the filter as opposed to the Core
generator might give better results, but it would need some manner of automation for higher orders,
say, greater than 100.
Future work would be on several fronts, getting better accuracy and less noise, and implementing
parallel outputs for the several filters, as well as using a stereo (dual channel) source. Additionally
using higher sample rates should be tried, as well as measuring the time delay to create the next
output sample.
13. FIR Filters with FPGA
Page | 13
i TMS320C6748 Fixed/Floating Point DSP, Texas Instruments, http://www.ti.com/lit/ds/symlink/tms320c6748.pdf,
2014.
ii Embedded design Using Programmable Gate Arrays, Dennis Silage, Temple University, Bookstand Publishing, Gilroy Cal,
2008.
iii The Verilog Hardware Description Language, 5th Edition, D Thomas, P Moorby, Springer, New York, 2002.
iv Advanced Digital design, M Cilletti, Person Publishing, Upper Saddle River, NJ, 2003.
v Spartan-3E FPGA Starter Kit Board User Guide, Xilinx Inc, www.xilinx.com, 2008.
vi Core Generator Guide, Xilinx Inc., www.xilinx.com, 2000.
vii IP LogiCORE FIR Compiler v5.0, Xilinx,
http://www.xilinx.com/support/documentation/ip_documentation/fir_compiler_ds534.pdf, 2011.
viiiviii Xilinx ISE FIR Core Complier, https://youtu.be/MUoJtv_M48M, “eazye8523”, 2015.
14. FIR Filters with FPGA
Page | 14
vProj_fir_25Passes Project Status (05/10/2016 - 17:23:35)
Project File: proj40k.xise Parser Errors: No Errors
Module Name: vProj_fir_25_6 Implementation State:
Programming File
Generated
Target Device: xc3s500e-4fg320
Errors:
No Errors
Product
Version:
ISE 14.5
Warnings:
86 Warnings (86 new)
Design Goal: Balanced
Routing Results: All Signals Completely
Routed
Design
Strategy:
Xilinx Default
(unlocked)
Timing Constraints:
All Constraints Met
Environment: System Settings
Final Timing Score:
0 (Timing Report)
Device Utilization Summary [-]
Logic Utilization Used Available Utilization Note(s)
Total Number Slice Registers 1,423 9,312 15%
Number used as Flip Flops 1,409
Number used as Latches 14
Number of 4 input LUTs 1,206 9,312 12%
Number of occupied Slices 1,072 4,656 23%
Number of Slices containing only related
logic
1,072 1,072 100%
Number of Slices containing unrelated logic 0 1,072 0%
Total Number of 4 input LUTs 1,398 9,312 15%
Number used as logic 901
Number used as a route-thru 192
Number used for Dual Port RAMs 24
Number used as Shift registers 281
Number of bonded IOBs 30 232 12%
Number of RAMB16s 17 20 85%
15. FIR Filters with FPGA
Page | 15
Number of BUFGMUXs 5 24 20%
Number of DCMs 1 4 25%
Number of MULT18X18SIOs 6 20 30%
Average Fanout of Non-Clock Nets 2.22
Performance Summary [-]
Final Timing
Score:
0 (Setup: 0, Hold: 0, Component Switching
Limit: 0)
Pinout
Data:
Pinout Report
Routing Results: All Signals Completely Routed
Clock
Data:
Clock Report
Timing
Constraints:
All Constraints Met
Detailed Reports [-]
Report Name Status Generated Errors Warnings Infos
Synthesis Report Current
Tue May 10
17:20:11 2016
0
63 Warnings (63
new)
11 Infos (11
new)
Translation Report Current
Tue May 10
17:20:36 2016
0
19 Warnings (19
new)
1 Info (0 new)
Map Report Current
Tue May 10
17:21:32 2016
0
1 Warning (1
new)
6 Infos (6 new)
Place and Route
Report
Current
Tue May 10
17:22:42 2016
0
2 Warnings (2
new)
0
Power Report
Post-PAR Static
Timing Report
Current
Tue May 10
17:22:53 2016
0 0 5 Infos (5 new)
Bitgen Report Current
Tue May 10
17:23:13 2016
0
1 Warning (1
new)
1 Info (1 new)
Secondary Reports [-]
Report Name Status Generated
WebTalk Report Current Tue May 10 17:23:14 2016
WebTalk Log File Current Tue May 10 17:23:31 2016
Date Generated: 05/10/2016 - 17:23:36
16. FIR Filters with FPGA
Page | 16
Main Wrapper
//********************** sacred header
//**********************
module vProj_fir_25_6(
input wire CCLK, // 50 MHz/20 ns
SPIMISO, //Master In, Slave Out
BTN_EAST, // get sample
BTN_NORTH, // reset
BTN_WEST, // set preamp gain = -1
input [3:0] SW,
output wire SPIMOSI,
SPISCK,
AMPSD, AMPCS,
DACCS, DACCLR,
ADCONV,
sfCEbar,
fpgaINITb,
J4a, J4b, J4c, J4d,
output [7:0] LED
);
//********************** sacred variables
parameter ONE = 1'b1,
ZERO = 1'b0;
parameter sampl = 125; // set sample rate 250 = 20kHz 125 = 40kHz
wire clk4, Fs, Fs_clk2, CCLK50, clk40MHz; // from clock divider Fs = 20kHz Fs_clk2 =
320kHz
wire reset, start, d2a_enable;
wire [3:0] gain;
assign gain = SW;
wire get_a2d, set_preAmp;
// spi_miso,
wire spiclkP, spiMosiP, // CCLK & data to preamp
spiclkA, spiMosiA, // clk & data from a2d
spiclkD, spiMosiD;
wire [13:0] CN_Adat; //, CN_Bdat;
wire [11:0] data2Write;
17. FIR Filters with FPGA
Page | 17
wire raw_set_preAmp; // west button to single shot
// filter wrapper vars
wire [13:0] a2d_out;
wire [11:0] d2a_in_T;
wire clk_enable;
assign a2d_out = CN_Adat;
assign data2Write = d2a_in_T;
assign clk_enable = ONE;
assign LED = { ADCONV, DACCS, data2Write[11:6] };
//************************** filter vars
wire signed [15:0] filter_in; //sfix16_En15
wire signed [15:0] filter_out; //sfix36_En31 was 35 bits
wire rdy, rfd;
wire [2:0] AB; // ab switch for comparing in vs
out signal
assign AB = SW[3:1];
// test signals on S3e
assign J4a = ADCONV;
assign J4b = DACCS;
assign J4c = Fs;
assign J4d = rdy;
///************************** sacred code as above, so below
// .assign spi_miso = SPIMISO;
assign start = BTN_EAST;
assign reset = BTN_NORTH;
assign raw_set_preAmp = BTN_WEST;
assign sfCEbar = ONE; //parallel flash enable lo
assign fpgaINITb = ZERO; // flash enable hi
assign SPIMOSI = (spiMosiP && ~AMPCS) || (spiMosiD && ~DACCS);// || spiMosiA ; // data
TO SPI stuff
assign SPISCK = (spiclkP && ~AMPCS) || (spiclkD && ~DACCS) || spiclkA ; // // data
FROM SPI stuff
wire buf_clk;
BUFG bufg(.I( CCLK50 ), .O( buf_clk ) );
wire [15:0] TRIG0;
assign TRIG0 = {
SPIMISO, SPIMOSI, SPISCK, ADCONV, DACCS,
CN_Adat[13:9], // five bits of 14 from a2d
data2Write[11:7], // five bits of 12 to d2a
reset };
19. FIR Filters with FPGA
Page | 19
.reset( reset ),
.start( start ),
.fs( Fs ),
.a2d_enable( get_a2d ),
.d2a_enable( d2a_enable )
);
//**************************more sacred code begin
//******************************************
A2D a2d ( // like RDID, only different
// inputs
.spi_miso ( SPIMISO ), .clk ( clk4 ),
.reset ( reset ), .get_a2d ( get_a2d ),
//outputs
.spi_sck ( spiclkA ),
.spi_mosi ( spiMosiA ),
.ADCONV( ADCONV ),
.CN_Adat ( CN_Adat )
// .CN_Bdat ( CN_Bdat )
);
///************************** sacred code above
preAmp PA ( // like RDID, only different
.spi_miso( SPIMISO ), .clk( clk4 ),
.reset ( reset ),
.set_preAmp ( set_preAmp ),
.gain( gain ),
.spi_sck ( spiclkP ),
.spi_mosi ( spiMosiP ),
.AMPCS( AMPCS ), // preamp chip select, active low
.AMPSD( AMPSD ) // shut down not, power on, active low
);
D2A d2a(
.spi_miso( SPIMISO ), // SPI read data
.clk( clk4 ),
.reset( reset ),
.d2a_enable( d2a_enable ),
.data2Write( data2Write ), // data to write input wire [15:0]
.spi_sck( spiclkD ), // SPI clock
.spi_mosi( spiMosiD ), // SPI Data to write
.DACCS( DACCS ), // chip select, active low while sending data
.DACCLR( DACCLR) // clear d2s
20. FIR Filters with FPGA
Page | 20
);
oneShot PreShot (
.clk( clk4 ), // wire source to wire destination
.trig( raw_set_preAmp ), // reg to wire
.trigOut( set_preAmp )// wire to wire
);
// sign2unsign conJob(
// .in( sign_dat ), // 14 bits
// .data2Write( data2Write ) // 16 bits
// );
//********************************** filter wrapper
filter_wrapper wrap(
.clk( wrapClk ),
.Fs_clk2( Fs_clk2 ),
.clk_enable( clk_enable ),
.reset( reset ),
.a2d_out( a2d_out ),
.rfd( rfd ), // output rfd
.rdy( rdy ), // output rdy
.AB( AB ),
.d2a_in( d2a_in_T ) // transfers a2d_out to d2a_in_T
);
endmodule
Digital to Analog Converter (like RDID, only different
// SPI Master for the ST MicroM25P16 Serial Flash
`default_nettype none
module D2A(
input wire spi_miso, // SPI read data
input wire clk,
input wire reset, // Active high
input wire d2a_enable,
input wire [11:0] data2Write, // data to write
output reg spi_sck, // SPI clock
output wire spi_mosi, // SPI Data to write
output reg DACCS, // chip select, active low while sending gain command
output wire DACCLR // clear d2s
);
21. FIR Filters with FPGA
Page | 21
reg [2:0] cs_d2a, ns_d2a;
reg [4:0] send_count;
reg [4:0] get_count;
reg enable_get_count, enable_send_count;
reg mosi_enable;
reg assert_DACCS;
wire [31:0] data_word; // command to turn on d2a, create wave
parameter [4:0] SEND_COUNT_MAX = 5'h1F; //----------------------------------------- was 24/17
// parameter [4:0] GET_COUNT_MAX = 5'h18;
parameter [2:0] IDLE = 3'b000,
SET_CS = 3'b001,
sendInstruct = 3'b10,
//getDATA = 3'b011,
Clr_DAC_CS = 3'b100;
parameter ONE = 1'b1;
parameter ZERO = 1'b0;
parameter ZZ = 1'bz;
assign DACCLR = ONE;
assign data_word = { 8'h00, 4'b0010, 4'b1111, data2Write, 4'h0 };
// 8 + 4 + 4 + 12 + 4 = 32 bits
/////////////////////////////////////////////////////////// added eight bits of zero
always @ ( * ) begin
// Defaults
ns_d2a = IDLE;
enable_send_count = ZERO;
// enable_get_count = 1'b0;
assert_DACCS = ZERO;
mosi_enable = ZERO;
case (cs_d2a)
// Remain in idle until told to send data
IDLE: begin
if ( d2a_enable )
ns_d2a = SET_CS;
else ns_d2a = IDLE;
mosi_enable = ZERO;
//else assert_DACCS = ZERO;
end
// Assert chip select in its own state to meet chip select assertion setup time
SET_CS: begin
22. FIR Filters with FPGA
Page | 22
ns_d2a = sendInstruct;
assert_DACCS = ONE;
end
// Provide clocks to d2a_enable the instructions
sendInstruct: begin
enable_send_count = ONE;
assert_DACCS = ONE;
mosi_enable = ONE;
if ( send_count == 0 )
ns_d2a = Clr_DAC_CS;
else
ns_d2a = sendInstruct;
end
// Deassert chip select in its own state to meet chip select deassertion setup time
Clr_DAC_CS: begin
ns_d2a = IDLE;
assert_DACCS = ZERO;
enable_send_count = ZERO;
mosi_enable = ZERO;
end
endcase
end
// Need a register so the chip select don't glitch
always @(posedge clk or posedge reset) begin
if ( reset )
DACCS <= ONE;
else if ( assert_DACCS )
DACCS <= ZERO;
else
DACCS <= ONE;
end
// Current state gets next state at the positive edge of the clock
always @(posedge clk or posedge reset) begin
if ( reset )
cs_d2a <= IDLE;
else
cs_d2a <= ns_d2a;
end
// maintain a count of the spi_sck's we've provided sending
always @(posedge clk or posedge reset) begin
23. FIR Filters with FPGA
Page | 23
if ( reset )
send_count <= SEND_COUNT_MAX;
// Reset counter every time we're asked to get the ID again.
else if ( d2a_enable )
send_count <= SEND_COUNT_MAX;
else if ( enable_send_count && spi_sck)
send_count <= send_count - 1'b1;
end
// maintain a count of the spi_sck's
/*
always @(posedge clk or posedge reset) begin
if ( reset )
get_count <= GET_COUNT_MAX;
// Reset counter every time we're asked to get the ID again.
else if ( d2a_enable )
get_count <= GET_COUNT_MAX;
else if (enable_get_count && !spi_sck)
get_count <= get_count - ONE;
end
*/
// Collect read_data
/* always @(posedge clk or posedge reset) begin //*************************************
// always @(negedge clk or posedge reset) begin
if (reset)
read_data <= 24'b0;
else if (enable_get_count && !spi_sck)
read_data[get_count-1] <= spi_miso;
end
*/
// Toggle spi_sck. Need a register so the clock doesn't glitch
always @(posedge clk or posedge reset) begin
if (reset)
spi_sck <= ZERO;
else if (enable_send_count) // || enable_get_count)
spi_sck <= !spi_sck;
else if ( d2a_enable )
spi_sck <= ZERO;
else spi_sck <= ZERO;
end
// spi-mosi is just an index into the data_word vector
assign spi_mosi = data_word[send_count] && mosi_enable;
//synopsys translate_off
reg [95:0] ASCII_csd2a, ASCII_nsd2a; // Hold 12 characters (8*12=96)
24. FIR Filters with FPGA
Page | 24
always @* begin
case (cs_d2a)
IDLE: ASCII_csd2a = "IDLE";
SET_CS: ASCII_csd2a = "SET_CS";
sendInstruct: ASCII_csd2a = "sendInstruct";
// getDATA: ASCII_csd2a = "getDATA";
Clr_DAC_CS: ASCII_csd2a = "Clr_DAC_CS";
endcase
end
always @* begin
case (ns_d2a)
IDLE: ASCII_nsd2a = "IDLE";
SET_CS: ASCII_nsd2a = "SET_CS";
sendInstruct: ASCII_nsd2a = "sendInstruct";
// getDATA: ASCII_nsd2a = "getDATA";
Clr_DAC_CS: ASCII_nsd2a = "Clr_DAC_CS";
endcase
end
//synopsys translate_on
endmodule
/*
D2A your_name_here(
.spi_miso( spi_miso ), // SPI read data
.clk( clk ),
.reset( reset ),
.d2a_enable( d2a_enable ),
.data2Write( data2Write ), // data to write input wire [15:0]
.spi_sck( spi_sck ), // SPI clock
.spi_mosi( spi_mosi ), // SPI Data to write
.DACCS( DACCS ), // chip select, active low while sending gain command
.DACCLR( DACCLR) // clear d2s
);
*/
Second Wrapper
Instantiates the filters.
module Second_wrapper(
input clk, // 50 MHz
clk320, // nominal sample freq x 16
25. FIR Filters with FPGA
Page | 25
clk_enable,
reset,
output wire rdylp, rfdlp,
input wire [2:0] AB,
input wire signed [15:0] filter_in_16,
//output reg signed [15:0] filter_out_16LP,
//output reg signed [15:0] filter_out_16HP,
//output reg signed [15:0] filter_out_16BP,
output reg signed [15:0] filter_out_16
);
parameter outMSB_LP = 40; // fir41 fir40 is 37;
parameter outMSB_HP = 37; // fir41 fir40 is 37;
parameter outMSB_BP = 39;
parameter outMSB_HPlong = 41;
parameter outMSB_HPshort = 42;
wire ndL, ndH, ndB, ndHl;
assign ndL = 1'b1; //(AB == 2'b11);
assign ndH = 1'b1; //(AB == 2'b10);
assign ndB = 1'b1; //(AB == 2'b01);
assign ndHl = 1'b1; //(AB == 2'b01);
wire rdyhp, rfdhp, rfdHl;
wire rdybp, rfdbp, rdyHl;
wire signed [15:0] filter_in_16LP;
wire signed [15:0] filter_in_16HP;
wire signed [15:0] filter_in_16BP;
wire signed [15:0] filter_in_16HPlong;
assign filter_in_16LP = filter_in_16;
assign filter_in_16HP = filter_in_16;
assign filter_in_16BP = filter_in_16;
assign filter_in_16HPlong = filter_in_16;
wire signed [outMSB_LP:0] firLP;
wire signed [outMSB_HP:0] firHP;
wire signed [outMSB_BP:0] firBP;
wire signed [outMSB_HPlong:0] firHPlong;
wire signed [outMSB_HPshort:0] firHPshort;
wire signed [39:0] HP10c;
always @ ( * ) begin
case( AB )
3'b000: // IN >> OUT