-- -- Opcode Block RAWCOM -- -- Send payload as COM data -- -- An example of an opcode that only sends an Ack as response -- (using ll_ack_gen) -- -- -- change log -- 2012-05-15 syncd ocrawcom_start -- 2012-05-24 added OC_COM_PATTERN 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_rawcom 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 abc_com_o : out std_logic; ocrawcom_start_o : out std_logic; pattern_go_i : in std_logic; -- infrastructure strobe40_i : in std_logic; clk : in std_logic; rst : in std_logic ); -- Declarations end ocb_rawcom ; architecture rtl of ocb_rawcom is component cg_dram16x16 port ( a : in std_logic_vector(3 downto 0); d : in std_logic_vector(15 downto 0); clk : in std_logic; we : in std_logic; spo : 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 abc_com : std_logic; signal bitcount40 : integer range 0 to 15; signal bitcount40_set : std_logic; signal ocseq_store_en : std_logic; signal rx_ocseq : slv16; signal ack_busy : std_logic; signal ack_send : std_logic; signal com_start : std_logic; signal com_start_q : std_logic_vector(1 downto 0); signal pattram_data : slv16; signal pattram_we : std_logic; signal pattram_ad : slv4; signal wcount : integer range 0 to 15; signal wcount_en : std_logic; signal wcount_clr : std_logic; type oc_codes is (RAWCOM, COM_PATTERN, INVALID ); signal oc_coded : oc_codes; signal rx_oc_port : slv4; signal rx_oc_coded : oc_codes; signal rx_opcode : slv16; signal rx_opcode0 : slv16; signal oc_data_opcodepl : slv16; signal oc_coded_store_en : std_logic; type states is (Opcode, OCSeq, Size, RawComStart, Serialise, SerialLoad0, SerialLoad1, PatternLoad, PatternWords, PatternStart, PattSerialise, PattSerialLoad0, PattSerialLoad1, SendAck, WaitAckBusy, Idle, WaitOCReady, OCDone ); signal state, nstate : states; begin oc_data_opcodepl <= oc_get_opcodepl(oc_data_i); oc_coded <= RAWCOM when (oc_data_opcodepl = OC_RAWCOM) else COM_PATTERN when (oc_data_opcodepl = OC_COM_PATTERN) else INVALID; -- State Machine -------------------------------------------------------- prc_sync_part : process (clk) begin if rising_edge(clk) then if (rst = '1') then state <= WaitOCReady; else state <= nstate; end if; end if; end process; prc_async_machine : process (oc_valid_i, oc_data_i, oc_coded, pattern_go_i, rx_oc_coded, pattram_data, wcount, bitcount40, strobe40_i, ack_busy, state ) begin -- defaults nstate <= WaitOCReady; oc_dack_no <= '1'; bitcount40_set <= '0'; abc_com <= '0'; ack_send <= '0'; ocseq_store_en <= '0'; com_start <= '0'; oc_coded_store_en <= '0'; pattram_we <= '0'; wcount_clr <= '0'; wcount_en <= '0'; case state is ------------------------------------------------------------- when WaitOCReady => nstate <= WaitOCReady; oc_dack_no <= 'Z'; if (oc_valid_i = '0') then -- wait for OC to be done nstate <= Idle; end if; when Idle => nstate <= Idle; oc_dack_no <= 'Z'; if (pattern_go_i = '1') then nstate <= PatternStart; elsif (oc_valid_i = '1') then if (oc_coded /= INVALID) then -- check for opcode here oc_coded_store_en <= '1'; nstate <= Opcode; else nstate <= WaitOCReady; end if; end if; when Opcode => oc_dack_no <= '0'; nstate <= OCSeq; when OCSeq => oc_dack_no <= '0'; ocseq_store_en <= '1'; nstate <= Size; when Size => oc_dack_no <= '0'; if (rx_oc_coded = RAWCOM) then nstate <= RawComStart; else nstate <= PatternLoad; end if; ------------------------------------------------------------------ -- OC_RAWCOM ------------------------------------------------------------------ when RawComStart => nstate <= RawComStart; bitcount40_set <= '1'; if (strobe40_i = '0') then com_start <= '1'; -- must be sync'd with com nstate <= Serialise; end if; when Serialise => nstate <= Serialise; abc_com <= oc_data_i(bitcount40); if (bitcount40 = 1) and (strobe40_i = '0') then nstate <= SerialLoad0; end if; when SerialLoad0 => -- strobe40 = 1 nstate <= SerialLoad0; abc_com <= oc_data_i(bitcount40); nstate <= SerialLoad1; when SerialLoad1 => --strobe40 = '0' abc_com <= oc_data_i(bitcount40); oc_dack_no <= '0'; if (oc_valid_i = '0') then oc_dack_no <= '1'; -- wait til after ack nstate <= SendAck; else nstate <= Serialise; end if; ------------------------------------------------------------------ -- OC_COM_PATTERN ------------------------------------------------------------------ when PatternLoad => wcount_clr <= '1'; nstate <= PatternWords; when PatternWords => nstate <= PatternWords; wcount_en <= '1'; oc_dack_no <= '0'; pattram_we <= '1'; if (wcount = 15) then nstate <= SendAck; end if; ---------------------------------------------------------------- when PatternStart => nstate <= PatternStart; oc_dack_no <= 'Z'; bitcount40_set <= '1'; wcount_clr <= '1'; if (strobe40_i = '0') then com_start <= '1'; -- must be sync'd with com nstate <= PattSerialise; end if; when PattSerialise => oc_dack_no <= 'Z'; nstate <= PattSerialise; abc_com <= pattram_data(bitcount40); if (bitcount40 = 1) and (strobe40_i = '0') then nstate <= PattSerialLoad0; end if; when PattSerialLoad0 => -- strobe40 = 1 nstate <= PattSerialLoad0; oc_dack_no <= 'Z'; abc_com <= pattram_data(bitcount40); nstate <= PattSerialLoad1; when PattSerialLoad1 => --strobe40 = '0' oc_dack_no <= 'Z'; abc_com <= pattram_data(bitcount40); if (wcount = 15) then nstate <= WaitOCReady; else wcount_en <= '1'; nstate <= PattSerialise; end if; --------------------------------------------------------------- when SendAck => oc_dack_no <= '1'; ack_send <= '1'; nstate <= WaitAckBusy; when WaitAckBusy => oc_dack_no <= '1'; nstate <= WaitAckBusy; if (ack_busy = '0') then nstate <= OCDone; end if; --========================================================================= when OCDone => oc_dack_no <= '0'; -- final oc_dack to release ocbus nstate <= Idle; end case; end process; --------------------------------- prc_clockout : process (clk) begin if rising_edge(clk) then if (rst = '1') then abc_com_o <= '0'; else abc_com_o <= abc_com; end if; end if; end process; -------------------------------------------------------------------- prc_bit_counter40 : process (clk) begin if rising_edge(clk) then if (rst = '1') or (bitcount40_set = '1') then bitcount40 <= 15; else if (strobe40_i = '0') then if (bitcount40 = 0) then bitcount40 <= 15; else bitcount40 <= bitcount40 - 1; end if; end if; end if; end if; end process; -------------------------------------------------------------------- prc_wcount : process (clk) begin if rising_edge(clk) then if (rst = '1') then wcount <= 0; else if (wcount_clr = '1') then wcount <= 0; elsif (wcount_en = '1') and (wcount /= 15) then wcount <= wcount + 1; end if; end if; end if; end process; pattram_ad <= conv_std_logic_vector(wcount, 4); inst_ram : cg_dram16x16 port map ( a => pattram_ad, d => oc_data_i, clk => clk, we => pattram_we, spo => pattram_data ); ----------------------------------------------------------- -- Ack Interface prc_occoded_store : process (clk) begin if rising_edge(clk) then if (oc_coded_store_en = '1') then rx_oc_coded <= oc_coded; rx_oc_port <= oc_get_port(oc_data_i); end if; end if; end process; prc_ocseq_store : process (clk) begin if rising_edge(clk) then if (ocseq_store_en = '1') then rx_ocseq <= oc_data_i; end if; end if; end process; rx_opcode0 <= OC_RAWCOM when (rx_oc_coded = RAWCOM) else OC_COM_PATTERN; rx_opcode <= oc_insert_port(rx_opcode0, rx_oc_port); ocbrawcom_ack : ll_ack_gen port map ( opcode_i => rx_opcode, ocseq_i => rx_ocseq, ocsize_i => x"0002", payload_i => x"acac", send_i => ack_send, busy_o => ack_busy, lls_o => lls_o, lld_i => lld_i, clk => clk, rst => rst ); prc_com_start : process (clk) begin if rising_edge(clk) then if (rst = '1') then com_start_q <= (others => '0'); else com_start_q <= com_start_q(0) & com_start; -- sync twice to align with bco and make 25ns pulse end if; end if; end process; --ocrawcom_start_o <= '1' when com_start_q = "11" else '0'; ocrawcom_start_o <= com_start_q(1); end architecture;