fpga: x400: Add support for X410 motherboard FPGA

Co-authored-by: Andrew Moch <Andrew.Moch@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Javier Valenzuela <javier.valenzuela@ni.com>
Co-authored-by: Joerg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Kumaran Subramoniam <kumaran.subramoniam@ni.com>
Co-authored-by: Max Köhler <max.koehler@ni.com>
Co-authored-by: Michael Auchter <michael.auchter@ni.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Co-authored-by: Hector Rubio <hrubio@ni.com>


Original-commit: 6d3765605262016a80f71e36357f749ea35cbe5a
This commit is contained in:
Wade Fife
2021-06-10 11:56:58 -05:00
committed by Aaron Rossetto
co-authored by Andrew Moch Daniel Jepson Javier Valenzuela Joerg Hofrichter Kumaran Subramoniam Max Köhler Michael Auchter Paul Butler Hector Rubio
parent bfef20ea45
commit 61782b02d7
205 changed files with 299634 additions and 0 deletions
+143
View File
@@ -0,0 +1,143 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: dac_1_3_clk_converter
--
-- Description:
--
-- This module transfers data from s_axis_aclk to m_axis_aclk. m_axis_aclk
-- must be three times the frequency of s_axis_aclk, and the two clocks must
-- be related (this module requires timing closure across the clock domain
-- boundary).
--
library IEEE;
use IEEE.std_logic_1164.all;
entity dac_1_3_clk_converter is
port(
s_axis_aclk : in std_logic;
s_axis_aresetn : in std_logic;
s_axis_tvalid : in std_logic;
s_axis_tdata : in std_logic_vector(31 downto 0);
s_axis_tready : out std_logic := '1';
m_axis_aclk : in std_logic;
m_axis_aresetn : in std_logic;
m_axis_tready : in std_logic;
m_axis_tdata : out std_logic_vector(31 downto 0);
m_axis_tvalid : out std_logic
);
end entity dac_1_3_clk_converter;
architecture RTL of dac_1_3_clk_converter is
-- I was unable to think of a simple implementation that implements a correct
-- AXIS handshake on both ports. All my ideas became equivalent to a two
-- clock FIFO (although the clocks are synchronous, so the write-to-read
-- latency would have been certain).
--
-- We don't expect the DAC to ever hold off incoming data, and dac_100m_bd
-- already has the AXIS handshake disconnected: the FIR is configured to
-- disallow back pressure - it has no m_axis_data_tready pin.
--
-- I'm going with the simple, but not strictly correct, implementation.
-- s_axis_tready will be constantly true, even when it shouldn't be. The
-- bottom line is this component is likely useless for any application but
-- dac_100m_bd.
type output_fsm is (
idle,
got_data,
-- The recovery state of delay ensures that we don't re-use an old input
-- valid signal (remember the output clock is 3x the frequency of the input
-- clock)
recovery
);
subtype word is std_logic_vector(s_axis_tdata'range);
signal output_state_mclk : output_fsm;
signal axis_tdata_sclk : word;
signal axis_tvalid_sclk : std_logic;
signal axis_tdata_mclk : word;
signal axis_tvalid_mclk : std_logic;
begin
s_axis_tready <= '1';
input_valid_register:
process(s_axis_aclk, s_axis_aresetn) is
begin
if s_axis_aresetn='0' then
axis_tvalid_sclk <= '0';
elsif rising_edge(s_axis_aclk) then
axis_tvalid_sclk <= s_axis_tvalid;
end if;
end process;
input_data_register:
process (s_axis_aclk) is
begin
if rising_edge(s_axis_aclk) then
axis_tdata_sclk <= s_axis_tdata;
end if;
end process input_data_register;
-- These CDC registers will not become metastable because the two clock
-- domains are related.
cdc_input_valid_register:
process (m_axis_aclk, m_axis_aresetn) is
begin
if m_axis_aresetn='0' then
axis_tvalid_mclk <= '0';
elsif rising_edge(m_axis_aclk) then
axis_tvalid_mclk <= axis_tvalid_sclk;
end if;
end process cdc_input_valid_register;
cdc_input_data_register:
process (m_axis_aclk) is
begin
if rising_edge(m_axis_aclk) then
axis_tdata_mclk <= axis_tdata_sclk;
end if;
end process cdc_input_data_register;
output_data_register:
process (m_axis_aclk) is
begin
if rising_edge(m_axis_aclk) then
if output_state_mclk=idle then
m_axis_tdata <= axis_tdata_mclk;
end if;
end if;
end process output_data_register;
fsm: process(m_axis_aresetn, m_axis_aclk) is
begin
if m_axis_aresetn='0' then
output_state_mclk <= idle;
m_axis_tvalid <= '0';
elsif rising_edge(m_axis_aclk) then
m_axis_tvalid <= '0';
case output_state_mclk is
when idle =>
if axis_tvalid_mclk='1' then
output_state_mclk <= got_data;
end if;
when got_data =>
m_axis_tvalid <= '1';
output_state_mclk <= recovery;
when recovery =>
output_state_mclk <= idle;
end case;
end if;
end process fsm;
end RTL;