Порядок CIC 3 вместо 4: аккумуляторы шире 18 бит не работают в кристалле

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