AD7766 на Tang Primer 25K: отладочная прошивка, структура после рефакторинга
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
----------------------------------------------------------------------------------
|
||||
-- Module Name: ad7766_model
|
||||
-- Project Name: AD7766_prj
|
||||
-- Description:
|
||||
-- Поведенческая модель AD7766 для симуляции. Не синтезируется.
|
||||
-- Воспроизводит: сброс фильтра по SYNC/PD, задержку tSETTLING, период DRDY
|
||||
-- в 8 периодов MCLK, выдачу MSB по спаду CS и остальных бит по спадам SCLK.
|
||||
-- Времена tN — по AD7766 Data Sheet Rev. D, Table 3.
|
||||
----------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity ad7766_model is
|
||||
generic (
|
||||
SETTLING_MCLK : integer := 590; -- tSETTLING для AD7766, Table 7
|
||||
ODR_DIV : integer := 8; -- ODR = MCLK/8 для AD7766, Table 6
|
||||
T4 : time := 265 ns;
|
||||
T5 : time := 294 ns;
|
||||
T7 : time := 6 ns;
|
||||
T8 : time := 24 ns
|
||||
);
|
||||
port (
|
||||
mclk : in std_logic;
|
||||
sync_pd_n : in std_logic;
|
||||
cs_n : in std_logic;
|
||||
sclk : in std_logic;
|
||||
next_word : in std_logic_vector(23 downto 0);
|
||||
|
||||
sdo : out std_logic;
|
||||
drdy : out std_logic;
|
||||
word_tick : out std_logic -- строб: слово защёлкнуто в выходной регистр
|
||||
);
|
||||
end entity ad7766_model;
|
||||
|
||||
architecture model of ad7766_model is
|
||||
signal out_reg : std_logic_vector(23 downto 0) := (others => '0');
|
||||
signal bit_idx : integer range 0 to 23 := 23;
|
||||
signal settled : std_logic := '0';
|
||||
signal s_cnt : integer := 0;
|
||||
signal div : integer range 0 to ODR_DIV - 1 := 0;
|
||||
begin
|
||||
|
||||
drdy_proc : process (mclk, sync_pd_n)
|
||||
begin
|
||||
if sync_pd_n = '0' then
|
||||
-- SYNC/PD низкий: выходной регистр недействителен, DRDY уходит вверх
|
||||
drdy <= '1';
|
||||
settled <= '0';
|
||||
s_cnt <= 0;
|
||||
div <= 0;
|
||||
word_tick <= '0';
|
||||
elsif rising_edge(mclk) then
|
||||
word_tick <= '0';
|
||||
if settled = '0' then
|
||||
if s_cnt = SETTLING_MCLK - 1 then
|
||||
settled <= '1';
|
||||
div <= 0;
|
||||
out_reg <= next_word;
|
||||
word_tick <= '1';
|
||||
drdy <= '1' after T4, '0' after T4 + T5;
|
||||
else
|
||||
s_cnt <= s_cnt + 1;
|
||||
end if;
|
||||
else
|
||||
if div = ODR_DIV - 1 then
|
||||
div <= 0;
|
||||
out_reg <= next_word;
|
||||
word_tick <= '1';
|
||||
drdy <= '1' after T4, '0' after T4 + T5;
|
||||
else
|
||||
div <= div + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process drdy_proc;
|
||||
|
||||
-- MSB встаёт на SDO по спаду CS, остальные биты — спадами SCLK (стр. 17)
|
||||
shift_proc : process (cs_n, sclk)
|
||||
begin
|
||||
if cs_n = '1' then
|
||||
bit_idx <= 23;
|
||||
elsif falling_edge(sclk) then
|
||||
if bit_idx > 0 then
|
||||
bit_idx <= bit_idx - 1;
|
||||
end if;
|
||||
end if;
|
||||
end process shift_proc;
|
||||
|
||||
sdo <= 'Z' after T7 when cs_n = '1' else
|
||||
out_reg(bit_idx) after T8;
|
||||
|
||||
end architecture model;
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
----------------------------------------------------------------------------------
|
||||
-- Module Name: tb_top
|
||||
-- Project Name: AD7766_prj
|
||||
-- Description:
|
||||
-- Сквозной тест: модель AD7766 -> top -> UART -> разбор кадра в тестбенче.
|
||||
-- Модель выдаёт группами по DECIM одинаковых слов, поэтому усреднённый
|
||||
-- отсчёт обязан в точности совпасть со значением группы. Проверяются
|
||||
-- разрядность, знак, порядок байт, CRC и счётчик кадров.
|
||||
----------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use std.env.all;
|
||||
|
||||
entity tb_top is
|
||||
generic (
|
||||
FRAMES : integer := 2 -- сколько кадров проверяем, переопределяется -gFRAMES=N
|
||||
);
|
||||
end entity tb_top;
|
||||
|
||||
architecture sim of tb_top is
|
||||
|
||||
constant CLK_T : time := 20 ns;
|
||||
constant BAUD : integer := 921600;
|
||||
constant BIT_T : time := 1 sec / BAUD;
|
||||
constant DECIM : integer := 10;
|
||||
constant SPF : integer := 50; -- отсчётов в кадре
|
||||
|
||||
constant PAYLOAD_LEN : integer := 2 + 1 + SPF * 3; -- CNT + STATUS + DATA
|
||||
|
||||
signal clk : std_logic := '0';
|
||||
signal run : boolean := true;
|
||||
|
||||
signal adc_sdo : std_logic;
|
||||
signal adc_drdy : std_logic;
|
||||
signal adc_sclk : std_logic;
|
||||
signal adc_mclk : std_logic;
|
||||
signal adc_sdi : std_logic;
|
||||
signal adc_cs_n : std_logic;
|
||||
signal adc_sync_pd : std_logic;
|
||||
signal uart_tx : std_logic;
|
||||
signal led : std_logic;
|
||||
|
||||
signal next_word : std_logic_vector(23 downto 0);
|
||||
signal word_tick : std_logic;
|
||||
signal word_idx : integer := 0;
|
||||
|
||||
type byte_arr_t is array (natural range <>) of std_logic_vector(7 downto 0);
|
||||
|
||||
-- Значения групп: крайние точки шкалы, единицы младшего разряда и оба знака
|
||||
function grp_value(g : integer) return signed is
|
||||
variable v : integer;
|
||||
begin
|
||||
case g mod 8 is
|
||||
when 0 => v := 0;
|
||||
when 1 => v := 8388607; -- +полная шкала
|
||||
when 2 => v := - 8388608; -- -полная шкала
|
||||
when 3 => v := 1;
|
||||
when 4 => v := - 1;
|
||||
when 5 => v := 5592405; -- 0x555555
|
||||
when 6 => v := - 5592406; -- 0xAAAAAA как знаковое
|
||||
when others => v := 1193046; -- 0x123456
|
||||
end case;
|
||||
return to_signed(v, 24);
|
||||
end function;
|
||||
|
||||
function crc16_upd(crc : std_logic_vector(15 downto 0);
|
||||
d : std_logic_vector(7 downto 0))
|
||||
return std_logic_vector is
|
||||
variable c : std_logic_vector(15 downto 0) := crc;
|
||||
variable fb : std_logic;
|
||||
begin
|
||||
for i in 7 downto 0 loop
|
||||
fb := c(15) xor d(i);
|
||||
c := c(14 downto 0) & '0';
|
||||
if fb = '1' then
|
||||
c := c xor x"1021";
|
||||
end if;
|
||||
end loop;
|
||||
return c;
|
||||
end function;
|
||||
|
||||
procedure get_byte(signal rx : in std_logic;
|
||||
b : out std_logic_vector(7 downto 0)) is
|
||||
variable v : std_logic_vector(7 downto 0);
|
||||
begin
|
||||
wait until rx = '0'; -- фронт старт-бита
|
||||
wait for BIT_T / 2;
|
||||
assert rx = '0' report "start bit not confirmed" severity error;
|
||||
for i in 0 to 7 loop
|
||||
wait for BIT_T;
|
||||
v(i) := rx;
|
||||
end loop;
|
||||
wait for BIT_T;
|
||||
assert rx = '1' report "stop bit not at expected position" severity error;
|
||||
b := v;
|
||||
end procedure;
|
||||
|
||||
begin
|
||||
|
||||
clk <= not clk after CLK_T / 2 when run else '0';
|
||||
|
||||
next_word <= std_logic_vector(grp_value(word_idx / DECIM));
|
||||
|
||||
word_cnt_proc : process
|
||||
begin
|
||||
wait until rising_edge(word_tick);
|
||||
word_idx <= word_idx + 1;
|
||||
end process word_cnt_proc;
|
||||
|
||||
dut : entity work.Top(Behavioral)
|
||||
generic map(
|
||||
SYS_CLK_HZ => 50_000_000,
|
||||
BAUD_RATE => BAUD
|
||||
)
|
||||
port map
|
||||
(
|
||||
clk => clk,
|
||||
ADC_SDO => adc_sdo,
|
||||
ADC_DRDY => adc_drdy,
|
||||
ADC_SCLK => adc_sclk,
|
||||
ADC_MCLK => adc_mclk,
|
||||
ADC_SDI => adc_sdi,
|
||||
ADC_CS_N => adc_cs_n,
|
||||
ADC_SYNC_PD => adc_sync_pd,
|
||||
UART_TX => uart_tx,
|
||||
LED => led
|
||||
);
|
||||
|
||||
adc : entity work.ad7766_model(model)
|
||||
port map
|
||||
(
|
||||
mclk => adc_mclk,
|
||||
sync_pd_n => adc_sync_pd,
|
||||
cs_n => adc_cs_n,
|
||||
sclk => adc_sclk,
|
||||
next_word => next_word,
|
||||
sdo => adc_sdo,
|
||||
drdy => adc_drdy,
|
||||
word_tick => word_tick
|
||||
);
|
||||
|
||||
check_proc : process
|
||||
variable b : std_logic_vector(7 downto 0);
|
||||
variable prev : std_logic_vector(7 downto 0) := (others => '0');
|
||||
variable pl : byte_arr_t(0 to PAYLOAD_LEN - 1);
|
||||
variable crc : std_logic_vector(15 downto 0);
|
||||
variable crc_rx : std_logic_vector(15 downto 0);
|
||||
variable cnt_rx : integer;
|
||||
variable got : signed(23 downto 0);
|
||||
variable want : signed(23 downto 0);
|
||||
variable errors : integer := 0;
|
||||
variable frame_no : integer := 0;
|
||||
begin
|
||||
report "start: waiting for first frame";
|
||||
|
||||
while frame_no < FRAMES loop
|
||||
|
||||
-- Ищем SYNC A5 5A, как это будет делать приёмник на ПК
|
||||
loop
|
||||
get_byte(uart_tx, b);
|
||||
exit when prev = x"A5" and b = x"5A";
|
||||
prev := b;
|
||||
end loop;
|
||||
prev := (others => '0');
|
||||
|
||||
for i in 0 to PAYLOAD_LEN - 1 loop
|
||||
get_byte(uart_tx, b);
|
||||
pl(i) := b;
|
||||
end loop;
|
||||
get_byte(uart_tx, b);
|
||||
crc_rx(15 downto 8) := b;
|
||||
get_byte(uart_tx, b);
|
||||
crc_rx(7 downto 0) := b;
|
||||
|
||||
crc := x"FFFF";
|
||||
for i in 0 to PAYLOAD_LEN - 1 loop
|
||||
crc := crc16_upd(crc, pl(i));
|
||||
end loop;
|
||||
|
||||
if crc /= crc_rx then
|
||||
report "frame " & integer'image(frame_no) & ": CRC mismatch" severity error;
|
||||
errors := errors + 1;
|
||||
end if;
|
||||
|
||||
cnt_rx := to_integer(unsigned(std_logic_vector'(pl(0) & pl(1))));
|
||||
if cnt_rx /= frame_no then
|
||||
report "frame " & integer'image(frame_no) & ": FRAME_CNT = " &
|
||||
integer'image(cnt_rx) severity error;
|
||||
errors := errors + 1;
|
||||
end if;
|
||||
|
||||
if pl(2) /= x"00" then
|
||||
report "frame " & integer'image(frame_no) & ": STATUS not zero" severity error;
|
||||
errors := errors + 1;
|
||||
end if;
|
||||
|
||||
for i in 0 to SPF - 1 loop
|
||||
got := signed(std_logic_vector'(pl(3 + i * 3) & pl(4 + i * 3) & pl(5 + i * 3)));
|
||||
want := grp_value(frame_no * SPF + i);
|
||||
if got /= want then
|
||||
report "frame " & integer'image(frame_no) & " sample " & integer'image(i) &
|
||||
": got " & integer'image(to_integer(got)) &
|
||||
", want " & integer'image(to_integer(want)) severity error;
|
||||
errors := errors + 1;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
report "frame " & integer'image(frame_no) & " parsed OK";
|
||||
frame_no := frame_no + 1;
|
||||
end loop;
|
||||
|
||||
if errors = 0 then
|
||||
report "TEST PASSED: frames = " & integer'image(FRAMES) & "";
|
||||
else
|
||||
report "TEST FAILED: errors = " & integer'image(errors) severity error;
|
||||
end if;
|
||||
|
||||
run <= false;
|
||||
stop;
|
||||
end process check_proc;
|
||||
|
||||
end architecture sim;
|
||||
Reference in New Issue
Block a user