initial commit
This commit is contained in:
220
fpga/f2p/f2p_master.vhd
Normal file
220
fpga/f2p/f2p_master.vhd
Normal file
@@ -0,0 +1,220 @@
|
||||
-- ---------------------------------------------------------------
|
||||
-- (2013) Benjamin Krill <benjamin@krll.de>
|
||||
-- ---------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity f2p_master is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
rst_n : in std_logic;
|
||||
debug : out std_logic_vector(7 downto 0);
|
||||
|
||||
-- cypress interface
|
||||
usb_clk : in std_logic;
|
||||
usb_flag_a_i : in std_logic; -- programmable flag
|
||||
usb_flag_b_i : in std_logic; -- full flag
|
||||
usb_flag_c_i : in std_logic; -- empty flag
|
||||
usb_cs_o : out std_logic; -- put to GND, not need for this application
|
||||
usb_oe_o : out std_logic; -- active_low
|
||||
usb_rd_o : out std_logic; -- active_low
|
||||
usb_wr_o : out std_logic; -- active_low
|
||||
usb_pktend_o : out std_logic; -- active_low
|
||||
usb_adr_o : out std_logic_vector(1 downto 0); -- 00 ep2, 01 ep4, 10 ep6, 11 ep8
|
||||
usb_dat_io : inout std_logic_vector(7 downto 0);
|
||||
|
||||
-- write/read pipe
|
||||
wp_wr_i : in std_logic;
|
||||
wp_full_o : out std_logic;
|
||||
wp_eop_i : in std_logic;
|
||||
wp_dat_i : in std_logic_vector(31 downto 0);
|
||||
rp_rd_i : in std_logic;
|
||||
rp_empty_o : out std_logic;
|
||||
rp_dat_o : out std_logic_vector(31 downto 0)
|
||||
);
|
||||
end f2p_master;
|
||||
|
||||
architecture f2p_master of f2p_master is
|
||||
constant EP2 : std_logic_vector(1 downto 0) := "00";
|
||||
constant EP4 : std_logic_vector(1 downto 0) := "01";
|
||||
constant EP6 : std_logic_vector(1 downto 0) := "10";
|
||||
constant EP8 : std_logic_vector(1 downto 0) := "11";
|
||||
signal rst : std_logic;
|
||||
|
||||
type sm_usb_t is (IDLE, RD_ADDRESS, RD_READ, WR_ADDRESS, WR_WRITE);
|
||||
signal sm_usb : sm_usb_t;
|
||||
signal usb_oe : std_logic;
|
||||
signal usb_rd : std_logic;
|
||||
signal usb_wr : std_logic;
|
||||
signal usb_wr_cnt : unsigned(25 downto 0);
|
||||
signal usb_pktend : std_logic;
|
||||
signal usb_dat_out : std_logic_vector(7 downto 0);
|
||||
signal usb_dat_in : std_logic_vector(7 downto 0);
|
||||
|
||||
signal usb_adr : std_logic;
|
||||
signal uftx_din : std_logic_vector(31 downto 0);
|
||||
signal uftx_wren : std_logic;
|
||||
signal uftx_rden : std_logic;
|
||||
signal uftx_dout : std_logic_vector( 7 downto 0);
|
||||
signal uftx_full : std_logic;
|
||||
signal uftx_empty : std_logic;
|
||||
signal ufrx_din : std_logic_vector( 7 downto 0);
|
||||
signal ufrx_wren : std_logic;
|
||||
signal ufrx_rden : std_logic;
|
||||
signal ufrx_dout : std_logic_vector(31 downto 0);
|
||||
signal ufrx_full : std_logic;
|
||||
signal ufrx_empty : std_logic;
|
||||
signal uftxfin_cnt : unsigned(23 downto 0);
|
||||
signal uftxfin_din : std_logic_vector(23 downto 0);
|
||||
signal uftxfin_wren : std_logic;
|
||||
signal uftxfin_rden : std_logic;
|
||||
signal uftxfin_dout : std_logic_vector(23 downto 0);
|
||||
signal uftxfin_full : std_logic;
|
||||
signal uftxfin_empty : std_logic;
|
||||
begin
|
||||
rst <= not rst_n;
|
||||
-- EP2 from host, EP6 to host
|
||||
-- during IDLE monitor EF and read data from fifo
|
||||
usb_adr_o <= EP2 when (usb_adr = '0' or sm_usb = RD_ADDRESS) and sm_usb /= WR_ADDRESS else EP6;
|
||||
usb_cs_o <= '0';
|
||||
usb_oe_o <= not usb_oe;
|
||||
usb_rd_o <= not usb_rd;
|
||||
usb_wr_o <= not usb_wr;
|
||||
usb_pktend_o <= not usb_pktend;
|
||||
|
||||
usb_dat_io <= (others => 'Z') when usb_oe = '1' else usb_dat_out;
|
||||
usb_dat_in <= usb_dat_io when usb_oe = '1' else (others => '0');
|
||||
usb_oe <= '1' when (usb_adr = '0' or sm_usb = RD_ADDRESS) and sm_usb /= WR_ADDRESS else '0';
|
||||
usb_rd <= '1' when sm_usb = RD_READ and usb_flag_c_i = '1' else '0';
|
||||
usb_wr <= '1' when sm_usb = WR_WRITE and usb_flag_b_i = '1' and uftx_empty = '0' else '0';
|
||||
usb_pktend <= '1' when sm_usb = WR_WRITE and uftxfin_empty = '0'
|
||||
and to_integer(usb_wr_cnt(25 downto 2)) = to_integer(unsigned(uftxfin_dout)) else '0';
|
||||
|
||||
process (usb_clk, rst_n)
|
||||
begin
|
||||
if rst_n = '0' then
|
||||
sm_usb <= IDLE;
|
||||
usb_adr <= '0';
|
||||
usb_wr_cnt <= "00" & x"000001";
|
||||
elsif rising_edge(usb_clk) then
|
||||
if usb_pktend = '1' then
|
||||
usb_wr_cnt <= "00" & x"000001";
|
||||
elsif usb_wr = '1' then
|
||||
usb_wr_cnt <= usb_wr_cnt + "1";
|
||||
end if;
|
||||
|
||||
-- EP address switch
|
||||
if sm_usb = RD_ADDRESS then
|
||||
usb_adr <= '0';
|
||||
elsif sm_usb = WR_ADDRESS then
|
||||
usb_adr <= '1';
|
||||
end if;
|
||||
|
||||
case sm_usb is
|
||||
when IDLE =>
|
||||
if uftx_empty = '0' then
|
||||
sm_usb <= WR_ADDRESS;
|
||||
elsif ufrx_full = '0' then
|
||||
sm_usb <= RD_ADDRESS;
|
||||
end if;
|
||||
|
||||
when RD_ADDRESS =>
|
||||
sm_usb <= RD_READ;
|
||||
|
||||
when RD_READ =>
|
||||
sm_usb <= IDLE;
|
||||
if usb_flag_c_i = '1' and ufrx_full = '0' then -- fifo not empty
|
||||
sm_usb <= RD_READ;
|
||||
end if;
|
||||
|
||||
when WR_ADDRESS =>
|
||||
sm_usb <= WR_WRITE;
|
||||
|
||||
when WR_WRITE =>
|
||||
if usb_pktend = '1' then
|
||||
sm_usb <= IDLE;
|
||||
end if;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- --------------------------------------------------------------------
|
||||
-- USB RX FIFO
|
||||
-- --------------------------------------------------------------------
|
||||
rp_dat_o <= ufrx_dout(7 downto 0) & ufrx_dout(15 downto 8) & ufrx_dout(23 downto 16) & ufrx_dout(31 downto 24);
|
||||
rp_empty_o <= ufrx_empty;
|
||||
ufrx_rden <= rp_rd_i;
|
||||
ufrx_din <= usb_dat_in;
|
||||
ufrx_wren <= usb_rd;
|
||||
usb_fifo_rx_0: entity work.usb_fifo_rx
|
||||
port map (
|
||||
rst => rst,
|
||||
|
||||
wr_clk => usb_clk,
|
||||
wr_en => ufrx_wren,
|
||||
din => ufrx_din,
|
||||
full => ufrx_full,
|
||||
|
||||
rd_clk => clk,
|
||||
rd_en => ufrx_rden,
|
||||
dout => ufrx_dout,
|
||||
empty => ufrx_empty
|
||||
);
|
||||
|
||||
-- --------------------------------------------------------------------
|
||||
-- USB TX FIFO
|
||||
-- --------------------------------------------------------------------
|
||||
uftx_din <= wp_dat_i;
|
||||
uftx_wren <= wp_wr_i;
|
||||
wp_full_o <= uftx_full;
|
||||
uftx_rden <= usb_wr;
|
||||
usb_dat_out <= uftx_dout;
|
||||
usb_fifo_tx_0: entity work.usb_fifo_tx
|
||||
port map (
|
||||
rst => rst,
|
||||
|
||||
wr_clk => clk,
|
||||
wr_en => uftx_wren,
|
||||
din => uftx_din,
|
||||
full => uftx_full,
|
||||
|
||||
rd_clk => usb_clk,
|
||||
rd_en => uftx_rden,
|
||||
dout => uftx_dout,
|
||||
empty => uftx_empty
|
||||
);
|
||||
|
||||
process (clk, rst_n)
|
||||
begin
|
||||
if rst_n = '0' then
|
||||
uftxfin_cnt <= x"000001";
|
||||
elsif rising_edge(clk) then
|
||||
if uftxfin_wren = '1' then
|
||||
uftxfin_cnt <= x"000001";
|
||||
elsif wp_wr_i = '1' then
|
||||
uftxfin_cnt <= uftxfin_cnt + "1";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
uftxfin_wren <= wp_wr_i and wp_eop_i and not uftxfin_full;
|
||||
uftxfin_din <= std_logic_vector(uftxfin_cnt);
|
||||
uftxfin_rden <= usb_pktend and not uftxfin_empty;
|
||||
usb_fifo_txfin_0: entity work.usb_fifo_tx_fin
|
||||
port map (
|
||||
rst => rst,
|
||||
|
||||
wr_clk => clk,
|
||||
wr_en => uftxfin_wren,
|
||||
din => uftxfin_din,
|
||||
full => uftxfin_full,
|
||||
|
||||
rd_clk => usb_clk,
|
||||
rd_en => uftxfin_rden,
|
||||
dout => uftxfin_dout,
|
||||
empty => uftxfin_empty
|
||||
);
|
||||
|
||||
end f2p_master;
|
||||
151
fpga/f2p/f2p_strm_top.vhd
Normal file
151
fpga/f2p/f2p_strm_top.vhd
Normal file
@@ -0,0 +1,151 @@
|
||||
-- ---------------------------------------------------------------
|
||||
-- (2013) Benjamin Krill <benjamin@krll.de>
|
||||
-- ---------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use work.strm_package.all;
|
||||
|
||||
entity f2p_strm_top is
|
||||
generic ( STRM_OUT_SLV_CNT : integer := 1 );
|
||||
port (
|
||||
clk : in std_logic;
|
||||
rst_n : in std_logic;
|
||||
debug : out std_logic_vector(7 downto 0);
|
||||
|
||||
-- cypress interface
|
||||
usb_clk : in std_logic;
|
||||
usb_flag_a_i : in std_logic; -- programmable flag
|
||||
usb_flag_b_i : in std_logic; -- full flag
|
||||
usb_flag_c_i : in std_logic; -- empty flag
|
||||
usb_cs_o : out std_logic; -- put to GND, not need for this application
|
||||
usb_oe_o : out std_logic; -- active_low
|
||||
usb_rd_o : out std_logic; -- active_low
|
||||
usb_wr_o : out std_logic; -- active_low
|
||||
usb_pktend_o : out std_logic; -- active_low
|
||||
usb_adr_o : out std_logic_vector(1 downto 0); -- 00 ep2, 01 ep4, 10 ep6, 11 ep8
|
||||
usb_dat_io : inout std_logic_vector(7 downto 0);
|
||||
|
||||
-- streaming bus
|
||||
strm_in_data_o : out std_logic_vector(31 downto 0);
|
||||
strm_in_eop_o : out std_logic;
|
||||
strm_in_en_o : out std_logic;
|
||||
strm_in_busy_i : in std_logic;
|
||||
strm_out_slv_reqs_i : in std_logic_vector(STRM_OUT_SLV_CNT-1 downto 0);
|
||||
strm_out_slv_busy_o : out std_logic_vector(STRM_OUT_SLV_CNT-1 downto 0);
|
||||
strm_out_data_i : in strm_dat_bus_t(STRM_OUT_SLV_CNT-1 downto 0);
|
||||
strm_out_eop_i : in std_logic_vector(STRM_OUT_SLV_CNT-1 downto 0);
|
||||
strm_out_en_i : in std_logic_vector(STRM_OUT_SLV_CNT-1 downto 0)
|
||||
);
|
||||
end f2p_strm_top;
|
||||
|
||||
architecture f2p_strm_top of f2p_strm_top is
|
||||
signal rp_read_cnt : unsigned(23 downto 0);
|
||||
signal strm_data : std_logic_vector(31 downto 0);
|
||||
signal strm_eop : std_logic;
|
||||
signal strm_en : std_logic;
|
||||
|
||||
signal wp_wr : std_logic;
|
||||
signal wp_full : std_logic;
|
||||
signal wp_eop : std_logic;
|
||||
signal wp_dat : std_logic_vector(31 downto 0);
|
||||
signal rp_rd : std_logic;
|
||||
signal rp_empty : std_logic;
|
||||
signal rp_dat : std_logic_vector(31 downto 0);
|
||||
|
||||
signal rrarb_req : std_logic_vector(STRM_OUT_SLV_CNT-1 downto 0);
|
||||
signal rrarb_ack : std_logic;
|
||||
signal rrarb_grant : std_logic_vector(STRM_OUT_SLV_CNT-1 downto 0);
|
||||
signal strm_out_data_mux : strm_dat_bus_t(STRM_OUT_SLV_CNT-1 downto 0);
|
||||
begin
|
||||
strm_in_data_o <= strm_data;
|
||||
strm_in_eop_o <= strm_eop;
|
||||
strm_in_en_o <= strm_en;
|
||||
|
||||
f2p_master_0: entity work.f2p_master
|
||||
port map (
|
||||
clk => clk,
|
||||
rst_n => rst_n,
|
||||
debug => debug,
|
||||
|
||||
-- cypress interface
|
||||
usb_clk => usb_clk,
|
||||
usb_flag_a_i => usb_flag_a_i,
|
||||
usb_flag_b_i => usb_flag_b_i,
|
||||
usb_flag_c_i => usb_flag_c_i,
|
||||
usb_cs_o => usb_cs_o,
|
||||
usb_oe_o => usb_oe_o,
|
||||
usb_rd_o => usb_rd_o,
|
||||
usb_wr_o => usb_wr_o,
|
||||
usb_pktend_o => usb_pktend_o,
|
||||
usb_adr_o => usb_adr_o,
|
||||
usb_dat_io => usb_dat_io,
|
||||
|
||||
-- write/read pipe
|
||||
wp_wr_i => wp_wr,
|
||||
wp_full_o => wp_full,
|
||||
wp_dat_i => wp_dat,
|
||||
wp_eop_i => wp_eop,
|
||||
rp_rd_i => rp_rd,
|
||||
rp_empty_o => rp_empty,
|
||||
rp_dat_o => rp_dat
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------------
|
||||
-- USB FIFO SLAVES
|
||||
-- ------------------------------------------------------------------
|
||||
-- FROM USB
|
||||
rp_rd <= not rp_empty and not strm_in_busy_i;
|
||||
process (clk, rst_n)
|
||||
begin
|
||||
if rst_n = '0' then
|
||||
rp_read_cnt <= (others => '0');
|
||||
strm_data <= (others => '0');
|
||||
strm_en <= '0';
|
||||
strm_eop <= '0';
|
||||
elsif rising_edge(clk) then
|
||||
-- get next packet and stream to slaves
|
||||
if rp_rd = '1' then
|
||||
if rp_read_cnt /= x"000000" then
|
||||
rp_read_cnt <= rp_read_cnt - "1";
|
||||
else
|
||||
rp_read_cnt <= unsigned(rp_dat(STRM_LENGTH_HIGH downto STRM_LENGTH_LOW));
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- stream data
|
||||
strm_en <= '0';
|
||||
strm_eop <= '0';
|
||||
if rp_rd = '1' then
|
||||
strm_en <= '1';
|
||||
strm_data <= rp_dat;
|
||||
if rp_read_cnt = x"000001" then
|
||||
strm_eop <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- TO USB - strm arbiter
|
||||
rrarb_req <= strm_out_slv_reqs_i and not rrarb_grant;
|
||||
rrarb_ack <= '1' when (strm_out_eop_i and rrarb_grant) /= (STRM_OUT_SLV_CNT-1 downto 0 => '0') else '0';
|
||||
rrarb_strm_out_0: entity work.rrarbiter
|
||||
generic map ( CNT => STRM_OUT_SLV_CNT )
|
||||
port map (
|
||||
clk => clk,
|
||||
rst_n => rst_n,
|
||||
req => rrarb_req,
|
||||
ack => rrarb_ack,
|
||||
grant => rrarb_grant
|
||||
);
|
||||
strm_out_slv_busy_o <= not rrarb_grant or (STRM_OUT_SLV_CNT-1 downto 0 => wp_full);
|
||||
|
||||
strm_out_data_mux(0) <= strm_out_data_i(0) and (31 downto 0 => rrarb_grant(0));
|
||||
dc: for I in 1 to STRM_OUT_SLV_CNT-1 generate
|
||||
strm_out_data_mux(I) <= strm_out_data_mux(I-1) or (strm_out_data_i(I) and (31 downto 0 => rrarb_grant(I)));
|
||||
end generate dc;
|
||||
wp_dat <= strm_out_data_mux(STRM_OUT_SLV_CNT-1);
|
||||
wp_wr <= '1' when (strm_out_en_i and rrarb_grant) /= (STRM_OUT_SLV_CNT-1 downto 0 => '0') else '0';
|
||||
wp_eop <= '1' when (strm_out_eop_i and rrarb_grant) /= (STRM_OUT_SLV_CNT-1 downto 0 => '0') else '0';
|
||||
|
||||
end f2p_strm_top;
|
||||
47
fpga/f2p/strm_package.vhd
Normal file
47
fpga/f2p/strm_package.vhd
Normal file
@@ -0,0 +1,47 @@
|
||||
-- ---------------------------------------------------------------
|
||||
-- (2013) Benjamin Krill <benjamin@krll.de>
|
||||
-- ---------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
-- GENERAL PKT FORMAT
|
||||
-- --------------------------------------------------------
|
||||
-- Type (4bit)
|
||||
-- Plength (7bit) data length (0 = 0byte, 0x7f = 127 * 4byte)
|
||||
-- 31 16|15 0
|
||||
-- header |Type ________|___PLenght______|
|
||||
-- data |... type defined data/fields ... |
|
||||
--
|
||||
-- DDR2 WRITE TYPE FORMAT
|
||||
-- --------------------------------------------------------
|
||||
-- header |1 ________ADDR|ESS_____________| -- ADDRESS 4byte aligned
|
||||
-- data | .... data .... |
|
||||
--
|
||||
-- DDR2 READ TYPE FORMAT
|
||||
-- --------------------------------------------------------
|
||||
-- header0 |0 ________ADDR|ESS_____________| -- ADDRESS 4byte aligned
|
||||
-- header1 | |_______SIZE_____| -- SIZE in 4byte to read
|
||||
|
||||
package strm_package is
|
||||
constant STRM_TYPE_HIGH : integer := 31;
|
||||
constant STRM_TYPE_LOW : integer := 28;
|
||||
constant STRM_LENGTH_HIGH : integer := 23;
|
||||
constant STRM_LENGTH_LOW : integer := 0;
|
||||
|
||||
-- SLAVE TYPE IDs
|
||||
constant STRM_TYPE_DDR2 : std_logic_vector(3 downto 0) := "0001";
|
||||
|
||||
-- DDR2
|
||||
constant STRM_DDR2_BUS : integer := 0;
|
||||
constant STRM_DDR2_ADR_HIGH : integer := 27;
|
||||
constant STRM_DDR2_ADR_LOW : integer := 0;
|
||||
constant STRM_DDR2_ACCESS : integer := 31;
|
||||
constant STRM_DDR2_ACC_WRITE : std_logic := '1';
|
||||
constant STRM_DDR2_ACC_READ : std_logic := '0';
|
||||
constant STRM_DDR2_SIZE_HIGH : integer := 23;
|
||||
constant STRM_DDR2_SIZE_LOW : integer := 0;
|
||||
|
||||
-- bus types
|
||||
type strm_dat_bus_t is array(natural range <>) of std_logic_vector(31 downto 0);
|
||||
end package;
|
||||
Reference in New Issue
Block a user