utopia_master_tx.vhd
来自「utopia主模式发送和接收 主要针对5384」· VHDL 代码 · 共 413 行
VHD
413 行
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
entity utopia_master_tx is
port(
RST : in std_logic;
------------utopia interface ----------------------------------------
PM5384_TFCLK : in std_logic;
PM5384_TDATA : out std_logic_vector(15 downto 0);
PM5384_TPRTY : out std_logic;
PM5384_TENB : out std_logic;
PM5384_TSOC : out std_logic;
PM5384_TCA : in std_logic;
PM5384_TADDR : out std_logic_vector(4 downto 0);
PollAddr_S : in std_logic_vector(4 downto 0); -- input start addr of slave module
PollAddr_E : in std_logic_vector(4 downto 0); -- input end addr of slave module
MODULE_EN : in std_logic;
-------------fifo interface------------------------------------------------------
FIFO_RDREQ : out std_logic_vector(3 downto 0);
FIFO_Q0 : in std_logic_vector(15 downto 0);
FIFO_RDUSEDW0 : in std_logic_vector(6 downto 0);
FIFO_Q1 : in std_logic_vector(15 downto 0);
FIFO_RDUSEDW1 : in std_logic_vector(6 downto 0);
FIFO_Q2 : in std_logic_vector(15 downto 0);
FIFO_RDUSEDW2 : in std_logic_vector(6 downto 0);
FIFO_Q3 : in std_logic_vector(15 downto 0);
FIFO_RDUSEDW3 : in std_logic_vector(6 downto 0);
--------------tst interface-------------------------------------------------------------
TST_SM : out std_logic_vector(2 downto 0)
);
end utopia_master_tx;
architecture bhv of utopia_master_tx is
signal sig_pm5384_taddr : std_logic_vector(4 downto 0);
signal sig_addr_keep : std_logic_vector(4 downto 0);
--define cpustate machine
type SM is(
sm_en,
sm_wait,
sm_s0,
sm_s1,
sm_s2,
-- sm_s3,
sm_s4,
sm_t,
sm_t1,
sm_t2
);
signal tx_sm : SM;
subtype data_word is std_logic_vector(15 downto 0);
type ram16 is array (0 to 3) of data_word;
signal sig_q_array : ram16;
subtype data_byte is std_logic_vector(6 downto 0);
type ram7 is array (0 to 3) of data_byte;
signal sig_rdusedw_array : ram7;
signal sig_index : integer range 0 to 3;
signal sig_index0 : integer range 0 to 3;
signal sel_addr : std_logic_vector(4 downto 0);
signal poll_flag : std_logic;
signal select_addr : std_logic_vector(4 downto 0);
signal phy_status : std_logic_vector(3 downto 0);
signal fifo_flag : std_logic_vector(3 downto 0);
type state2 is (wait0,idle,phy1,phy2,phy3,phy4);
signal select_state : state2;
signal select_stop : std_logic;
signal select_suc : std_logic;
signal select_flag : std_logic_vector(1 downto 0);
signal select_flag0 : integer range 0 to 3;
begin -- bhv
sig_q_array(0) <= FIFO_Q0;
sig_q_array(1) <= FIFO_Q1;
sig_q_array(2) <= FIFO_Q2;
sig_q_array(3) <= FIFO_Q3;
sig_rdusedw_array(0) <= FIFO_RDUSEDW0;
sig_rdusedw_array(1) <= FIFO_RDUSEDW1;
sig_rdusedw_array(2) <= FIFO_RDUSEDW2;
sig_rdusedw_array(3) <= FIFO_RDUSEDW3;
-------------------------------------------------------------
--The process judges FIFOs' status and save the results, which
-- is used in "PHY Selection FSM"
-------------------------------------------------------------
process(rst,PM5384_TFCLK)
begin
if rst = '0' then
fifo_flag <= (others => '0');
elsif rising_edge(PM5384_TFCLK) then
for i in 0 to 3 loop
if sig_rdusedw_array(i) > 26 then
fifo_flag(i) <= '1';
else
fifo_flag(i) <= '0';
end if;
end loop;
end if;
end process;
-------------------------------------------------------------
-------------------------------------------------------------
-- "PHY Selection FSM", according to polling feedback results
-- and FIFOs' status,one PHY is selected to transfer data.
-- The FSM is elaborately desinged to run as round-robin.
-------------------------------------------------------------
process(rst, PM5384_TFCLK)
begin
if rst = '0' then
select_addr <= (others => '1');
select_state <= phy1;
select_suc <= '0';
select_flag <= "00";
sig_index <= 0;
elsif rising_edge(PM5384_TFCLK) then
case select_state is
when idle =>
if select_stop = '0' then
select_suc <= '0';
case select_flag is
when "00" =>
select_state <= phy2;
when "01" =>
select_state <= phy3;
when "10" =>
select_state <= phy4;
when "11" =>
select_state <= phy1;
when others =>
select_state <= phy1;
end case;
else
select_suc <= '1';
select_state <= idle;
end if;
when phy1 =>
if phy_status(0) = '1' and fifo_flag(0) = '1' then
select_addr <= PollAddr_S;
select_suc <= '1';
select_flag <= "00";
sig_index <= 0;
select_state<= wait0;
else
select_suc <= '0';
select_state<= phy2;
end if;
when phy2 =>
if phy_status(1) = '1' and fifo_flag(1) = '1' then
select_addr <= PollAddr_S + 1;
select_suc <= '1';
select_flag <= "01";
sig_index <= 1;
select_state<= wait0;
else
select_suc <= '0';
select_state<= phy3;
end if;
when phy3 =>
if phy_status(2) = '1' and fifo_flag(2) = '1' then
select_addr <= PollAddr_S + 2;
select_suc <= '1';
select_flag <= "10";
sig_index <= 2;
select_state<= wait0;
else
select_suc <= '0';
select_state<= phy4;
end if;
when phy4 =>
if phy_status(3) = '1' and fifo_flag(3) = '1' then
select_addr <= PollAddr_E;
select_suc <= '1';
select_flag <= "11";
sig_index <= 3;
select_state<= wait0;
else
select_suc <= '0';
select_state<= phy1;
end if;
when wait0 =>
select_state <= idle;
when others =>
select_addr <= (others => '1');
select_state <= phy1;
select_suc <= '0';
select_flag <= "00";
sig_index <= 0;
end case;
end if;
end process;
-------------------------------------------------------------
polling_and_tx:process(PM5384_TFCLK, RST)
variable var_counter : integer range 0 to 31;
variable var_wait : integer range 0 to 63;
-- variable phy_status : std_logic_vector(3 downto 0);
begin
if RST = '0' then
FIFO_RDREQ <= (others => '0');
PM5384_TDATA <= (others => 'Z');
PM5384_TPRTY <= '0';
PM5384_TENB <= '1';
PM5384_TSOC <= '0';
var_counter := 0;
sig_pm5384_taddr <= PollAddr_S;
sig_addr_keep <= (others => '0');
phy_status <= (others => '0');
sel_addr <= (others => '0');
poll_flag <= '1';
select_stop <= '0';
sig_index0 <= 0;
tx_sm <= sm_en;
TST_SM <= "111";
elsif rising_edge(PM5384_TFCLK) then
PM5384_TSOC <= '0' after 0 ns;
FIFO_RDREQ <= (others => '0')after 0 ns;
PM5384_TENB <= '1'after 0 ns;
case tx_sm is
when sm_en =>
PM5384_TENB <= '1'after 0 ns;
PM5384_TSOC <= '0'after 0 ns;
PM5384_TDATA <= (others => 'Z')after 0 ns;
PM5384_TADDR <= (others => 'Z')after 0 ns;
if MODULE_EN = '1' then
var_counter := 0;
sig_pm5384_taddr <= PollAddr_S after 0 ns;
sig_addr_keep <= (others => '0')after 0 ns;
var_wait := 0;
tx_sm <= sm_wait after 0 ns;
TST_SM <= "000";
else
tx_sm <= sm_en after 0 ns;
TST_SM <= "111" after 0 ns;
end if;
when sm_wait =>
if var_wait < 63 then
PM5384_TENB <= '1' after 0 ns;
PM5384_TSOC <= '0' after 0 ns;
PM5384_TDATA <= (others => 'Z') after 0 ns;
PM5384_TADDR <= (others => 'Z') after 0 ns;
var_wait := var_wait + 1;
tx_sm <= sm_wait after 0 ns;
TST_SM <= "110" after 0 ns;
else
PM5384_TENB <= '1' after 0 ns;
PM5384_TSOC <= '0';
PM5384_TDATA <= (others => 'Z') after 0 ns;
PM5384_TADDR <= (others => '1') after 0 ns;
var_wait := 63;
tx_sm <= sm_s0 after 0 ns;
TST_SM <= "000" after 0 ns;
end if;
when sm_s0 => -- send valid addr
poll_flag <= '1';
var_counter := 0;
PM5384_TDATA <= (others => 'Z');
if select_suc = '1' then
PM5384_TADDR <= select_addr;
sel_addr <= select_addr;
phy_status(sig_index) <= '0';
sig_index0 <= sig_index;
select_stop <= '0';
tx_sm <= sm_t2;
else
select_stop <= '0';
phy_status(conv_integer(sig_addr_keep)) <= PM5384_TCA;
if sig_pm5384_taddr < (PollAddr_E + 1) then
PM5384_TADDR <= sig_pm5384_taddr after 0 ns;
sig_addr_keep <= sig_pm5384_taddr - PollAddr_S after 0 ns;
sig_pm5384_taddr <= sig_pm5384_taddr + '1' after 0 ns;
else
PM5384_TADDR <= PollAddr_S after 0 ns;
sig_addr_keep <= (others => '0') after 0 ns;
sig_pm5384_taddr <= PollAddr_S + '1' after 0 ns;
end if;
tx_sm <= sm_s1 after 0 ns;
TST_SM <= "001" after 0 ns;
end if;
when sm_s1 =>
if select_suc = '1' then
select_stop <= '1';
else
select_stop <='0';
end if;
PM5384_TADDR <= (others => '1') after 0 ns;
tx_sm <= sm_s0 after 0 ns;
TST_SM <= "000" after 0 ns;
when sm_t2 =>
PM5384_TADDR <= (others => '1') after 0 ns;
tx_sm <= sm_t after 0 ns;
TST_SM <= "000" after 0 ns;
when sm_t =>
if PM5384_TCA = '1' then
PM5384_TADDR <= (others => '1'); --sel_addr
FIFO_RDREQ(sig_index0) <= '1' after 0 ns;
tx_sm <= sm_t1;
else
tx_sm <= sm_s0;
-- TST_SM <= "101" after 0 ns;
end if;
when sm_t1 =>
if select_suc = '1' then
select_stop <= '1';
else
select_stop <='0';
end if;
FIFO_RDREQ(sig_index0) <= '1' after 0 ns;
PM5384_TADDR <= sel_addr after 0 ns;
tx_sm <= sm_s2 after 0 ns;
when sm_s2 => -- send 1st word
if select_suc = '1' then
select_stop <= '1';
else
select_stop <='0';
end if;
var_counter := 0;
pm5384_TADDR <= (others => '1') after 0 ns;
FIFO_RDREQ(sig_index0) <= '1' after 0 ns;
PM5384_TSOC <= '1' after 0 ns;
PM5384_TENB <= '0' after 0 ns;
PM5384_TDATA <= sig_q_array(sig_index0) after 0 ns;
var_counter := var_counter + 1;
tx_sm <= sm_s4 after 0 ns;
TST_SM <= "100" after 0 ns;
when sm_s4 =>
if select_suc = '1' then
select_stop <= '1';
else
select_stop <='0';
end if;
if poll_flag = '0' then
PM5384_TADDR <= (others => '1') after 0 ns;
poll_flag <= not poll_flag;
else
phy_status(conv_integer(sig_addr_keep)) <= PM5384_TCA;
if sig_pm5384_taddr < (PollAddr_E + 1) then
PM5384_TADDR <= sig_pm5384_taddr after 0 ns;
sig_addr_keep <= sig_pm5384_taddr - PollAddr_S after 0 ns;
sig_pm5384_taddr <= sig_pm5384_taddr + '1' after 0 ns;
else
PM5384_TADDR <= PollAddr_S after 0 ns;
sig_addr_keep <= (others => '0') after 0 ns;
sig_pm5384_taddr <= PollAddr_S + '1' after 0 ns;
end if;
poll_flag <= not poll_flag;
end if;
if var_counter < 27 then
if var_counter > 24 then
FIFO_RDREQ(sig_index0) <= '0' after 0 ns;
else
if sig_rdusedw_array(sig_index0) > 2 then
FIFO_RDREQ(sig_index0) <= '1' after 0 ns;
else
FIFO_RDREQ(sig_index0) <= '0' after 0 ns;
tx_sm <= sm_s0 after 0 ns;
end if;
end if;
PM5384_TDATA <= sig_q_array(sig_index0) after 0 ns;
PM5384_TENB <= '0' after 0 ns;
PM5384_TSOC <= '0' after 0 ns;
var_counter := var_counter + 1;
tx_sm <= sm_s4 after 0 ns;
TST_SM <= "100" after 0 ns;
else
FIFO_RDREQ(sig_index0) <= '0' after 0 ns;
PM5384_TDATA <= (others => 'Z') after 0 ns;
var_counter := 0;
PM5384_TSOC <= '0' after 0 ns;
PM5384_TENB <= '1' after 0 ns;
tx_sm <= sm_s0 after 0 ns;
TST_SM <= "000" after 0 ns;
end if;
when others =>
FIFO_RDREQ <= (others => '0');
PM5384_TDATA <= (others => 'Z');
PM5384_TPRTY <= '0';
PM5384_TENB <= '1';
PM5384_TSOC <= '0';
var_counter := 0;
sig_pm5384_taddr <= PollAddr_S;
sig_addr_keep <= (others => '0');
phy_status <= (others => '0');
sel_addr <= (others => '0');
poll_flag <= '1';
select_stop <= '0';
sig_index0 <= 0;
tx_sm <= sm_en;
TST_SM <= "111";
end case;
end if;
end process polling_and_tx;
end bhv;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?