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 + -
显示快捷键?