-- -- Opcode Block SINK -- -- used to capture data to a RAM. -- -- -- Matt Warren 2013 -- -- change log -- 2013-10-24 birthday! -- 2014-07-10 Starts walking ... -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library utils; use utils.pkg_types.all; library hsio; use hsio.pkg_core_globals.all; library locallink; entity ocb_sink is port( -- oc rx interface oc_valid_i : in std_logic; oc_data_i : in slv16; oc_dack_no : out std_logic; -- locallink tx interface lls_o : out t_llsrc; lld_i : in std_logic; -- payload functions sigs_i : in std_logic_vector (15 downto 0); sink_go_i : in std_logic; --reg_sk_ctl_i : in std_logic_vector (15 downto 0); --sk_stat_o : out std_logic_vector (7 downto 0); --sk_addr_o : out std_logic_vector (15 downto 0); -- infrastructure s40 : in std_logic; clk : in std_logic; rst : in std_logic ); -- Declarations end ocb_sink; architecture rtl of ocb_sink is component cg_bram_8kx16 port ( clka : in std_logic; wea : in std_logic_vector(0 downto 0); addra : in std_logic_vector(12 downto 0); dina : in std_logic_vector(15 downto 0); douta : out std_logic_vector(15 downto 0) ); end component; component ll_ack_gen port ( -- input interface opcode_i : in slv16; ocseq_i : in slv16; ocsize_i : in slv16; payload_i : in slv16; send_i : in std_logic; busy_o : out std_logic; -- locallink tx interface lls_o : out t_llsrc; lld_i : in std_logic; -- infrastucture clk : in std_logic; rst : in std_logic ); end component; signal ack_busy : std_logic; signal ack_send : std_logic; constant RAM_AD_WIDTH : integer := 13; signal sram_dout : slv16; signal sram_din : slv16; signal sram_we : std_logic; signal sram_we00 : std_logic_vector(0 downto 0); signal sram_ad : std_logic_vector(RAM_AD_WIDTH-1 downto 0); constant I_WCOUNT_MAX : integer := (2**RAM_AD_WIDTH-1); constant I_WCOUNT_MAX_MINUS1 : integer := (I_WCOUNT_MAX-1); constant WCOUNT_MAX : std_logic_vector(RAM_AD_WIDTH-1 downto 0) := conv_std_logic_vector(I_WCOUNT_MAX, RAM_AD_WIDTH); constant WCOUNT_MAX_MINUS1 : std_logic_vector(RAM_AD_WIDTH-1 downto 0) := conv_std_logic_vector(I_WCOUNT_MAX_MINUS1, RAM_AD_WIDTH); signal wcount : std_logic_vector(RAM_AD_WIDTH-1 downto 0); signal wcount_en : std_logic; signal wcount_clr : std_logic; signal wcount_load : std_logic; signal tx_opcode : slv16; signal tx_payload : slv16; signal sk_running : std_logic; signal sk_ready : std_logic; signal ocseq : std_logic_vector(15 downto 0); signal seq_inc : std_logic; --signal end_addr : std_logic_vector(12 downto 0); --signal cyclic_en : std_logic; type states is ( SinkStart, SinkRun, SinkDone, SendHeader, SendPayload, SendDone, Done, Idle ); signal state, nstate : states; begin --sk_stat_o <= "000000" & sk_running & sk_ready; --sk_addr_o <= conv_std_logic_vector(wcount, 16); --end_addr <= reg_sk_ctl_i(12 downto 0); --cyclic_en <= reg_sk_ctl_i(B_SK_CYCLIC_EN); -- State Machine -------------------------------------------------------- prc_sync_part : process (clk) begin if rising_edge(clk) then if (rst = '1') then state <= Idle; else state <= nstate; end if; end if; end process; prc_async_machine : process (sink_go_i, wcount, s40, ack_busy, state ) begin -- defaults nstate <= Idle; sram_we <= '0'; wcount_clr <= '0'; wcount_en <= '0'; sk_running <= '1'; sk_ready <= '0'; seq_inc <= '0'; case state is ------------------------------------------------------------- when Idle => nstate <= Idle; sk_running <= '0'; oc_dack_no <= 'Z'; if (sink_go_i = '1') then nstate <= SinkStart; end if; ------------------------------------------------------------------ -- Fill RAM ------------------------------------------------------------------ when SinkStart => -- align with BCO nstate <= SinkStart; wcount_clr <= '1'; if (s40 = '0') then nstate <= SinkRun; end if; when SinkRun => nstate <= SinkRun; sram_we <= '1'; wcount_en <= '1'; if (wcount = WCOUNT_MAX_MINUS1) then nstate <= SinkDone; end if; when SinkDone => wcount_clr <= '1'; nstate <= SendHeader; ---------------------------------------------------------------- ---------------------------------------------------------------- when SendHeader => nstate <= SendHeader; ack_send <= '1'; if (ack_busy = '0') then -- if ack_send=1, ack_busy signals start of data transfer (this is advanced mode) nstate <= SendPayload; end if; when SendPayload => nstate <= SendPayload; ack_send <= '1'; wcount_en <= '1'; if (wcount(10 downto 0) = ("11" & x"ffe")) then nstate <= SendDone; end if; when SendDone => nstate <= SendDone; if (ack_busy = '0') then seq_inc <= '1'; if (wcount(13 downto 11) = "111") then nstate <= Done; else nstate <= SendHeader; end if; end if; --========================================================================= when Done => nstate <= Idle; end case; end process; ----------------------------------------------------------- -- Ack Interface prc_seq_gen : process (clk) begin if rising_edge(clk) then if (rst = '1') then ocseq <= x"0000"; else if (seq_inc = '1') then ocseq <= ocseq + '1'; end if; end if; end if; end process; ocbstatrd_ack : ll_ack_gen port map ( opcode_i => OC_SINK_DATA, ocseq_i => ocseq, ocsize_i => x"0400", payload_i => sram_dout, send_i => ack_send, busy_o => ack_busy, lls_o => lls_o, lld_i => lld_i, clk => clk, rst => rst ); --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--== --== -------------------------------------------------------------------- prc_counts : process (clk) begin if rising_edge(clk) then if (rst = '1') then wcount <= (others => '0'); else if (wcount_clr = '1') then wcount <= (others => '0'); elsif (wcount_en = '1') and (wcount < WCOUNT_MAX) then wcount <= wcount + '1'; end if; end if; end if; end process; sram_ad <= wcount; sram_we00 <= "1" when sram_we = '1' else "0"; sram_din <= sigs_i; inst_sram : cg_bram_8kx16 port map ( clka => clk, wea => sram_we00, addra => sram_ad, dina => sram_din, douta => sram_dout ); ------------------------------------------------------------------------------------------------- end architecture;