LIBRARY ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; entity REG_FILE is generic ( DATA_WIDTH : integer := 8 ); port ( REG_CLK : in std_logic; --system clock REG_RSTn : in std_logic; --active low reset S_CS : in std_logic; --slave chip select S_RRDY : in std_logic; --slave receive ready REG_CHAN : in std_logic_vector(2 downto 0); --signals from s_spi_reg SPI_DATA_LATCH : in std_logic; --command, address, data was received REG_BYTE_RX : in std_logic; --byte was received REG_COM_IN : in std_logic_vector(DATA_WIDTH-1 downto 0); REG_ADDR1_IN : in std_logic_vector(DATA_WIDTH-1 downto 0); REG_ADDR2_IN : in std_logic_vector(DATA_WIDTH-1 downto 0); REG_DATA1_IN : in std_logic_vector(DATA_WIDTH-1 downto 0); REG_DATA2_IN : in std_logic_vector(DATA_WIDTH-1 downto 0); REG_DATA_OUT : out std_logic_vector(DATA_WIDTH-1 downto 0); --data to s_spi_reg MCP25625_RX0BF : in std_logic; --active low MCP25625_RX1BF : in std_logic; --active low MCP25625_DATA_RDY : out std_logic; MSPI_CS : out std_logic := '1'; MSPI_WR_DATA : out std_logic_vector(DATA_WIDTH-1 downto 0); --write data to SPI MSPI_RD_DATA : in std_logic_vector(DATA_WIDTH-1 downto 0); --read data from SPI MSPI_WR_START_TRIG : out std_logic; MSPI_WR_DONE_CLR : out std_logic; MSPI_WR_DONE : in std_logic ); end REG_FILE; architecture behavior of REG_FILE is constant MAILBOX_COUNT : integer range 0 to 255 := 32; constant DATA_LENGHT : integer range 0 to 255 := 13; constant MAILBOX_SIZE : integer range 0 to 255 := 17; constant MAILBOX_OFFSET : integer := 0; constant MAILBOX_START_ADDR : integer := 0; type StateType is (ST_IDLE, ST_WAIT_DONE, ST_START_RX_DATA, ST_RX_DATA0, ST_RX_DATA, ST_RX_REG_COM, ST_RX_REG_ADDR, ST_RX_REG_DATA, ST_TX_REG_COM, ST_TX_REG_ADDR, ST_TX_REG_DATA, ST_TX_REG_DONE, ST_READ_STATUS_0, ST_READ_STATUS_1, ST_START_TX_DATA, ST_TX_DATA, ST_WAIT_USER_DONE); signal State :StateType; signal NextState :StateType; type can_mailbox is record --can header id : std_logic_vector(31 downto 0); mask : std_logic_vector(31 downto 0); dlc : std_logic_vector(7 downto 0); --can data data0 : std_logic_vector(7 downto 0); data1 : std_logic_vector(7 downto 0); data2 : std_logic_vector(7 downto 0); data3 : std_logic_vector(7 downto 0); data4 : std_logic_vector(7 downto 0); data5 : std_logic_vector(7 downto 0); data6 : std_logic_vector(7 downto 0); data7 : std_logic_vector(7 downto 0); end record; type array_can_mailbox_t is array (0 to MAILBOX_COUNT-1) of can_mailbox; signal can_mailboxes : array_can_mailbox_t; --consider to move variables in its processes shared variable rx_byte_idx : integer range 0 to 8 := 0; shared variable tx_byte_idx : integer range 0 to 8 := 0; shared variable mailbox_idx : integer range 0 to 8 := 0; signal mcp25625_reg_addr : std_logic_vector(7 downto 0); signal mcp25625_reg_data : std_logic_vector(7 downto 0); signal mcp25625_status_reg : std_logic_vector(7 downto 0); type packet_t is array (0 to DATA_LENGHT-1) of std_logic_vector(7 downto 0); signal temp_rx_mailbox :packet_t; signal tx_buf_sel_reg : std_logic_vector(2 downto 0); --variable timeout : integer := 0; signal timeout : std_logic_vector(15 downto 0) := X"0000"; signal tx_good : std_logic; signal rx_data_ready : std_logic; --------ram implementation---------------------------- type memory_t is array(1023 downto 0) of std_logic_vector(7 downto 0); signal ram_mem : memory_t; signal addr_bus : std_logic_vector(15 downto 0) := X"0000"; shared variable ram_addr : integer := 0; shared variable cont_ram_addr : integer := 0; --for continious read/write shared variable temp_id_addr : integer := 0; shared variable temp_mask_addr : integer := 0; -------------------------------------------------------- signal temp_id : std_logic_vector(31 downto 0); signal mailbox_mask : std_logic_vector(31 downto 0); signal mailbox_id : std_logic_vector(31 downto 0); signal command : std_logic_vector(2 downto 0) := "000"; signal status : std_logic_vector(7 downto 0) := X"00"; -------------------------------BEGIN OF ARCHITECTURE---------------------------------------------- begin addr_bus <= REG_ADDR2_IN & REG_ADDR1_IN; process(REG_CLK, REG_RSTn) begin if(REG_RSTn = '0') then --REG_DATA_OUT <= (others => '0'); --State <= ST_IDLE; command <= "000"; MSPI_CS <= '1'; elsif (rising_edge(REG_CLK) and SPI_DATA_LATCH = '1') then --REG_DATA_LATCH to be sure command, address, data was received from spi slave if (REG_COM_IN(7 downto 5) = REG_CHAN) then --select spi channel case REG_COM_IN is --command from mcu spi when X"01" => --continious data read command <= "001"; when X"02" => --continious data write command <= "010"; when X"03" => --read data command ram_addr := to_integer(unsigned(addr_bus)); REG_DATA_OUT <= ram_mem(ram_addr); when X"04" => --write data command ram_addr := to_integer(unsigned(addr_bus)); ram_mem(ram_addr) <= REG_DATA1_IN; when X"05" => --write to mcp25625 register if (REG_ADDR1_IN < X"80") then mcp25625_reg_addr <= REG_ADDR1_IN; mcp25625_reg_data <= REG_DATA1_IN; State <= ST_TX_REG_COM; end if; when X"06" => --read from mcp25625 register if (REG_ADDR1_IN < X"80") then mcp25625_reg_addr <= REG_ADDR1_IN; --State <= ST_RX_REG_COM; end if; when X"07" => --read status REG_DATA_OUT <= status; when others => null; end case; end if; end if; end process; --continious_command : process (REG_CLK, S_RRDY) --begin -- if (rising_edge(REG_CLK)) then -- if (command > "000") then -- if (S_CS <= '0') then --chip select low -- if (S_RRDY <= '1') then --byte received -- case command is -- when "001" => --continious read -- REG_DATA_OUT <= ram_mem(ram_addr); -- ram_addr := ram_addr + 1; -- when "010" => --continious write -- ram_mem(ram_addr) <= REG_DATA1_IN; -- ram_addr := ram_addr + 1; -- when others => null; -- end case; -- end if; -- else -- command <= "000"; -- end if; -- end if; -- end if; --end process continious_command; mspi_mcp25625_interface: process (REG_CLK) begin if (rising_edge(REG_CLK)) then case State is when ST_IDLE => MSPI_WR_START_TRIG <= '0'; MSPI_WR_DONE_CLR <= '0'; if (MCP25625_RX0BF='0' or MCP25625_RX1BF='0') then State <= ST_START_RX_DATA; end if; when ST_WAIT_DONE => MSPI_WR_START_TRIG <= '0'; MSPI_WR_DONE_CLR <= '0'; if (MSPI_WR_DONE = '1') then MSPI_WR_DONE_CLR <= '1'; if (NextState = ST_RX_DATA) then if (rx_byte_idx < DATA_LENGHT) then temp_rx_mailbox(rx_byte_idx) <= MSPI_RD_DATA; rx_byte_idx := rx_byte_idx + 1; --index for next rx byte -- else -- rx_byte_idx := 0; -- State <= ST_IDLE; end if; elsif (NextState = ST_RX_REG_DATA) then mcp25625_reg_data <= MSPI_RD_DATA; elsif (NextState = ST_READ_STATUS_1) then mcp25625_status_reg <= MSPI_RD_DATA; end if; State <= NextState; else --timeout timeout <= timeout + 1; if (timeout >= X"FFFE") then timeout <= X"0000"; State <= ST_IDLE; end if; end if; ---------------------------------------RECEIVE MAILBOX FROM MCP25625------------------------- when ST_START_RX_DATA => --start to receive a mailbox if (MCP25625_RX0BF='0') then MSPI_WR_DATA <= X"90"; --Receive Buffer 0, Start at RXB0SIDH (0x61) elsif (MCP25625_RX1BF='0') then MSPI_WR_DATA <= X"94"; --Receive Buffer 1, Start at RXB1SIDH (0x71) end if; MSPI_CS <= '0'; --chip select low MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_RX_DATA0; State <= ST_WAIT_DONE; when ST_RX_DATA0 => --skip first byte - it was a command MSPI_WR_DONE_CLR <= '0'; State <= ST_RX_DATA; when ST_RX_DATA => --receive a mailbox MSPI_WR_DONE_CLR <= '0'; if (rx_byte_idx < DATA_LENGHT) then MSPI_WR_DATA <= X"00"; --load dummy byte MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_RX_DATA; State <= ST_WAIT_DONE; else --13 bytes received MSPI_CS <= '1'; --chip select high rx_byte_idx := 0; --MCP25625_DATA_RDY <= '1'; --WHERE TO CLEAR? rx_data_ready <= '1'; NextState <= ST_IDLE; State <= ST_IDLE; end if; -- --Note! The commands X"90" and X"94" automatically clear a buffer full flag after reading. -- -- --------------------------------------------------------------------------------------------- -- ---------------------------------------READ MCP25625 REGISTER-------------------------------- when ST_RX_REG_COM => MSPI_WR_DATA <= X"03"; --load read command MSPI_CS <= '0'; --chip select low MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_RX_REG_ADDR; State <= ST_WAIT_DONE; when ST_RX_REG_ADDR => MSPI_WR_DATA <= mcp25625_reg_addr; --load register address MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_RX_REG_DATA; State <= ST_WAIT_DONE; when ST_RX_REG_DATA => MSPI_CS <= '1'; --chip select high NextState <= ST_IDLE; State <= ST_IDLE; --------------------------------------------------------------------------------------------- ---------------------------------------WRITE MCP25625 REGISTER-------------------------------- when ST_TX_REG_COM => MSPI_WR_DATA <= X"02"; --load write command MSPI_CS <= '0'; --chip select low MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_TX_REG_ADDR; State <= ST_WAIT_DONE; when ST_TX_REG_ADDR => MSPI_WR_DATA <= mcp25625_reg_addr; --load register address MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_TX_REG_DATA; State <= ST_WAIT_DONE; when ST_TX_REG_DATA => MSPI_WR_DATA <= mcp25625_reg_data; --load register data MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_TX_REG_DONE; State <= ST_WAIT_DONE; when ST_TX_REG_DONE => MSPI_CS <= '1'; --chip select high NextState <= ST_IDLE; State <= ST_IDLE; -- -- -------------------------------------------------------------------------------------------- -- -- ---------------------------------------SEND MAILBOX TO MCP25625----------------------------- -- --read staus register to check which transmit buffer is empty when ST_READ_STATUS_0 => MSPI_WR_DATA <= X"A0"; --load read status command MSPI_CS <= '0'; --chip select low MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_READ_STATUS_1; State <= ST_WAIT_DONE; when ST_READ_STATUS_1 => MSPI_CS <= '1'; --chip select high NextState <= ST_IDLE; State <= ST_IDLE; when ST_START_TX_DATA => tx_good <= '0'; if (mcp25625_status_reg(2) = '0') then --TXREQ 0 MSPI_WR_DATA <= X"40"; --Transmitter Buffer 0, Start at TXB0SIDH (0x31) tx_good <= '1'; elsif (mcp25625_status_reg(4) = '0') then --TXREQ 1 MSPI_WR_DATA <= X"41"; --Transmitter Buffer 1, Start at TXB1SIDH (0x41) tx_good <= '1'; elsif (mcp25625_status_reg(6) = '0') then --TXREQ 2 MSPI_WR_DATA <= X"44"; --Transmitter Buffer 2, Start at TXB2SIDH (0x51) tx_good <= '1'; else tx_good <= '0'; end if; if (tx_good <= '1') then ram_addr := to_integer(unsigned(addr_bus)); MSPI_CS <= '0'; --chip select low MSPI_WR_START_TRIG <= '1'; --send a byte NextState <= ST_TX_DATA; State <= ST_WAIT_DONE; else NextState <= ST_IDLE; State <= ST_IDLE; end if; when ST_TX_DATA => if (tx_byte_idx < DATA_LENGHT) then MSPI_WR_DATA <= ram_mem(ram_addr); MSPI_WR_START_TRIG <= '1'; --send a byte tx_byte_idx := tx_byte_idx + 1; ram_addr := ram_addr + 1; NextState <= ST_TX_DATA; State <= ST_WAIT_DONE; else MSPI_CS <= '1'; --chip select high tx_byte_idx := 0; NextState <= ST_IDLE; State <= ST_IDLE; end if; when others => State <= ST_IDLE; end case; end if; end process mspi_mcp25625_interface; --put data from MCP25625 to mailbox rx_data_to_mailbox : process (REG_CLK) begin if (rising_edge(REG_CLK)) then if (rx_data_ready = '1') then for i in 0 to (MAILBOX_COUNT-1) loop temp_id_addr := (MAILBOX_SIZE * i) + MAILBOX_OFFSET; --calculate id address temp_mask_addr := temp_id_addr + 13 ; --calculate mask address temp_id <= temp_rx_mailbox(3) & temp_rx_mailbox(2) & temp_rx_mailbox(1) & temp_rx_mailbox(0); --load id registers mailbox_id <= ram_mem(temp_id_addr+3) & ram_mem(temp_id_addr+2) & ram_mem(temp_id_addr+1) & ram_mem(temp_id_addr); mailbox_mask <= ram_mem(temp_mask_addr+3) & ram_mem(temp_mask_addr+2) & ram_mem(temp_mask_addr+1) & ram_mem(temp_mask_addr); --if id+mask is good - put the temp data to the mailbox if ( (temp_id and mailbox_mask) = (mailbox_id and mailbox_mask) ) then ram_mem(temp_id_addr) <= temp_rx_mailbox(0); ram_mem(temp_id_addr+1) <= temp_rx_mailbox(1); ram_mem(temp_id_addr+2) <= temp_rx_mailbox(2); ram_mem(temp_id_addr+3) <= temp_rx_mailbox(3); ram_mem(temp_id_addr+4) <= temp_rx_mailbox(4); ram_mem(temp_id_addr+5) <= temp_rx_mailbox(5); ram_mem(temp_id_addr+6) <= temp_rx_mailbox(6); ram_mem(temp_id_addr+7) <= temp_rx_mailbox(7); ram_mem(temp_id_addr+8) <= temp_rx_mailbox(8); ram_mem(temp_id_addr+9) <= temp_rx_mailbox(9); ram_mem(temp_id_addr+10) <= temp_rx_mailbox(10); ram_mem(temp_id_addr+11) <= temp_rx_mailbox(11); ram_mem(temp_id_addr+12) <= temp_rx_mailbox(12); -- loaded_mailboxes(i) <= '1'; end if; end loop; rx_data_ready <= '0'; end if; end if; end process rx_data_to_mailbox; --process (REG_CLK, MSPI_WR_DONE) --begin -- if (rising_edge(REG_CLK)) then -- if (MSPI_WR_DONE = '1') then -- MSPI_WR_DONE_CLR <= '1'; -- if (NextState = ST_RX_DATA) then -- if (rx_byte_idx < MAILBOX_LENGHT) then -- temp_rx_mailbox(rx_byte_idx) <= MSPI_RD_DATA; -- rx_byte_idx := rx_byte_idx + 1; --index for next rx byte -- -- else -- -- rx_byte_idx := 0; -- -- State <= ST_IDLE; -- end if; -- elsif (NextState = ST_RX_REG_DATA) then -- mcp25625_reg_data <= MSPI_RD_DATA; -- end if; -- State <= NextState; -- else --timeout -- timeout <= timeout + 1; -- if (timeout >= X"FFFE") then -- timeout <= X"0000"; -- State <= ST_IDLE; -- end if; -- end if; -- end if; --end process; end behavior;