--##############################################################################
|
--##############################################################################
|
--
|
--
|
-- lowpass
|
-- lowpass
|
-- generic all-pole lowpass filter
|
-- generic all-pole lowpass filter
|
--
|
--
|
-- This circuit simulates an analog ladder filter by replacing the integral
|
-- This circuit simulates an analog ladder filter by replacing the integral
|
-- relations of the LC elements by digital accumulators.
|
-- relations of the LC elements by digital accumulators.
|
--
|
--
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
--
|
--
|
-- Versions / Authors
|
-- Versions / Authors
|
-- 1.1 Francois Corthay added additional w(0) AND w(filterOrder+1)
|
-- 1.1 Francois Corthay added additional w(0) AND w(filterOrder+1)
|
-- 1.0 Romain Cheviron first implementation
|
-- 1.0 Romain Cheviron first implementation
|
--
|
--
|
-- Provided under GNU LGPL licence: <http://www.gnu.org/copyleft/lesser.html>
|
-- Provided under GNU LGPL licence: <http://www.gnu.org/copyleft/lesser.html>
|
--
|
--
|
-- by the electronics group of "HES-SO//Valais Wallis", in Switzerland:
|
-- by the electronics group of "HES-SO//Valais Wallis", in Switzerland:
|
-- <http://isi.hevs.ch/switzerland/robust-electronics.html>.
|
-- <http://isi.hevs.ch/switzerland/robust-electronics.html>.
|
--
|
--
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
--
|
--
|
-- Usage
|
-- Usage
|
-- Set the input signal bit number with the generic "inputBitNb".
|
-- Set the input signal bit number with the generic "inputBitNb".
|
--
|
--
|
-- Set the output signal bit number with the generic "outputBitNb". This
|
-- Set the output signal bit number with the generic "outputBitNb". This
|
-- value must be greater or equal than "inputBitNb". The additional bits
|
-- value must be greater or equal than "inputBitNb". The additional bits
|
-- are added as LSBs. They allow to increas the resolution as the bandwidth
|
-- are added as LSBs. They allow to increas the resolution as the bandwidth
|
-- is reduced.
|
-- is reduced.
|
--
|
--
|
-- Define the cutoff frequency with the generic "shiftBitNb". Every
|
-- Define the cutoff frequency with the generic "shiftBitNb". Every
|
-- increment in this value shifts the cutoff frequency down by an octave
|
-- increment in this value shifts the cutoff frequency down by an octave
|
-- (a factor of 2).
|
-- (a factor of 2).
|
--
|
--
|
-- In order to define the filter function, the first lines of the
|
-- In order to define the filter function, the first lines of the
|
-- architecture have to be edited:
|
-- architecture have to be edited:
|
-- constant "filterOrder" obviously gives the filter order.
|
-- constant "filterOrder" obviously gives the filter order.
|
-- constant "coefficientBitNb" obviously gives the number of bits of
|
-- constant "coefficientBitNb" obviously gives the number of bits of
|
-- the coefficients.
|
-- the coefficients.
|
-- constant "coefficient" give the time constants as unsigned numbers
|
-- constant "coefficient" give the time constants as unsigned numbers
|
-- ranging from 1 to (2**coefficientBitNb)-1. The relative values
|
-- ranging from 1 to (2**coefficientBitNb)-1. The relative values
|
-- of the coefficients give the shape of the transfer function.
|
-- of the coefficients give the shape of the transfer function.
|
-- The cutoff frequency is furthermore given by the "shiftBitNb"
|
-- The cutoff frequency is furthermore given by the "shiftBitNb"
|
-- generic.
|
-- generic.
|
-- constant "additionalInternalWBitNb" gives the number of additional
|
-- constant "additionalInternalWBitNb" gives the number of additional
|
-- bits assigned to the internal signals corresponding to the state
|
-- bits assigned to the internal signals corresponding to the state
|
-- variables of the analog filter. They are used to avoid overflows
|
-- variables of the analog filter. They are used to avoid overflows
|
-- on these signals.
|
-- on these signals.
|
-- The values for "shiftBitNb" and "constant additionalInternalWBitNb" can
|
-- The values for "shiftBitNb" and "constant additionalInternalWBitNb" can
|
-- be dertermined analytically, but a frequency sweep simulation allows to
|
-- be dertermined analytically, but a frequency sweep simulation allows to
|
-- set them iteratively.
|
-- set them iteratively.
|
--
|
--
|
-- The input samples are read from the signal "filterIn" at the rising edge
|
-- The input samples are read from the signal "filterIn" at the rising edge
|
-- of "clock" when "en" is '1'.
|
-- of "clock" when "en" is '1'.
|
--
|
--
|
-- With this, a new output sample is calculated and provided on
|
-- With this, a new output sample is calculated and provided on
|
-- "filterOut". The output changes at the end of the iterative calculation
|
-- "filterOut". The output changes at the end of the iterative calculation
|
-- of the multiplication, which is roughly n clock periods after "en"
|
-- of the multiplication, which is roughly n clock periods after "en"
|
-- was '1'. The number of clock periods, n, is equal to the number of bits
|
-- was '1'. The number of clock periods, n, is equal to the number of bits
|
-- of the coefficients. The output sample remains stable until the next
|
-- of the coefficients. The output sample remains stable until the next
|
-- sample has been calculated.
|
-- sample has been calculated.
|
--
|
--
|
-- The "reset" signal is active high.
|
-- The "reset" signal is active high.
|
--
|
--
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
--
|
--
|
-- Synthesis results
|
-- Synthesis results
|
--
|
--
|
-- A 3rd order filter with 16 bit input, 16 bit output and 4 bit shift
|
-- A 3rd order filter with 16 bit input, 16 bit output and 4 bit shift
|
-- gives the following synthesis result on a Xilinx Spartan3-1000:
|
-- gives the following synthesis result on a Xilinx Spartan3-1000:
|
-- Number of Slice Flip Flops: 162 out of 15,360 1%
|
-- Number of Slice Flip Flops: 162 out of 15,360 1%
|
-- Number of 4 input LUTs: 282 out of 15,360 1%
|
-- Number of 4 input LUTs: 282 out of 15,360 1%
|
-- Average Fanout of Non-Clock Nets: 2.73
|
-- Average Fanout of Non-Clock Nets: 2.73
|
--
|
--
|
-- A 6th order filter with 16 bit input, 16 bit output and 4 bit shift
|
-- A 6th order filter with 16 bit input, 16 bit output and 4 bit shift
|
-- gives the following synthesis result on a Xilinx Spartan3-1000:
|
-- gives the following synthesis result on a Xilinx Spartan3-1000:
|
-- Number of Slice Flip Flops: 333 out of 15,360 2%
|
-- Number of Slice Flip Flops: 333 out of 15,360 2%
|
-- Number of 4 input LUTs: 604 out of 15,360 3%
|
-- Number of 4 input LUTs: 604 out of 15,360 3%
|
-- Average Fanout of Non-Clock Nets: 2.81
|
-- Average Fanout of Non-Clock Nets: 2.81
|
--
|
--
|
--##############################################################################
|
--##############################################################################
|
|
|
LIBRARY ieee;
|
LIBRARY ieee;
|
USE ieee.std_logic_1164.all;
|
USE ieee.std_logic_1164.all;
|
USE ieee.numeric_std.all;
|
USE ieee.numeric_std.all;
|
|
|
ENTITY lowpass IS
|
ENTITY lowpass IS
|
GENERIC(
|
GENERIC(
|
inputBitNb : positive := 16;
|
inputBitNb : positive := 16;
|
outputBitNb : positive := 16;
|
outputBitNb : positive := 16;
|
shiftBitNb : positive := 4
|
shiftBitNb : positive := 4
|
);
|
);
|
PORT(
|
PORT(
|
clock : IN std_ulogic;
|
clock : IN std_ulogic;
|
reset : IN std_ulogic;
|
reset : IN std_ulogic;
|
en : IN std_ulogic;
|
en : IN std_ulogic;
|
filterIn : IN signed (inputBitNb-1 DOWNTO 0);
|
filterIn : IN signed (inputBitNb-1 DOWNTO 0);
|
filterOut : OUT signed (outputBitNb-1 DOWNTO 0)
|
filterOut : OUT signed (outputBitNb-1 DOWNTO 0)
|
);
|
);
|
END butterworth3 ;
|
END lowpass ;
|
|
|
--==============================================================================
|
--==============================================================================
|
|
|
ARCHITECTURE RTL OF lowpass IS
|
ARCHITECTURE RTL OF lowpass IS
|
|
|
-- 3rd order Butterworth
|
-- 3rd order Butterworth
|
--
|
--
|
-- constant filterOrder : natural := 3;
|
-- constant filterOrder : natural := 3;
|
-- constant coefficientBitNb : natural := 8;
|
-- constant coefficientBitNb : natural := 8;
|
-- type unsigned_vector_c is array(1 to filterOrder)
|
-- type unsigned_vector_c is array(1 to filterOrder)
|
-- of unsigned(coefficientBitNb-1 downto 0);
|
-- of unsigned(coefficientBitNb-1 downto 0);
|
-- constant coefficient : unsigned_vector_c := (
|
-- constant coefficient : unsigned_vector_c := (
|
-- to_unsigned(2**7, coefficientBitNb),
|
-- to_unsigned(2**7, coefficientBitNb),
|
-- to_unsigned(2**6, coefficientBitNb),
|
-- to_unsigned(2**6, coefficientBitNb),
|
-- to_unsigned(2**7, coefficientBitNb)
|
-- to_unsigned(2**7, coefficientBitNb)
|
-- );
|
-- );
|
-- constant additionalInternalWBitNb: positive := 2;
|
-- constant additionalInternalWBitNb: positive := 2;
|
|
|
-- 6th order Bessel
|
-- 6th order Bessel
|
--
|
--
|
constant filterOrder : natural := 6;
|
constant filterOrder : natural := 6;
|
constant coefficientBitNb : natural := 8;
|
constant coefficientBitNb : natural := 8;
|
type unsigned_vector_c is array(1 to filterOrder)
|
type unsigned_vector_c is array(1 to filterOrder)
|
of unsigned(coefficientBitNb-1 downto 0);
|
of unsigned(coefficientBitNb-1 downto 0);
|
constant coefficient : unsigned_vector_c := (
|
constant coefficient : unsigned_vector_c := (
|
to_unsigned(215, coefficientBitNb),
|
to_unsigned(215, coefficientBitNb),
|
to_unsigned( 88, coefficientBitNb),
|
to_unsigned( 88, coefficientBitNb),
|
to_unsigned( 81, coefficientBitNb),
|
to_unsigned( 81, coefficientBitNb),
|
to_unsigned( 61, coefficientBitNb),
|
to_unsigned( 61, coefficientBitNb),
|
to_unsigned( 38, coefficientBitNb),
|
to_unsigned( 38, coefficientBitNb),
|
to_unsigned( 13, coefficientBitNb)
|
to_unsigned( 13, coefficientBitNb)
|
);
|
);
|
constant additionalInternalWBitNb: positive := 4;
|
constant additionalInternalWBitNb: positive := 4;
|
|
|
constant internalWBitNb: positive := filterOut'length + additionalInternalWBitNb;
|
constant internalWBitNb: positive := filterOut'length + additionalInternalWBitNb;
|
signal inputSignalScaled : signed(internalWBitNb-1 downto 0);
|
signal inputSignalScaled : signed(internalWBitNb-1 downto 0);
|
|
|
constant internalAccumulatorBitNb : positive := internalWBitNb + shiftBitNb;
|
constant internalAccumulatorBitNb : positive := internalWBitNb + shiftBitNb;
|
type signed_vector_accumulator is array(1 to filterOrder)
|
type signed_vector_accumulator is array(1 to filterOrder)
|
of signed(internalAccumulatorBitNb-1 downto 0);
|
of signed(internalAccumulatorBitNb-1 downto 0);
|
type signed_vector_w is array(0 to filterOrder+1)
|
type signed_vector_w is array(0 to filterOrder+1)
|
of signed(internalWBitNb-1 downto 0);
|
of signed(internalWBitNb-1 downto 0);
|
signal accumulator : signed_vector_accumulator;
|
signal accumulator : signed_vector_accumulator;
|
signal w : signed_vector_w;
|
signal w : signed_vector_w;
|
|
|
type unsigned_vector_coeffShiftReg is array(1 to filterOrder)
|
type unsigned_vector_coeffShiftReg is array(1 to filterOrder)
|
of unsigned(coefficientBitNb-1 downto 0);
|
of unsigned(coefficientBitNb-1 downto 0);
|
signal coefficientShiftRegister: unsigned_vector_coeffShiftReg;
|
signal coefficientShiftRegister: unsigned_vector_coeffShiftReg;
|
signal multiplicandBit: std_ulogic_vector(1 to filterOrder);
|
signal multiplicandBit: std_ulogic_vector(1 to filterOrder);
|
type signed_vector_multAcc is array(1 to filterOrder)
|
type signed_vector_multAcc is array(1 to filterOrder)
|
of signed(internalAccumulatorBitNb+coefficientBitNb-1 downto 0);
|
of signed(internalAccumulatorBitNb+coefficientBitNb-1 downto 0);
|
signal multiplicationAccumulator: signed_vector_multAcc;
|
signal multiplicationAccumulator: signed_vector_multAcc;
|
|
|
signal cycleCounterShiftReg: unsigned(coefficientBitNb downto 0);
|
signal cycleCounterShiftReg: unsigned(coefficientBitNb downto 0);
|
signal endOfCycle: std_ulogic;
|
signal endOfCycle: std_ulogic;
|
signal calculating: std_ulogic;
|
signal calculating: std_ulogic;
|
|
|
signal wDebug : signed_vector_w;
|
signal wDebug : signed_vector_w;
|
|
|
BEGIN
|
BEGIN
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- Scale input signal to internal state variables size
|
-- Scale input signal to internal state variables size
|
inputSignalScaled <= SHIFT_LEFT(
|
inputSignalScaled <= SHIFT_LEFT(
|
RESIZE(filterIn, inputSignalScaled'length),
|
RESIZE(filterIn, inputSignalScaled'length),
|
filterOut'length - filterIn'length
|
filterOut'length - filterIn'length
|
);
|
);
|
|
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- Accumulator chain
|
-- Accumulator chain
|
process(reset, clock)
|
process(reset, clock)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
accumulator <= (others => (others => '0'));
|
accumulator <= (others => (others => '0'));
|
elsif rising_edge(clock) then
|
elsif rising_edge(clock) then
|
if en = '1' then
|
if en = '1' then
|
for index in 1 to filterOrder loop
|
for index in 1 to filterOrder loop
|
accumulator(index) <= accumulator(index) + (
|
accumulator(index) <= accumulator(index) + (
|
RESIZE(w(index-1), w(index)'length+1) -
|
RESIZE(w(index-1), w(index)'length+1) -
|
RESIZE(w(index+1), w(index)'length+1)
|
RESIZE(w(index+1), w(index)'length+1)
|
);
|
);
|
end loop;
|
end loop;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- Multiplication sequence
|
-- Multiplication sequence
|
|
|
-- Coefficient shift
|
-- Coefficient shift
|
process(reset, clock)
|
process(reset, clock)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
coefficientShiftregister <= (others => (others => '0'));
|
coefficientShiftregister <= (others => (others => '0'));
|
elsif rising_edge(clock) then
|
elsif rising_edge(clock) then
|
for index in 1 to filterOrder loop
|
for index in 1 to filterOrder loop
|
if en = '1' then
|
if en = '1' then
|
coefficientShiftregister(index) <= coefficient(index);
|
coefficientShiftregister(index) <= coefficient(index);
|
else
|
else
|
coefficientShiftregister(index) <=
|
coefficientShiftregister(index) <=
|
shift_right(coefficientShiftregister(index), 1);
|
shift_right(coefficientShiftregister(index), 1);
|
end if;
|
end if;
|
end loop;
|
end loop;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
process(coefficientShiftregister)
|
process(coefficientShiftregister)
|
begin
|
begin
|
for index in 1 to filterOrder loop
|
for index in 1 to filterOrder loop
|
multiplicandBit(index) <= coefficientShiftregister(index)(0);
|
multiplicandBit(index) <= coefficientShiftregister(index)(0);
|
end loop;
|
end loop;
|
end process;
|
end process;
|
|
|
-- Multiplication accumulator
|
-- Multiplication accumulator
|
process(reset, clock)
|
process(reset, clock)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
multiplicationAccumulator <= (others => (others => '0'));
|
multiplicationAccumulator <= (others => (others => '0'));
|
elsif rising_edge(clock) then
|
elsif rising_edge(clock) then
|
for index in 1 to filterOrder loop
|
for index in 1 to filterOrder loop
|
if en = '1' then
|
if en = '1' then
|
multiplicationAccumulator(index) <= (others => '0');
|
multiplicationAccumulator(index) <= (others => '0');
|
elsif calculating = '1' then
|
elsif calculating = '1' then
|
if multiplicandBit(index) = '0' then
|
if multiplicandBit(index) = '0' then
|
multiplicationAccumulator(index) <=
|
multiplicationAccumulator(index) <=
|
shift_right(multiplicationAccumulator(index), 1);
|
shift_right(multiplicationAccumulator(index), 1);
|
else
|
else
|
multiplicationAccumulator(index) <=
|
multiplicationAccumulator(index) <=
|
shift_right(multiplicationAccumulator(index), 1) +
|
shift_right(multiplicationAccumulator(index), 1) +
|
shift_left(
|
shift_left(
|
resize(accumulator(index), multiplicationAccumulator(index)'length),
|
resize(accumulator(index), multiplicationAccumulator(index)'length),
|
coefficientBitNb
|
coefficientBitNb
|
);
|
);
|
end if;
|
end if;
|
end if;
|
end if;
|
end loop;
|
end loop;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- Analog filter state variables
|
-- Analog filter state variables
|
process(multiplicationAccumulator, w, inputSignalScaled)
|
process(multiplicationAccumulator, w, inputSignalScaled)
|
begin
|
begin
|
for index in 1 to filterOrder loop
|
for index in 1 to filterOrder loop
|
w(index) <= RESIZE(
|
w(index) <= RESIZE(
|
SHIFT_RIGHT(
|
SHIFT_RIGHT(
|
multiplicationAccumulator(index),
|
multiplicationAccumulator(index),
|
coefficientBitNb + shiftBitNb
|
coefficientBitNb + shiftBitNb
|
),
|
),
|
w(index)'length
|
w(index)'length
|
);
|
);
|
end loop;
|
end loop;
|
-- w(0) combines input and w(1) for first accumulator
|
-- w(0) combines input and w(1) for first accumulator
|
w(0) <= inputSignalScaled - w(1);
|
w(0) <= inputSignalScaled - w(1);
|
-- w(filterOrder+1) is a copy of w(filterOrder) for last accumulator
|
-- w(filterOrder+1) is a copy of w(filterOrder) for last accumulator
|
w(filterOrder+1) <= w(filterOrder);
|
w(filterOrder+1) <= w(filterOrder);
|
end process;
|
end process;
|
|
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- Scale last state variables to output size and latch
|
-- Scale last state variables to output size and latch
|
process(reset, clock)
|
process(reset, clock)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
filterOut <= (others => '0');
|
filterOut <= (others => '0');
|
elsif rising_edge(clock) then
|
elsif rising_edge(clock) then
|
if calculating = '0' then
|
if calculating = '0' then
|
filterOut <= RESIZE(w(w'high), filterOut'length);
|
filterOut <= RESIZE(w(w'high), filterOut'length);
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- Multiplication cycle counter
|
-- Multiplication cycle counter
|
process(reset, clock)
|
process(reset, clock)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
cycleCounterShiftReg <= (others => '0');
|
cycleCounterShiftReg <= (others => '0');
|
elsif rising_edge(clock) then
|
elsif rising_edge(clock) then
|
cycleCounterShiftReg <= shift_right(cycleCounterShiftReg, 1);
|
cycleCounterShiftReg <= shift_right(cycleCounterShiftReg, 1);
|
cycleCounterShiftReg(cycleCounterShiftReg'high) <= en;
|
cycleCounterShiftReg(cycleCounterShiftReg'high) <= en;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
endOfCycle <= cycleCounterShiftReg(0);
|
endOfCycle <= cycleCounterShiftReg(0);
|
calculating <= '1' when cycleCounterShiftReg /= 0
|
calculating <= '1' when cycleCounterShiftReg /= 0
|
else '0';
|
else '0';
|
|
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- Debug information
|
-- Debug information
|
process(reset, clock)
|
process(reset, clock)
|
begin
|
begin
|
if reset = '1' then
|
if reset = '1' then
|
wDebug <= (others => (others => '0'));
|
wDebug <= (others => (others => '0'));
|
elsif rising_edge(clock) then
|
elsif rising_edge(clock) then
|
for index in 1 to filterOrder loop
|
for index in 1 to filterOrder loop
|
if calculating = '0' then
|
if calculating = '0' then
|
wDebug <= w;
|
wDebug <= w;
|
end if;
|
end if;
|
end loop;
|
end loop;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
END ARCHITECTURE RTL;
|
END ARCHITECTURE RTL;
|
|
|