Last active
August 29, 2015 14:22
-
-
Save thetooth/a676fd15a9f176d2609f to your computer and use it in GitHub Desktop.
Controller FSM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library ieee; | |
| use ieee.std_logic_1164.all; | |
| library MACHXO2; | |
| use MACHXO2.components.all; | |
| -- Opcode Size Description CMD Access | |
| ------------------------------------------------------------------------------------------ | |
| -- Operation codes for SPI FSM | |
| ------------------------------------------------------------------------------------------ | |
| -- INJMDR 16 Injector main delta 0xA0 Write | |
| -- INJPDR 16 Injector preinjection delta 0xA1 Write | |
| -- INJBEN 0 Disables timing adjustment 0xA2 Write | |
| -- UFMADR 8 Address user flash memory 0xE0 Read/Write | |
| -- (last page returned, write 0xFF to retain last page) | |
| -- UFMWRR 128 Write UFM page 0xE1 Write | |
| -- UFMRDR 128 Read UFM page 0xE2 Read | |
| ------------------------------------------------------------------------------------------ | |
| -- EFB SPI memory mapped register addresses are 0x54-0x5D | |
| ------------------------------------------------------------------------------------------ | |
| -- SPICR0 Control Reg 0 0x54 Read/Write | |
| -- SPICR1 Control Reg1 0x55 Read/Write | |
| -- SPICR2 Control Reg2 0x56 Read/Write | |
| -- SPIBR Clock Pre-Scale 0x57 Read/Write | |
| -- SPICSR Master Chip Select 0x58 Read/Write | |
| -- SPITXDR Transmit Data 0x59 Write | |
| -- SPISR Status 0x5A Read | |
| -- SPIRXDR Receive Data 0x5B Read | |
| -- SPIIRQ Interrupt Request 0x5C Read/Write | |
| -- SPIIRQEN Interrupt Request Enable 0x5D Read/Write | |
| entity SPICtl is | |
| port( | |
| -- Control Plane | |
| clk : in std_logic; | |
| nreset : in std_logic; | |
| spi_clk : inout std_logic; | |
| spi_scsn : in std_logic; | |
| spi_irq : out std_logic; | |
| busy_out : out std_logic; | |
| -- Data Plane | |
| spi_mosi : inout std_logic; | |
| spi_miso : inout std_logic; | |
| debug : out std_logic_vector(15 downto 0); | |
| INJMDR : out std_logic_vector(15 downto 0) | |
| ); | |
| end SPICtl; | |
| architecture logic of SPICtl is | |
| component Embedded_Function_Block | |
| port( | |
| wb_clk_i : in std_logic; | |
| wb_rst_i : in std_logic; | |
| wb_cyc_i : in std_logic; | |
| wb_stb_i : in std_logic; | |
| wb_we_i : in std_logic; | |
| wb_adr_i : in std_logic_vector(7 downto 0); | |
| wb_dat_i : in std_logic_vector(7 downto 0); | |
| wb_dat_o : out std_logic_vector(7 downto 0); | |
| wb_ack_o : out std_logic; | |
| spi_clk : inout std_logic; | |
| spi_miso : inout std_logic; | |
| spi_mosi : inout std_logic; | |
| spi_scsn : in std_logic; | |
| spi_irq : out std_logic | |
| ); | |
| end component; | |
| component SPI_wbController | |
| port( | |
| clk : in std_logic; | |
| nreset : in std_logic; | |
| wb_bus_en : in std_logic; | |
| wb_ack_o : in std_logic; | |
| wb_valid_address : in std_logic_vector(7 downto 0); | |
| wb_valid_data : in std_logic_vector(7 downto 0); | |
| wb_valid_data_o : in std_logic_vector(7 downto 0); | |
| w_enable : in std_logic; | |
| busy : out std_logic; | |
| wb_rst_i : out std_logic; | |
| wb_cyc_i : out std_logic; | |
| wb_stb_i : out std_logic; | |
| wb_we_i : out std_logic; | |
| wb_adr_i : out std_logic_vector(7 downto 0); | |
| wb_dat_o : out std_logic_vector(7 downto 0); | |
| wb_dat_i : out std_logic_vector(7 downto 0) | |
| ); | |
| end component; | |
| -- Local wishbone bus signals from wb state machine controller | |
| signal w_enable : std_logic; | |
| signal wb_rst_i : std_logic; | |
| signal wb_cyc_i : std_logic; | |
| signal wb_stb_i : std_logic; | |
| signal wb_we_i : std_logic; | |
| signal wb_adr_i : std_logic_vector(7 downto 0); | |
| signal wb_dat_i : std_logic_vector(7 downto 0); | |
| signal wb_dat_o : std_logic_vector(7 downto 0); | |
| signal wb_ack_o : std_logic; | |
| signal wb_busy : std_logic; | |
| signal wb_bus_en : std_logic; | |
| signal reg_address : std_logic_vector(7 downto 0); | |
| signal tx_address : std_logic_vector(7 downto 0); | |
| signal tx_reg : std_logic_vector(7 downto 0); | |
| -- Encode for one hot fsm :^) | |
| type state_type is (ready, RxRDY, get_data, get_opcode, get_INJMDR_data1, get_INJMDR_data2, TxRDY, put_data); | |
| attribute enum_encoding : string; | |
| attribute enum_encoding of state_type : type is "00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000"; | |
| signal state_reg, state_next, cmd_reg : state_type; | |
| signal reg_address_ff : std_logic_vector(7 downto 0); | |
| begin | |
| -- The spi bus is instantiated through the EFB within IPExpress | |
| I0 : Embedded_Function_Block | |
| port map (wb_clk_i => clk, wb_rst_i => wb_rst_i, wb_cyc_i => wb_cyc_i, wb_stb_i => wb_stb_i, | |
| wb_we_i => wb_we_i, wb_adr_i(7 downto 0) => wb_adr_i(7 downto 0), | |
| wb_dat_i(7 downto 0) => wb_dat_i(7 downto 0), wb_dat_o(7 downto 0) => wb_dat_o(7 downto 0), -- This is the data that comes from the master such as an address to mux to the tx buffer to the wb_data_i | |
| wb_ack_o => wb_ack_o, spi_clk => spi_clk, spi_miso => spi_miso, | |
| spi_mosi => spi_mosi, spi_scsn => spi_scsn, spi_irq => spi_irq); | |
| -- The spi controller is used to control the machxo2 wishbone bus interfacing the spi | |
| I1 : SPI_wbController | |
| port map ( clk => clk, nreset => nreset, wb_bus_en => wb_bus_en, wb_ack_o => wb_ack_o, | |
| wb_valid_address(7 downto 0) => tx_address(7 downto 0), | |
| w_enable => w_enable, busy => wb_busy, | |
| wb_valid_data(7 downto 0) => tx_reg(7 downto 0), | |
| wb_valid_data_o(7 downto 0) => wb_dat_o(7 downto 0), | |
| wb_rst_i => wb_rst_i, wb_cyc_i => wb_cyc_i, wb_stb_i => wb_stb_i, | |
| wb_we_i => wb_we_i, wb_adr_i(7 downto 0) => wb_adr_i(7 downto 0), | |
| wb_dat_o(7 downto 0) => reg_address(7 downto 0), | |
| wb_dat_i(7 downto 0) => wb_dat_i(7 downto 0)); -- This is the data going out to the master from the txbuffer | |
| -- State update and timing with synch active low reset | |
| process(clk, nreset) | |
| begin | |
| if(rising_edge(clk)) then | |
| if(nreset = '0') then | |
| state_reg <= ready; | |
| else | |
| state_reg <= state_next; | |
| end if; | |
| end if; | |
| end process; | |
| -- Control logic state machine, add to sensitivity list as needed when modified | |
| process(state_reg, reg_address, reg_address_ff, wb_busy) | |
| begin | |
| -- default conditions | |
| tx_address(7 downto 0) <= (others => 'Z'); | |
| tx_reg(7 downto 0) <= (others => 'Z'); | |
| -- testing | |
| wb_bus_en <= '0'; | |
| case state_reg is | |
| -- Initial state | |
| ------------------------------------------------------------------------------ | |
| when ready => | |
| wb_bus_en <= '0'; | |
| tx_address(7 downto 0) <= (others => 'Z'); | |
| tx_reg(7 downto 0) <= (others => 'Z'); | |
| if( wb_busy = '1') then | |
| state_next <= state_reg; | |
| else | |
| state_next <= RxRDY; | |
| end if; | |
| -- Read status reg to see if reciever contains a reg address yet | |
| ------------------------------------------------------------------------------ | |
| when RxRDY => | |
| wb_bus_en <= '1'; -- starts wishbone controller fsm | |
| w_enable <= '0'; -- set to read the wb | |
| -- load wishbone status register | |
| tx_address(7 downto 0) <= X"5A"; | |
| if(wb_busy = '1') then | |
| state_next <= state_reg; | |
| else | |
| if(reg_address(3) = '1') then | |
| state_next <= get_data; | |
| else | |
| state_next <= state_reg; | |
| end if; | |
| end if; | |
| -- This state is used to get the address data from the master | |
| ------------------------------------------------------------------------------ | |
| when get_data => | |
| wb_bus_en <= '0'; | |
| w_enable <= '0'; | |
| -- load wishbone reciever register | |
| tx_address(7 downto 0) <= X"5B"; | |
| if(wb_busy= '1') then | |
| state_next <= state_reg; | |
| else | |
| if(cmd_reg = ready) then | |
| state_next <= get_opcode; | |
| else | |
| state_next <= cmd_reg; | |
| end if; | |
| end if; | |
| -- This state checks and stores the recieved operation code | |
| ------------------------------------------------------------------------------ | |
| when get_opcode => | |
| wb_bus_en <= '1'; | |
| w_enable <= '0'; | |
| tx_address(7 downto 0) <= X"5B"; | |
| reg_address_ff(7 downto 0) <= reg_address; | |
| if( wb_busy = '1') then | |
| state_next <= state_reg; | |
| else | |
| case reg_address_ff(7 downto 0) is | |
| when X"A0" => | |
| cmd_reg <= get_INJMDR_data1; | |
| state_next <= RxRDY; | |
| when others => | |
| state_next <= TxRDY; | |
| end case; | |
| end if; | |
| -- This state is used to latch in the data into the application register | |
| ------------------------------------------------------------------------------ | |
| when get_INJMDR_data1 => | |
| wb_bus_en <= '1'; | |
| w_enable <= '0'; | |
| tx_address(7 downto 0) <= X"5B"; | |
| INJMDR(15 downto 8) <= reg_address; | |
| if( wb_busy = '1') then | |
| state_next <= state_reg; | |
| else | |
| cmd_reg <= get_INJMDR_data2; | |
| state_next <= RxRDY; -- Get next byte | |
| end if; | |
| when get_INJMDR_data2 => | |
| wb_bus_en <= '1'; | |
| w_enable <= '0'; | |
| tx_address(7 downto 0) <= X"5B"; | |
| INJMDR(7 downto 0) <= reg_address; | |
| if( wb_busy = '1') then | |
| state_next <= state_reg; | |
| else | |
| cmd_reg <= ready; | |
| state_next <= TxRDY; -- Final transaction | |
| end if; | |
| -- This state checks the status of the spi transmitter to ensure its empty | |
| ------------------------------------------------------------------------------ | |
| when TxRDY => | |
| wb_bus_en <= '1'; | |
| w_enable <= '0'; | |
| tx_address(7 downto 0) <= X"5A"; | |
| if(wb_busy = '1') then | |
| state_next <= state_reg; | |
| else | |
| if(reg_address(4) = '1') then | |
| state_next <= put_data; | |
| else | |
| state_next <= state_reg; | |
| end if; | |
| end if; | |
| -- This state sends the requested data to the spi transmit buffer | |
| ------------------------------------------------------------------------------ | |
| when put_data => | |
| wb_bus_en <= '1'; | |
| w_enable <= '1'; -- set to write to master | |
| -- load wishbone transmitter register | |
| tx_address(7 downto 0) <= X"59"; | |
| -- Add extra addresses and data lines to this if-elsif statement | |
| -- when connecting more shit | |
| --if(reg_address_ff = X"A3") then | |
| -- tx_reg(7 downto 0) <= tx_data(7 downto 0); | |
| --else | |
| tx_reg(7 downto 0) <= "00000000"; | |
| --end if; | |
| if( wb_busy = '1') then | |
| state_next <= state_reg; | |
| else | |
| state_next <= RxRDY; -- ! Should be `ready`, maybe needs nreset signal | |
| end if; | |
| end case; | |
| end process; | |
| busy_out <= wb_busy; | |
| end logic; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment