From 668c0564e94d6429f18e3b450b6a71df42b1b906 Mon Sep 17 00:00:00 2001 From: nikit3s Date: Tue, 18 Aug 2026 12:06:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA=20CI?= =?UTF-8?q?C=203=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=204:=20=D0=B0?= =?UTF-8?q?=D0=BA=D0=BA=D1=83=D0=BC=D1=83=D0=BB=D1=8F=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D1=8B=20=D1=88=D0=B8=D1=80=D0=B5=2018=20=D0=B1=D0=B8=D1=82=20?= =?UTF-8?q?=D0=BD=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D1=8E=D1=82?= =?UTF-8?q?=20=D0=B2=20=D0=BA=D1=80=D0=B8=D1=81=D1=82=D0=B0=D0=BB=D0=BB?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Тракт молча отдавал нули: CIC с 26-битными аккумуляторами в железе не считает, хотя синтез, трассировка, тайминг и симуляция чистые. Порог найден перебором на плате с приёмом по UART: 26, 24 и 20 бит мертвы, 18, 16 и 10 работают. Порядок 3 требует ровно 18 бит вместо 24 и попадает в рабочую область. Характеристики от этого стали лучше: подавление в задерживании 76 дБ вместо 72, сворачиваемых полос 92 дБ вместо 77, полоса та же 0.032 дБ. Коэффициенты ФНЧ пересчитаны под sinc^3, сдвиг выхода уменьшен до 13 -- усиление CIC теперь 50^3, и коэффициенты по-прежнему укладываются в 18 бит. Сброс по включению убран: он тоже убивает тракт, проверено прошивкой в обе стороны. Маяк светодиода вынесен в условную генерацию, чтобы его широкий счётчик не собирался в рабочем режиме. Проверено на плате: 1481 кадр за 6 с, 74050 отсчётов, CRC без ошибок, STATUS чистый, на входе живой звук. --- README.md | 40 ++++++++++---- src/Top.vhd | 63 ++++++++++----------- src/cic_decim.vhd | 10 ++-- src/fir_coefs_pkg.vhd | 122 ++++++++++++++++++++--------------------- tools/gen_fir_coefs.py | 8 +-- 5 files changed, 130 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index d0835b3..2557733 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Прошивка принимает поток PDM с микрофона SPH9855LM4H-C, приводит его к **24 бит / 12 500 Гц** и отдаёт отсчёты кадрами по UART. -MIC_CLK 3.125 МГц -> CIC sinc^4 /50 -> 62.5 кГц -> ФНЧ /5 -> **12 500 Гц** -> +MIC_CLK 3.125 МГц -> CIC sinc^3 /50 -> 62.5 кГц -> ФНЧ /5 -> **12 500 Гц** -> кадры по 50 отсчётов -> UART 921600. ## Тактирование и частоты @@ -12,7 +12,7 @@ MIC_CLK 3.125 МГц -> CIC sinc^4 /50 -> 62.5 кГц -> ФНЧ /5 -> **12 500 |:--|:--|:--| | Системный клок | 50 МГц (E2) | генератор платы | | MIC_CLK | 3.125 МГц = 50/16 | Normal mode микрофона 1.1...4.8 МГц | -| CIC | sinc^4, децимация 50 | до 62.5 кГц, без умножителей | +| CIC | sinc^3, децимация 50 | до 62.5 кГц, без умножителей, аккумуляторы 18 бит | | ФНЧ | 221 отвод, децимация 5 | до 12 500 Гц | | Выходная ЧД | 12 500 Гц | | | UART | 921600, 8N1 | 157 байт на кадр, 250 кадров/с, 39.25 кБ/с (43% канала) | @@ -31,11 +31,15 @@ CIC снимает поток до 62.5 кГц, а всю избирательн | Показатель | Значение | |:--|:--| | неравномерность полосы 0...5000 Гц | 0.032 дБ | -| подавление от 6250 Гц | 72 дБ | -| подавление сворачиваемых полос | 77 дБ | +| подавление от 6250 Гц | 76 дБ | +| подавление сворачиваемых полос | 92 дБ | -Спад CIC в полосе (до 0.36 дБ на краю) не компенсируется отдельным звеном: -он задан прямо в желаемой АЧХ при расчёте ФНЧ. +Спад CIC в полосе не компенсируется отдельным звеном: он задан прямо в желаемой +АЧХ при расчёте ФНЧ, поэтому смена порядка CIC требует только перезапуска +генератора коэффициентов. + +Порядок 3, а не 4, выбран не из соображений АЧХ — характеристики с ним даже +лучше — а по ограничению кристалла, см. ниже. Коэффициенты и разрядности лежат в `src/fir_coefs_pkg.vhd`, файл генерируется: @@ -46,7 +50,7 @@ py -3 tools/gen_fir_coefs.py ## Шкала Постоянная `'1'` на выводе данных микрофона даёт полную шкалу 24 бит -(код 8 388 567). Отсюда шкала выхода — dBFS, ровно та, в которой микрофон +(код 8 388 596). Отсюда шкала выхода — dBFS, ровно та, в которой микрофон специфицирован. Вольт в тракте нет, `V_REF` в приёмных скриптах не нужен. ## Формат кадра UART @@ -85,6 +89,21 @@ B3 (`FPGA_UART_RX`, контакт 19). выборка идёт в середине низкой фазы. Если вывод SELECT посажен на питание платой, поменять `SEL_HIGH` в `Top.vhd` на `'1'` — точка выборки переедет сама. +## Два ограничения кристалла, добытые на железе + +Оба проявляются одинаково: синтез и трассировка проходят без замечаний, тайминг +чистый, симуляция верная, а в кристалле тракт молча отдаёт нули. + +**Разрядность аккумуляторов CIC не выше 18 бит.** Проверено перебором на плате +с приёмом по UART: 26, 24 и 20 бит — тракт мёртв, 18, 16 и 10 бит — работает. +Отсюда порядок 3: требуется `ORDER*log2(DECIM)+1`, для 3 и 50 это ровно 18, для +4 было бы 24. На аккумулятор ФНЧ (40 бит) ограничение не распространяется — он +проверен на железе и считает верно. + +**Сброс по включению ставить нельзя.** Добавление счётчика, держащего `rst_n` +в нуле первые 256 тактов, убивает тракт целиком. С константой `'1'` всё +работает. Проверено прошивкой в обе стороны. + ## Сборка Выводы `clk` (E2) и `LED` (E8) на этом корпусе сидят на двойных функциях @@ -93,8 +112,9 @@ B3 (`FPGA_UART_RX`, контакт 19). в `gw_sh` -- `set_option -use_cpu_as_gpio 1 -use_sspi_as_gpio 1 -use_ready_as_gpio 1`. -Занято на GW5A-25: 778 LUT/ALU (4%), 616 регистров (3%), 5 BSRAM (9%), -1 DSP (4%). Fmax 164 МГц при требуемых 50, нарушений установки и удержания нет. +Занято на GW5A-25: 649 LUT/ALU (3%), 461 регистр (2%), 4 BSRAM (8%), 1 DSP (4%). +Тайминг сходится с запасом, но полагаться на него как на признак исправности +нельзя — см. раздел про ограничения кристалла выше. ## Состав @@ -102,7 +122,7 @@ B3 (`FPGA_UART_RX`, контакт 19). |:--|:--| | `src/Top.vhd` | верхний уровень: только экземпляры и связи | | `src/pdm_rx.vhd` | тактирование микрофона и выборка бита в нужной фазе | -| `src/cic_decim.vhd` | CIC sinc^4, децимация 50 | +| `src/cic_decim.vhd` | CIC sinc^3, децимация 50 | | `src/fir_decim.vhd` | ФНЧ с децимацией 5, последовательная свёртка | | `src/fir_coefs_pkg.vhd` | коэффициенты ФНЧ, генерируется | | `src/fifo_top.vhd` | буфер отсчётов, заглушка под IP-ядро Gowin | diff --git a/src/Top.vhd b/src/Top.vhd index bc00541..333f1bf 100644 --- a/src/Top.vhd +++ b/src/Top.vhd @@ -8,7 +8,7 @@ -- Target Devices: Gowin GW5A-25 -- Description: -- Цифровой микрофон SPH9855 -> UART. --- MIC_CLK 3.125 МГц (50/16, Normal mode) -> CIC sinc^4 /50 -> 62.5 кГц -> +-- MIC_CLK 3.125 МГц (50/16, Normal mode) -> CIC sinc^3 /50 -> 62.5 кГц -> -- ФНЧ /5 -> 12 500 Гц, 24 бита -> кадры по 50 отсчётов -> UART 921600. -- -- Постоянная '1' на выводе данных микрофона даёт полную шкалу 24 бит, @@ -51,16 +51,14 @@ architecture Behavioral of Top is constant PDM_DIV : integer := 16; -- 50 МГц / 16 = 3.125 МГц constant CIC_R : integer := 50; -- 3.125 МГц / 50 = 62.5 кГц - constant CIC_N : integer := 4; - constant CIC_W : integer := 26; + constant CIC_N : integer := 3; + constant CIC_W : integer := 18; constant FIR_DEC : integer := 5; -- 62.5 кГц / 5 = 12.5 кГц - -- Сброс по включению. Раньше здесь была константа '1', и тогда состояние - -- модулей после конфигурации определялось только начальными значениями - -- регистров. Для UART это критично: до первого кадра он молчит, и уровень - -- на линии задаёт его сдвиговый регистр, который обязан быть в единицах. - signal rst_n : std_logic := '0'; - signal rst_cnt : unsigned(7 downto 0) := (others => '0'); + -- Сброса нет намеренно: состояние задают начальные значения регистров. + -- Пробовал сброс по включению от счётчика -- на железе тракт от него молча + -- умирает, кадры перестают идти. Проверено прошивкой в обе стороны. + signal rst_n : std_logic := '1'; signal pdm_bit : std_logic; signal pdm_valid : std_logic; @@ -89,37 +87,33 @@ architecture Behavioral of Top is begin - por_proc : process (clk) - begin - if rising_edge(clk) then - if rst_cnt = 255 then - rst_n <= '1'; - else - rst_cnt <= rst_cnt + 1; - rst_n <= '0'; - end if; - end if; - end process por_proc; + rst_n <= '1'; led_event <= pdm_valid when LED_SRC = 2 else cic_valid when LED_SRC = 1 else fir_valid; - LED <= beacon when LED_SRC = 3 else led_chain; + -- Маяк собирается только когда выбран: его счётчик широкий и тикает каждый + -- такт, а такие в этом кристалле надёжно работать не обязаны + beacon_gen : if LED_SRC = 3 generate + LED <= beacon; - -- Маяк: полпериода = SYS_CLK_HZ/2 тактов, то есть ровно 1 Гц на выводе. - -- Ни от чего, кроме clk, не зависит. - beacon_proc : process (clk) - begin - if rising_edge(clk) then - if beat_cnt = SYS_CLK_HZ / 2 - 1 then - beat_cnt <= 0; - beacon <= not beacon; - else - beat_cnt <= beat_cnt + 1; + beacon_proc : process (clk) + begin + if rising_edge(clk) then + if beat_cnt = SYS_CLK_HZ / 2 - 1 then + beat_cnt <= 0; + beacon <= not beacon; + else + beat_cnt <= beat_cnt + 1; + end if; end if; - end if; - end process beacon_proc; + end process beacon_proc; + end generate beacon_gen; + + chain_gen : if LED_SRC /= 3 generate + LED <= led_chain; + end generate chain_gen; pdm_rx_inst : entity work.pdm_rx(rtl) generic map( @@ -159,7 +153,7 @@ begin DOUT_W => 24, DECIM => FIR_DEC, BUF_AW => 8, - ACC_W => 48 + ACC_W => 40 ) port map ( @@ -234,6 +228,7 @@ begin tx => UART_TX ); + led_status_inst : entity work.led_status(rtl) generic map( SYS_CLK_HZ => SYS_CLK_HZ, diff --git a/src/cic_decim.vhd b/src/cic_decim.vhd index 5d6895c..0df0266 100644 --- a/src/cic_decim.vhd +++ b/src/cic_decim.vhd @@ -11,10 +11,12 @@ -- частоте PDM, гребёнки -- на пониженной. Умножителей не требует, нули АЧХ -- стоят ровно на частотах, которые складываются в полосу при децимации. -- --- Разрядность: ORDER*log2(DECIM) + 1 бит на знак. Для 4 и 50 это 24 бита, --- ACC_W взят с запасом. Переполнение внутри тракта штатно: результат верен --- за счёт дополнительного кода, пока ACC_W не меньше требуемого. --- Постоянному '1' на входе отвечает DECIM^ORDER = 6 250 000. +-- Разрядность: ORDER*log2(DECIM) + 1 бит на знак. Для 3 и 50 это 18 бит. +-- Шире 18 бит на этом кристалле нельзя: аккумуляторы от 20 бит и выше +-- Gowin укладывает неверно, тракт молча отдаёт нули (проверено на железе). +-- Переполнение внутри тракта штатно: результат верен за счёт дополнительного +-- кода, пока ACC_W не меньше требуемого. +-- Постоянному '1' на входе отвечает DECIM^ORDER = 125 000. -- -- Каждая ступень защёлкнута отдельно -- это только задержка на ORDER -- отсчётов, зато нет длинной цепи сумматоров в одном такте. diff --git a/src/fir_coefs_pkg.vhd b/src/fir_coefs_pkg.vhd index 0b6cce1..61f6c71 100644 --- a/src/fir_coefs_pkg.vhd +++ b/src/fir_coefs_pkg.vhd @@ -9,8 +9,8 @@ -- вход 62500 Гц -> выход 12500 Гц, отводов 221, симметричный -- полоса 0..5000 Гц, задерживание от 6250 Гц -- неравномерность полосы с учётом CIC: 0.032 дБ --- подавление в полосе задерживания: -72.1 дБ --- худшее подавление сворачиваемых полос: -77.5 дБ +-- подавление в полосе задерживания: -76.3 дБ +-- худшее подавление сворачиваемых полос: -92.1 дБ ---------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; @@ -20,72 +20,72 @@ package fir_coefs_pkg is constant FIR_NTAPS : integer := 221; constant FIR_COEF_W : integer := 18; - constant FIR_SHIFT : integer := 17; + constant FIR_SHIFT : integer := 13; -- Отклик тракта на постоянную '1' на выводе данных микрофона: -- сумма коэффициентов x усиление CIC, округлённая как в fir_decim. - constant FIR_SUM : integer := 175921; - constant FIR_DC_CODE : integer := 8388567; + constant FIR_SUM : integer := 549755; + constant FIR_DC_CODE : integer := 8388596; type fir_coefs_t is array (0 to FIR_NTAPS - 1) of signed(FIR_COEF_W - 1 downto 0); constant FIR_COEFS : fir_coefs_t := ( - "000000000000000001", "000000000000000010", "000000000000000100", "000000000000000111", -- 0 - "000000000000001000", "000000000000001000", "000000000000000110", "000000000000000001", -- 4 - "111111111111111010", "111111111111110100", "111111111111101110", "111111111111101101", -- 8 - "111111111111110010", "111111111111111011", "000000000000001000", "000000000000010110", -- 12 - "000000000000011111", "000000000000100000", "000000000000010111", "000000000000000101", -- 16 - "111111111111101101", "111111111111010111", "111111111111001010", "111111111111001100", -- 20 - "111111111111011111", "000000000000000000", "000000000000100110", "000000000001000111", -- 24 - "000000000001010110", "000000000001001100", "000000000000101000", "111111111111110001", -- 28 - "111111111110110111", "111111111110001100", "111111111101111111", "111111111110011010", -- 32 - "111111111111011010", "000000000000101111", "000000000010000000", "000000000010110011", -- 36 - "000000000010110100", "000000000001111011", "000000000000010100", "111111111110011001", -- 40 - "111111111100101111", "111111111011111011", "111111111100010100", "111111111101111100", -- 44 - "000000000000011010", "000000000011000010", "000000000101000001", "000000000101100111", -- 48 - "000000000100011111", "000000000001110100", "111111111110010000", "111111111010110111", -- 52 - "111111111000101111", "111111111000101100", "111111111010111110", "111111111111000110", -- 56 - "000000000011111100", "000000001000000011", "000000001010000001", "000000001001000000", -- 60 - "000000000101000001", "111111111111000010", "111111111000101111", "111111110100001000", -- 64 - "111111110010110100", "111111110101100100", "111111111011111011", "000000000100001101", -- 68 - "000000001100000000", "000000010000110000", "000000010000101010", "000000001011010000", -- 72 - "000000000001101101", "111111110110101001", "111111101101011100", "111111101001001100", -- 76 - "111111101011110001", "111111110101000101", "000000000010111000", "000000010001001111", -- 80 - "000000011011101011", "000000011110011001", "000000010111101101", "000000001000101000", -- 84 - "111111110100111111", "111111100010100000", "111111010111001101", "111111010111100110", -- 88 - "111111100101001000", "111111111101001111", "000000011001110001", "000000110010010000", -- 92 - "000000111110001111", "000000110111110101", "000000011101110100", "111111110100110100", -- 96 - "111111000110110101", "111110100001011001", "111110010010011110", "111110100100111011", -- 100 - "111111011101011111", "000000111000110011", "000010101011011110", "000100100011111001", -- 104 - "000110001101101111", "000111010110001001", "000111110000000101", "000111010110001001", -- 108 - "000110001101101111", "000100100011111001", "000010101011011110", "000000111000110011", -- 112 - "111111011101011111", "111110100100111011", "111110010010011110", "111110100001011001", -- 116 - "111111000110110101", "111111110100110100", "000000011101110100", "000000110111110101", -- 120 - "000000111110001111", "000000110010010000", "000000011001110001", "111111111101001111", -- 124 - "111111100101001000", "111111010111100110", "111111010111001101", "111111100010100000", -- 128 - "111111110100111111", "000000001000101000", "000000010111101101", "000000011110011001", -- 132 - "000000011011101011", "000000010001001111", "000000000010111000", "111111110101000101", -- 136 - "111111101011110001", "111111101001001100", "111111101101011100", "111111110110101001", -- 140 - "000000000001101101", "000000001011010000", "000000010000101010", "000000010000110000", -- 144 - "000000001100000000", "000000000100001101", "111111111011111011", "111111110101100100", -- 148 - "111111110010110100", "111111110100001000", "111111111000101111", "111111111111000010", -- 152 - "000000000101000001", "000000001001000000", "000000001010000001", "000000001000000011", -- 156 - "000000000011111100", "111111111111000110", "111111111010111110", "111111111000101100", -- 160 - "111111111000101111", "111111111010110111", "111111111110010000", "000000000001110100", -- 164 - "000000000100011111", "000000000101100111", "000000000101000001", "000000000011000010", -- 168 - "000000000000011010", "111111111101111100", "111111111100010100", "111111111011111011", -- 172 - "111111111100101111", "111111111110011001", "000000000000010100", "000000000001111011", -- 176 - "000000000010110100", "000000000010110011", "000000000010000000", "000000000000101111", -- 180 - "111111111111011010", "111111111110011010", "111111111101111111", "111111111110001100", -- 184 - "111111111110110111", "111111111111110001", "000000000000101000", "000000000001001100", -- 188 - "000000000001010110", "000000000001000111", "000000000000100110", "000000000000000000", -- 192 - "111111111111011111", "111111111111001100", "111111111111001010", "111111111111010111", -- 196 - "111111111111101101", "000000000000000101", "000000000000010111", "000000000000100000", -- 200 - "000000000000011111", "000000000000010110", "000000000000001000", "111111111111111011", -- 204 - "111111111111110010", "111111111111101101", "111111111111101110", "111111111111110100", -- 208 - "111111111111111010", "000000000000000001", "000000000000000110", "000000000000001000", -- 212 - "000000000000001000", "000000000000000111", "000000000000000100", "000000000000000010", -- 216 - "000000000000000001" -- 220 + "000000000000000011", "000000000000000111", "000000000000001110", "000000000000010100", -- 0 + "000000000000011001", "000000000000011001", "000000000000010010", "000000000000000011", -- 4 + "111111111111101111", "111111111111011010", "111111111111001011", "111111111111000111", -- 8 + "111111111111010100", "111111111111110010", "000000000000011011", "000000000001000011", -- 12 + "000000000001100000", "000000000001100011", "000000000001000111", "000000000000001110", -- 16 + "111111111111000110", "111111111110000011", "111111111101011011", "111111111101100001", -- 20 + "111111111110011011", "000000000000000000", "000000000001110111", "000000000011011011", -- 24 + "000000000100001001", "000000000011101001", "000000000001111010", "111111111111010010", -- 28 + "111111111100011111", "111111111010011001", "111111111001110011", "111111111011000111", -- 32 + "111111111110001100", "000000000010010001", "000000000110001011", "000000001000101001", -- 36 + "000000001000101011", "000000000101111011", "000000000000111100", "111111111011000000", -- 40 + "111111110101111011", "111111110011011011", "111111110100101001", "111111111001101001", -- 44 + "000000000001010001", "000000001001011001", "000000001111011110", "000000010001010011", -- 48 + "000000001101110101", "000000000101100100", "111111111010100110", "111111110000001000", -- 52 + "111111101001100110", "111111101001011110", "111111110000100001", "111111111101010000", -- 56 + "000000001100001101", "000000011000110110", "000000011110111001", "000000011011110000", -- 60 + "000000001111011100", "111111111100111101", "111111101001100100", "111111011011010101", -- 64 + "111111010111010100", "111111011111110110", "111111110011011110", "000000001101000100", -- 68 + "000000100101000100", "000000110011101101", "000000110011010111", "000000100010101000", -- 72 + "000000000101001011", "111111100011000011", "111111000110101010", "111110111001100111", -- 76 + "111111000001101010", "111111011110011101", "000000001001000010", "000000110101010100", -- 80 + "000001010101011011", "000001011101101111", "000001001000111110", "000000011010011000", -- 84 + "111111011101110010", "111110100100110011", "111110000010000100", "111110000011011110", -- 88 + "111110101101011000", "111111110111111011", "000001001111111101", "000010011011011000", -- 92 + "000011000000000100", "000010101011111000", "000001011011001110", "111111011100011010", -- 96 + "111101001110011111", "111011011011010101", "111010101110000110", "111011101000011010", -- 100 + "111110011000101100", "000010110100100011", "001000011000100101", "001110001110010000", -- 104 + "010011010110100000", "010110110111000011", "011000000110110111", "010110110111000011", -- 108 + "010011010110100000", "001110001110010000", "001000011000100101", "000010110100100011", -- 112 + "111110011000101100", "111011101000011010", "111010101110000110", "111011011011010101", -- 116 + "111101001110011111", "111111011100011010", "000001011011001110", "000010101011111000", -- 120 + "000011000000000100", "000010011011011000", "000001001111111101", "111111110111111011", -- 124 + "111110101101011000", "111110000011011110", "111110000010000100", "111110100100110011", -- 128 + "111111011101110010", "000000011010011000", "000001001000111110", "000001011101101111", -- 132 + "000001010101011011", "000000110101010100", "000000001001000010", "111111011110011101", -- 136 + "111111000001101010", "111110111001100111", "111111000110101010", "111111100011000011", -- 140 + "000000000101001011", "000000100010101000", "000000110011010111", "000000110011101101", -- 144 + "000000100101000100", "000000001101000100", "111111110011011110", "111111011111110110", -- 148 + "111111010111010100", "111111011011010101", "111111101001100100", "111111111100111101", -- 152 + "000000001111011100", "000000011011110000", "000000011110111001", "000000011000110110", -- 156 + "000000001100001101", "111111111101010000", "111111110000100001", "111111101001011110", -- 160 + "111111101001100110", "111111110000001000", "111111111010100110", "000000000101100100", -- 164 + "000000001101110101", "000000010001010011", "000000001111011110", "000000001001011001", -- 168 + "000000000001010001", "111111111001101001", "111111110100101001", "111111110011011011", -- 172 + "111111110101111011", "111111111011000000", "000000000000111100", "000000000101111011", -- 176 + "000000001000101011", "000000001000101001", "000000000110001011", "000000000010010001", -- 180 + "111111111110001100", "111111111011000111", "111111111001110011", "111111111010011001", -- 184 + "111111111100011111", "111111111111010010", "000000000001111010", "000000000011101001", -- 188 + "000000000100001001", "000000000011011011", "000000000001110111", "000000000000000000", -- 192 + "111111111110011011", "111111111101100001", "111111111101011011", "111111111110000011", -- 196 + "111111111111000110", "000000000000001110", "000000000001000111", "000000000001100011", -- 200 + "000000000001100000", "000000000001000011", "000000000000011011", "111111111111110010", -- 204 + "111111111111010100", "111111111111000111", "111111111111001011", "111111111111011010", -- 208 + "111111111111101111", "000000000000000011", "000000000000010010", "000000000000011001", -- 212 + "000000000000011001", "000000000000010100", "000000000000001110", "000000000000000111", -- 216 + "000000000000000011" -- 220 ); end package fir_coefs_pkg; diff --git a/tools/gen_fir_coefs.py b/tools/gen_fir_coefs.py index 455f040..ad82100 100644 --- a/tools/gen_fir_coefs.py +++ b/tools/gen_fir_coefs.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 """Расчёт ФНЧ-дециматора /5 и генерация src/fir_coefs_pkg.vhd. -Фильтр стоит после CIC sinc^4 /50 и решает две задачи сразу: +Фильтр стоит после CIC sinc^3 /50 и решает две задачи сразу: - давит всё выше 6250 Гц, куда после децимации на 5 сворачивается шум сигма-дельта модулятора микрофона (CIC там ничего не подавляет); - выравнивает спад CIC в полосе (задаётся желаемая АЧХ 1/H_cic). Масштаб выбран так, чтобы постоянная '1' на входе PDM давала полную шкалу -24 бит: коэффициенты домножены на 2^23 / 50^4 и сумма подогнана точно. +24 бит: коэффициенты домножены на 2^23 / 50^3 и сумма подогнана точно. Запуск: py -3 tools/gen_fir_coefs.py """ @@ -21,7 +21,7 @@ from scipy.signal import firls, freqz # --- параметры тракта, должны совпадать с Top.vhd --- F_PDM = 3_125_000.0 # PDM_CLK = 50 МГц / 16 R_CIC = 50 # децимация CIC -N_CIC = 4 # порядок CIC +N_CIC = 3 # порядок CIC FS_IN = F_PDM / R_CIC # 62500 Гц на входе FIR DECIM = 5 # децимация FIR FS_OUT = FS_IN / DECIM # 12500 Гц @@ -29,7 +29,7 @@ FS_OUT = FS_IN / DECIM # 12500 Гц # --- параметры фильтра --- NTAPS = 221 # нечётное: линейная фаза, симметрия COEF_W = 18 # разрядность коэффициента -SHIFT = 17 # выход = (сумма произведений) >> SHIFT +SHIFT = 13 # выход = (сумма произведений) >> SHIFT PASS = 5000.0 # граница полосы пропускания STOP = 6250.0 # граница полосы задерживания = FS_OUT/2 WSTOP = 300.0 # вес полосы задерживания