Победил появление сигнала на частотах F +- 156,25 кГц на краях полосы пропускания.
Сделал каскадное соединение фильтров с разными характеристиками.
Пока не разобрался с CIC фильтрами, ставлю вместо них сумматоры-аккумуляторы со
схожими с CIC АЧХ. При моделировании CIC фильтры показывают лучший результат по
сравнению с сумматорами-аккумуляторами, а на реальном сигнале уровень шума выше.
Что-то еще не понимаю.
Сначала после ПЗУ понижаю частоту в 32 раза до 625 кГц, затем ставлю КИХ фильтр
21-го порядка с частотой минимума 140 кГц(т.е. вырезаю частоты преобразования
кратные 156,25 кГц).
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity lpf32iq is
port(
i_in : in std_logic_vector(7 downto 0);
q_in : in std_logic_vector(7 downto 0);
clk, nres : in std_logic;
term : out std_logic;
i_out : out std_logic_vector(12 downto 0);
q_out : out std_logic_vector(12 downto 0)
);
end;
architecture behavior of lpf32iq is
signal siReg: std_logic_vector(12 downto 0);
signal sqReg: std_logic_vector(12 downto 0);
signal scnt : std_logic_vector(4 downto 0);
signal sterm : std_logic;
begin
term <= sterm;
mk_sreg:
process(nres,clk,sterm,i_in,q_in)
begin
if nres = '0' then
siReg <= "0000000000000" after 1 ns;
sqReg <= "0000000000000" after 1 ns;
elsif (clk = '1' and clk'event) then
if sterm = '1' then
siReg <= i_in(7) & i_in(7) & i_in(7) & i_in(7) & i_in(7) & i_in after 1 ns;
sqReg <= q_in(7) & q_in(7) & q_in(7) & q_in(7) & q_in(7) & q_in after 1 ns;
else
siReg <= siReg + (i_in(7) & i_in(7) & i_in(7) & i_in(7) & i_in(7) & i_in) after 1 ns;
sqReg <= sqReg + (q_in(7) & q_in(7) & q_in(7) & q_in(7) & q_in(7) & q_in) after 1 ns;
end if;
end if;
end process;
mk_iq_out:
process(nres,clk,sterm,siReg,sqReg)
begin
if nres = '0' then
i_out <= "0000000000000" after 1 ns;
q_out <= "0000000000000" after 1 ns;
elsif (clk = '1' and clk'event) then
if sterm = '1' then
i_out <= siReg after 1 ns;
q_out <= sqReg after 1 ns;
else
end if;
end if;
end process;
mk_scnt:
process(nres,clk)
begin
if nres = '0' then
scnt <= "00000" after 1 ns;
sterm <= '0' after 1 ns;
elsif (clk = '1' and clk'event) then
scnt <= scnt + "00001" after 1 ns;
if scnt = "11111" then
sterm <= '1' after 1 ns;
else
sterm <= '0' after 1 ns;
end if;
end if;
end process;
end;
--/*
--
--FIR filter designed with
--http://t-filter.appspot.com
--
--sampling frequency: 625000 Hz
--
--fixed point precision: 16 bits
--
--* 0 Hz - 19000 Hz
-- gain = 1
-- desired ripple = 1 dB
-- actual ripple = n/a
--
--* 140000 Hz - 312500 Hz
-- gain = 0
-- desired attenuation = -100 dB
-- actual attenuation = n/a
--
--*/
--
--#define FILTER_TAP_NUM 21
--
--static int filter_taps[FILTER_TAP_NUM] = {
-- -11, xFFF5
-- -56, xFFC8
-- -139, xFF75
-- -180, xFF4C
-- 58, x003A
-- 933, x03A5
-- 2741, x0AB5
-- 5435, x153B
-- 8459, x210B
-- 10881, x2A81
-- 11810, x2E22
-- 10881,
-- 8459,
-- 5435,
-- 2741,
-- 933,
-- 58,
-- -180,
-- -139,
-- -56,
-- -11
--};
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity fir21_625kHz_2_filtr is
port(
clk : in std_logic; --- clock 20 MHz
nres : in std_logic; --- active low
idata : in std_logic_vector(12 downto 0);
start : in std_logic; --- active high 625 kHz
odata : out std_logic_vector(31 downto 0)
);
end;
architecture behavior of fir21_625kHz_2_filtr is
signal s0reg: std_logic_vector(15 downto 0);
signal s1reg: std_logic_vector(15 downto 0);
signal s2reg: std_logic_vector(15 downto 0);
signal s3reg: std_logic_vector(15 downto 0);
signal s4reg: std_logic_vector(15 downto 0);
signal s5reg: std_logic_vector(15 downto 0);
signal s6reg: std_logic_vector(15 downto 0);
signal s7reg: std_logic_vector(15 downto 0);
signal s8reg: std_logic_vector(15 downto 0);
signal s9reg: std_logic_vector(15 downto 0);
signal s10reg: std_logic_vector(15 downto 0);
signal s11reg: std_logic_vector(15 downto 0);
signal s12reg: std_logic_vector(15 downto 0);
signal s13reg: std_logic_vector(15 downto 0);
signal s14reg: std_logic_vector(15 downto 0);
signal s15reg: std_logic_vector(15 downto 0);
signal s16reg: std_logic_vector(15 downto 0);
signal s17reg: std_logic_vector(15 downto 0);
signal s18reg: std_logic_vector(15 downto 0);
signal s19reg: std_logic_vector(15 downto 0);
signal s20reg: std_logic_vector(15 downto 0);
signal s11cnt: std_logic_vector(3 downto 0);
signal s0en: std_logic;
signal s1en: std_logic;
signal s2en: std_logic;
signal ostart: std_logic;
signal sstart: std_logic_vector(1 downto 0);
constant cK0: std_logic_vector(15 downto 0) := x"FFF5";
constant cK1: std_logic_vector(15 downto 0) := x"FFC8";
constant cK2: std_logic_vector(15 downto 0) := x"FF75";
constant cK3: std_logic_vector(15 downto 0) := x"FF4C";
constant cK4: std_logic_vector(15 downto 0) := x"003A";
constant cK5: std_logic_vector(15 downto 0) := x"03A5";
constant cK6: std_logic_vector(15 downto 0) := x"0AB5";
constant cK7: std_logic_vector(15 downto 0) := x"153B";
constant cK8: std_logic_vector(15 downto 0) := x"210B";
constant cK9: std_logic_vector(15 downto 0) := x"2A81";
constant cK10: std_logic_vector(15 downto 0) := x"2E22";
signal sopa: std_logic_vector(15 downto 0);
signal sopb: std_logic_vector(15 downto 0);
signal smr: std_logic_vector(31 downto 0);
signal sdmr: std_logic_vector(31 downto 0);
signal sacc: std_logic_vector(31 downto 0);
begin
-- SIGN MULT:
U1: entity work.firmult
port map (
opa => sopa,
opb => sopb,
clk => clk,
ce => s0en,
nres => nres,
y => smr
);
mk_sopa_sopb:
process (s11cnt,s0reg,s1reg,s2reg,s3reg,s4reg,s5reg,s6reg,s7reg,s8reg,s9reg,s10reg,s11reg,s12reg,
s13reg,s14reg,s15reg,s16reg,s17reg,s18reg,s19reg,s20reg)
begin
case s11cnt is
when "0001" => sopa <= s0reg + s20reg; sopb <= cK0;
when "0010" => sopa <= s1reg + s19reg; sopb <= cK1;
when "0011" => sopa <= s2reg + s18reg; sopb <= cK2;
when "0100" => sopa <= s3reg + s17reg; sopb <= cK3;
when "0101" => sopa <= s4reg + s16reg; sopb <= cK4;
when "0110" => sopa <= s5reg + s15reg; sopb <= cK5;
when "0111" => sopa <= s6reg + s14reg; sopb <= cK6;
when "1000" => sopa <= s7reg + s13reg; sopb <= cK7;
when "1001" => sopa <= s8reg + s12reg; sopb <= cK8;
when "1010" => sopa <= s9reg + s11reg; sopb <= cK9;
when "1011" => sopa <= s10reg; sopb <= cK10;
when others => sopa <= x"0000"; sopb <= x"0000";
end case;
end process;
mk_s8cnt:
process(nres,clk,start)
begin
if nres = '0' then
s11cnt <= "1011" after 1 ns;
s0en <= '0' after 1 ns;
s1en <= '0' after 1 ns;
s2en <= '0' after 1 ns;
sstart <= "00" after 1 ns;
ostart <= '0' after 1 ns;
elsif (clk = '1' and clk'event) then
s1en <= s0en after 1 ns;
s2en <= s1en after 1 ns;
sstart <= sstart(0) & start after 1 ns;
ostart <= sstart(1) and not sstart(0) after 1 ns;
if ostart = '1' then
s11cnt <= "0000" after 1 ns;
s0en <= '0' after 1 ns;
elsif s11cnt < "1011" then
s11cnt <= s11cnt + "0001" after 1 ns;
s0en <= '1' after 1 ns;
else s0en <= '0' after 1 ns;
end if;
end if;
end process;
mk_sregs:
process(nres,clk,ostart,idata)
begin
if nres = '0' then
s0reg <= x"0000" after 1 ns;
s1reg <= x"0000" after 1 ns;
s2reg <= x"0000" after 1 ns;
s3reg <= x"0000" after 1 ns;
s4reg <= x"0000" after 1 ns;
s5reg <= x"0000" after 1 ns;
s6reg <= x"0000" after 1 ns;
s7reg <= x"0000" after 1 ns;
s8reg <= x"0000" after 1 ns;
s9reg <= x"0000" after 1 ns;
s10reg <= x"0000" after 1 ns;
s11reg <= x"0000" after 1 ns;
s12reg <= x"0000" after 1 ns;
s13reg <= x"0000" after 1 ns;
s14reg <= x"0000" after 1 ns;
s15reg <= x"0000" after 1 ns;
s16reg <= x"0000" after 1 ns;
s17reg <= x"0000" after 1 ns;
s18reg <= x"0000" after 1 ns;
s19reg <= x"0000" after 1 ns;
s20reg <= x"0000" after 1 ns;
elsif (clk = '1' and clk'event) then
if ostart = '1' then
s0reg <= (idata(12) & idata(12) & idata(12) & idata) after 1 ns;
s1reg <= s0reg after 1 ns;
s2reg <= s1reg after 1 ns;
s3reg <= s2reg after 1 ns;
s4reg <= s3reg after 1 ns;
s5reg <= s4reg after 1 ns;
s6reg <= s5reg after 1 ns;
s7reg <= s6reg after 1 ns;
s8reg <= s7reg after 1 ns;
s9reg <= s8reg after 1 ns;
s10reg <= s9reg after 1 ns;
s11reg <= s10reg after 1 ns;
s12reg <= s11reg after 1 ns;
s13reg <= s12reg after 1 ns;
s14reg <= s13reg after 1 ns;
s15reg <= s14reg after 1 ns;
s16reg <= s15reg after 1 ns;
s17reg <= s16reg after 1 ns;
s18reg <= s17reg after 1 ns;
s19reg <= s18reg after 1 ns;
s20reg <= s19reg after 1 ns;
end if;
end if;
end process;
mk_sacc:
process(nres,clk,s1en,s2en,smr,ostart)
begin
if nres = '0' then
sacc <= x"00000000" after 1 ns;
sdmr <= x"00000000" after 1 ns;
odata <= x"00000000" after 1 ns;
elsif (clk = '1' and clk'event) then
if ostart = '1' then
odata <= sacc after 1 ns;
end if;
if ostart = '1' then
sdmr <= x"00000000" after 1 ns;
elsif s1en = '1' then
sdmr <= smr after 1 ns;
end if;
if ostart = '1' then
sacc <= x"00000000" after 1 ns;
elsif s2en = '1' then
sacc <= sacc + sdmr after 1 ns;
else
end if;
end if;
end process;
end;
Затем еще понижаю частоту в 4 раза до частоты 156,25 кГц и после этого ставлю
КИХ фильтр 89-го порядка с частотой минимума 27 кГц. Затем понижаю частоту в 4 раза
и подаю на выход.
КИХ фильтры сделал по структуре, описаной в книге Л.РАБИНЕР, Б.ГОУЛД "ТЕОРИЯ И
ПРИМЕНЕНИЕ ЦИФРОВОЙ ОБРАБОТКИ СИГНАЛОВ" издательство МИР Москва 1978.
Иногда принимаю сигналы любительских радиостанций на диапазонах 3,65 МГц, 7,1 МГц
и 14,15 МГц (20000 кГц - 14150 кГц = 5850 кГц). Но сигналы слабые, явно не хватает
радиолюбительской антенны. На входе усилителя ВЧ поставил низкодобротный преселектор
в виде дросселя на 2 мкГ и переменного конденсатора. При резонансной настройке
сигналы становятся чуть громче. Хочу попробовать поставить хороший высокодобротный
двухконтурный преселектор. Но это как-нибудь потом.
Еще принял неизвестный сигнал на частоте 4880 кГц(20000 кГц - 15120 кГц = 4880 кГц).
Подозреваю что это DRM. Но настроить HDSDR не смог на декодирование этого сигнала.
Не нашел информации как это сделать.
Николай.