OpenCores
URL https://opencores.org/ocsvn/pif2wb/pif2wb/trunk

Subversion Repositories pif2wb

[/] [pif2wb/] [trunk/] [vhdl/] [pif2wb.vhd] - Rev 12

Go to most recent revision | Compare with Previous | Blame | View Log

------------------------------------------------------------------------------
-- Title       : PIF2WB
-- Project    : Bridge PIF to WISHBONE / WISHBONE to PIF
-------------------------------------------------------------------------------
-- File       : PIF2WB.vhd
-- Author     : Edoardo Paone, Paolo Motto, Sergio Tota, Mario Casu
--              {sergio.tota,mario.casu}@polito.it
--              http://vlsilab.polito.it
-- Company    : Politecnico of Torino, VLSI-Lab, Dipartimento di Elettronica,
--              Corso Duca degli Abruzzi 24, 10129 Torino, Italy
-- Last update: 2007/08/01
-- Platform   : 
-------------------------------------------------------------------------------
-- Description: This bridge interfaces the Tensilica (www.tensilica.com) proprietary
--              PIF bus protocol with the OpenCores WishBone. It currently supports
--              a master PIF and a slave WB. Single-cycle as well burst transfers
--              are possible.
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author          Description
-- 2007/04/18  1.0      Edoardo         Created
-- 2007/07/18  1.1      Paolo Motto     2nd Revision
-- 2007/08/01  1.2      Sergio Tota     3rd Revision
-------------------------------------------------------------------------------
 
-- I have replaced all undefined signals with the low value '0'
-- BTE_O, in case of burst transfer, must always be "00", because this bridge supports
-- only linear incremental burst mode
-- State :
-- IDLE
-- SR    : Single Read
-- BR    : Block Read
-- SW    : Single Write
-- BW    : Block Write
-- R_ACK : Response to ACK_I in Block Read
-- W_ACK : Response to ACK_I in Block Write
 
 
library ieee;
use ieee.std_logic_1164.all;
 
entity PIF2WB is
 
  generic (
    constant DATA_SIZE_PIF : integer := 32;  -- this value specifies the data bus PIF parallelism
    constant DATA_SIZE_WB  : integer := 32;  -- this value specifies the data bus Wishbone parallelism    
    constant ADRS_SIZE     : integer := 32;  -- this value specifies the address bus length
    constant CNTL_PIF      : integer := 8;   -- The PIF CNTL vector size
    constant MSB_PIF       : integer := 31;  -- The PIF most significant bit
    constant LSB_PIF       : integer := 0;   -- The PIF least significant bit 
    constant MSB_WB        : integer := 31;  -- The Wishbone most significant bit
    constant LSB_WB        : integer := 0;   -- The Wishbone least significant bit
    constant ADRS_BITS	   : integer := 4;
    constant ADRS_RANGE    : integer := 8);
 
 
  port (
 
    CLK     : in std_logic;             -- the clock signal
    RST     : in std_logic;             -- the syncronus reset signal
 
 
    -- PIF signals
 
    PIReqVALID  : in  std_logic;
                                        -- Indicates that there is a valid request
    PIReqCNTL   : in  std_logic_vector(CNTL_PIF-1 downto 0);
                                        -- Encodes the data, size and last transfer information for requests
    PIReqADRS   : in  std_logic_vector(ADRS_SIZE-1 downto 0);
                                        -- Request address
    PIReqDATA   : in  std_logic_vector(DATA_SIZE_PIF-1 downto 0);
                                        -- Data used by requests that require data
    PIReqDataBE : in  std_logic_vector(DATA_SIZE_PIF/8-1 downto 0);
                                        -- Indicates valid bytes lanes of PIReqDATA
    POReqRDY    : out std_logic;
                                        -- Indicates that the slave is ready to accept requests
    PORespVALID : out std_logic;
                                        -- Indicates that there is a valid response
    PORespCNTL  : out std_logic_vector(CNTL_PIF-1 downto 0);
                                        -- Encodes the response type and any error
    PORespDATA  : out std_logic_vector(DATA_SIZE_PIF-1 downto 0);
                                        --Response data
    PIRespRDY   : in  std_logic;
                                        -- Indicates that the master is ready to accept responses
 
    -- WISHBONE signals
 
    ACK_I : in  std_logic;              -- The acknowledge input
    DAT_I : in  std_logic_vector(DATA_SIZE_WB-1 downto 0);
                                        -- The data input array
    ERR_I : in  std_logic;              -- Incates address or data error in transaction
    ADR_O : out std_logic_vector(ADRS_SIZE-1 downto 0);
                                        -- The address data output array
    DAT_O : out std_logic_vector(DATA_SIZE_WB-1 downto 0);
                                        -- The data output array
    CYC_O : out std_logic;              -- The cycle output
    SEL_O : out std_logic_vector(DATA_SIZE_WB/8-1 downto 0);
                                        -- The select output array
    STB_O : out std_logic;              -- The strobe output
    WE_O  : out std_logic;              -- The write enable output
    BTE_O : out std_logic_vector(1 downto 0);
                                        -- Indicates the burst length
    CTI_O : out std_logic_vector(2 downto 0) );
                                        -- Indicates the bus cycle type
end PIF2WB;
 
 
architecture PIF2WB_3process of PIF2WB is
 
  component Counter is
  	  generic (
  	  	constant DATA_SIZE_WB :     integer := 32;
    		constant ADRS_SIZE    :     integer := 32 );  -- Address bus length
	  port (
		CLK        : in  std_logic;
		RST        : in  std_logic;
		LOAD_ADDR  : in  std_logic;
		GO_UP      : in  std_logic;
		ADR_INIT   : in  std_logic_vector(ADRS_SIZE-1 downto 0);
		ADR_CNTR   : out std_logic_vector(ADRS_SIZE-1 downto 0);
		N_TRANSFER : out integer range 0 to 15);
  end component;
 
  component AdrDec is
  	  generic (
    		constant ADRS_SIZE    :     integer := 32;
    		constant ADRS_BITS    :     integer := 4;
    		constant ADRS_RANGE   :     integer := 8 );
	  port (
		AdrIn                 : in  std_logic_vector(ADRS_SIZE-1 downto ADRS_SIZE-ADRS_BITS);
    		AdrValid 	      : out std_logic);
  end component;
 
  component sel_reg is
		port (
				clk   : in std_logic;
				rst   : in std_logic;
				En    : in std_logic;
				sel_i : in  std_logic_vector (3 downto 0);
				sel_o : out std_logic_vector (3 downto 0)
				);
  end component;
 
  component tran_reg is
		port (
				clk   : in std_logic;
				rst   : in std_logic;
				En    : in std_logic;
				Num_i : in  integer range 0 to 15;
				Num_o : out integer range 0 to 15
				);
  end component;
 
  type state_type is (IDLE, SR, BR, SW, BW, R_ACK, W_ACK);
 
  signal state, next_state : state_type;
  signal N_TRANSFER          : integer range 0 to 15;
  signal TOT_TRANSFER_I      : integer range 0 to 15;
  signal TOT_TRANSFER_O      : integer range 0 to 15;
 
  -- Signals used by Counter
  signal LOAD_ADDR : std_logic;
  signal GO_UP     : std_logic;
 
  -- Signals used by Registers and Address Comparator
  signal AddressValid : std_logic;
  signal Enable       : std_logic;
 
 
begin
 
  Dec : AdrDec
	port map (
		AdrIn 	 => PIReqADRS (ADRS_SIZE-1 downto ADRS_SIZE-ADRS_BITS),
		AdrValid => AddressValid);
 
  reg0 : sel_reg
   	port map (
		clk 	=> clk,
		rst 	=> rst,
		En 	=> Enable,
		sel_i   => PIReqDataBE,
		sel_o   => SEL_O);
 
  reg1 : tran_reg
   	port map (
		clk 	=> clk,
		rst 	=> rst,
		En 	=> Enable,
		Num_i   => TOT_TRANSFER_I,
		Num_o   => TOT_TRANSFER_O);
 
  -- Counter used in burst mode
  Counter_Burst_Transfer : COUNTER
    	port map( CLK, RST, LOAD_ADDR, GO_UP, PIReqADRS, ADR_O, N_TRANSFER);
 
  -- purpose: every clock cycle updates the signals
  -- type   : sequential
  -- inputs : CLK, RST
  State_Register : process (CLK, RST)
  begin  -- process State_Register
    if  RST = '1' then
      state   <= IDLE;
    elsif CLK'event and CLK = '1' then  -- rising clock edge
      state <= next_state;
    end if;
  end process State_Register;
 
  -- purpose: It determines which will be the next state
  -- type   : combinational
  -- inputs : state, PIReqVALID, PIRespRDY, ACK_I, PIReqCNTL, N_TRANSFER, TOT_TRANSFER_O
  -- outputs: next_state
  Next_State_Function : process (state, PIReqVALID, PIRespRDY, ACK_I, PIReqCNTL, N_TRANSFER, TOT_TRANSFER_O, AddressValid)
  begin  -- process Next_State_Function
    case state is
 
      when IDLE =>
        if(PIReqVALID = '1' and ACK_I = '0' and AddressValid = '1') then  -- ACK_I=0 means POReqRDY='1'
          if(PIReqCNTL(7) = '0' and PIReqCNTL(4) = '0') then   
            	next_state <= SR;	-- single read cycle			
          elsif(PIReqCNTL(7) = '0' and PIReqCNTL(4) = '1') then                    
           	next_state <= BR;	-- burst read cycle
	  elsif(PIReqCNTL(7) = '1' and PIReqCNTL(4) = '0') then
		next_state <= SW;	-- single write cycle
	  elsif(PIReqCNTL(7) = '1' and PIReqCNTL(4) = '1') then
		next_state <= BW;	-- burst write cycle
	  else
		next_state <=  IDLE;
          end if;
	else
		next_state <= IDLE;
        end if;
 
      when SR =>
	if(ACK_I = '1' and PIRespRDY = '1') then
            next_state <= IDLE;
        else                          
            next_state <= SR;
        end if;
 
      when BR =>
	if (ACK_I = '1' and PIRespRDY = '1') then
	    	next_state <= R_ACK; 
	else
		next_state <= BR;
     end if;
 
      when SW =>
	if(ACK_I = '1' and PIRespRDY = '1') then
            next_state <= IDLE;
        else                          
            next_state <= SW;
        end if;
 
      when BW =>
	if (ACK_I = '1' and PIRespRDY = '1') then
	    	next_state <= W_ACK; 
	else
		next_state <= BW;
     end if;
 
      when R_ACK =>
	if (ACK_I = '0') then
		if N_TRANSFER = TOT_TRANSFER_O then
			next_state <= IDLE;
		else
			next_state <= BR;
		end if;
	else
		next_state <= R_ACK;
	end if;
 
      when W_ACK =>
	if (ACK_I = '0') then
		if (N_TRANSFER = TOT_TRANSFER_O  and  PIReqCNTL(0) = '1') then
			next_state <= IDLE;
		else
			next_state <= BW;
		end if;
	else
		next_state <= W_ACK;
	end if;
 
      when others =>
	next_state <= IDLE;
 
     end case;
  end process Next_State_Function;
 
  -- purpose: It assigns the correct values to output signals
  -- type   : combinational
  -- inputs : state, N_TRANSFER_O, PIReqCNTL, PIReqDATA, DAT_I, GO_UP, ERR_I
  -- outputs: 
  Output_Function : process (state, N_TRANSFER, TOT_TRANSFER_O, PIReqCNTL, PIReqDATA, DAT_I, ERR_I, ACK_I, DAT_I)
  begin  -- process Output_Function
 
    LOAD_ADDR 					<= '0';
    Enable    					<= '0';
    GO_UP					<= '0';
 
    BTE_O     					<= "00";
    DAT_O					<= (others => 'Z');
    CYC_O					<= '0';
    STB_O					<= '0';
    WE_O					<= '0';
    CTI_O					<= (others => '0');
 
    PORespVALID             			<= ACK_I;
    POReqRDY 					<= '1';
    PORespDATA					<= (others => 'Z');
    PORespCNTL (7 downto 3)			<= (others => '0');
    PORespCNTL (0)				<= '0';
 
    if ERR_I = '1' then
      PORespCNTL(2 downto 1) 			<= "11";
    else
      PORespCNTL(2 downto 1) 			<= "00";
    end if;
 
    case state is
      when IDLE =>
	Enable 				   	<= '1';
        LOAD_ADDR              		   	<= '1';
        CYC_O                  		   	<= '0';
        STB_O                  		   	<= '0';
        DAT_O                  		   	<= (others => 'Z');
        WE_O                   		   	<= '0';
        CTI_O                  		   	<= (others => '0');
        PORespCNTL(7 downto 3) 		   	<= "00000";
        PORespCNTL(0)          		   	<= '0';
        PORespDATA             		   	<= (others => 'Z');
 
	case PIReqCNTL(2 downto 1) is
      		when "00"   =>
        		TOT_TRANSFER_I 		<= 1;
      		when "01"   =>
        		TOT_TRANSFER_I 		<= 3;
      		when "10"   =>
        		TOT_TRANSFER_I 		<= 7;
      		when "11"   =>
        		TOT_TRANSFER_I 		<= 15;
      		when others =>
        		TOT_TRANSFER_I 		<= 0;
    	end case;
 
     when SR =>
	CYC_O   	       		   	<= '1';
   	STB_O                  		   	<= '1';
   	CTI_O                  		   	<= (others => '0');               -- single transfer
   	WE_O    	       		   	<= '0';
	DAT_O                  		   	<= (others => 'Z');
	PORespDATA(MSB_PIF downto LSB_PIF) 	<= DAT_I(MSB_WB downto LSB_WB);
	PORespCNTL(7 downto 3) 		   	<= "00000";
	PORespCNTL(0)  	        		<= '1';
 
     when BR =>
	CYC_O   	       		   	<= '1';
   	STB_O                  	 	   	<= '1';
	WE_O    	       		  	<= '0';
	CTI_O                     	   	<= "010";
	DAT_O                         		<= (others => 'Z');
   	PORespDATA(MSB_PIF downto LSB_PIF) 	<= DAT_I(MSB_WB downto LSB_WB);
	PORespCNTL(7 downto 3)        		<= "00000";
        if (N_TRANSFER = TOT_TRANSFER_O) then 
        	PORespCNTL(0)           	<= '1';
		CTI_O                      	<= "111";
	else
		PORespCNTL(0)             	<= '0';
		CTI_O                      	<= "010";
	end if;
 
     when SW =>
	CYC_O                       	   	<= '1';
        STB_O                       	   	<= '1';        
        CTI_O                       	   	<= (others => '0');  		-- single transfer
	WE_O                        	   	<= '1';
	DAT_O(MSB_WB downto LSB_WB) 	   	<= PIReqDATA(MSB_PIF downto LSB_PIF);
	PORespDATA                         	<= (others => 'Z');
	PORespCNTL(7 downto 3)             	<= "00000";
	PORespCNTL(0)			   	<= '1';
 
     when BW =>
	CYC_O   	       		   	<= '1';
        STB_O                  	   	   	<= '1';
	WE_O           	        	   	<= '1';
	CTI_O                       	   	<= "010";
	DAT_O(MSB_WB downto LSB_WB)        	<= PIReqDATA(MSB_PIF downto LSB_PIF);
	PORespDATA                         	<= (others => 'Z');
	PORespCNTL(7 downto 3)             	<= "00000";
	if (N_TRANSFER = TOT_TRANSFER_O) then 
        	PORespCNTL(0)             	<= '1';
		CTI_O                           <= "111";
	else
		PORespCNTL(0)             	<= '0';
		CTI_O                           <= "010";
	end if;
 
     when R_ACK => 
	GO_UP     				<= '1';
        STB_O                              	<= '0';
	WE_O           	                   	<= '0';
	CTI_O                              	<= "010";
	DAT_O                              	<= (others => 'Z');
        PORespDATA(MSB_PIF downto LSB_PIF) 	<= DAT_I(MSB_WB downto LSB_WB);
	PORespCNTL(7 downto 3)             	<= "00000";
        PORespCNTL(0)             	   	<= '0';
	if (N_TRANSFER = TOT_TRANSFER_O) then 
        	PORespCNTL(0)             	<= '1';
		CTI_O                           <= "111";
		CYC_O   	                <= '0';
	else
		PORespCNTL(0)             	<= '0';
		CTI_O                           <= "010";
		CYC_O   	                <= '1';
	end if;
 
     when W_ACK => 
	GO_UP     			   	<= '1';
        STB_O                              	<= '0';
	CTI_O                  	    	   	<= "010";
	DAT_O(MSB_WB downto LSB_WB) 	   	<= PIReqDATA(MSB_PIF downto LSB_PIF);
	PORespDATA                         	<= (others => 'Z');
        PORespCNTL(7 downto 3)             	<= "00000";
	if (N_TRANSFER = TOT_TRANSFER_O) then 
        	PORespCNTL(0)             	<= '1';
		CTI_O                           <= "111";
		CYC_O   	                <= '0';
		WE_O           	           	<= '0';
	else
		PORespCNTL(0)             	<= '0';
		CTI_O                           <= "010";
		CYC_O   	                <= '1';
		WE_O           	           	<= '1';
	end if;
 
     end case;
  end process Output_Function;
 
end PIF2WB_3process;
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.