142 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| library ieee;
 | |
| use ieee.std_logic_1164.all;
 | |
| use ieee.numeric_std.all;
 | |
| 
 | |
| entity flashrom_spi is
 | |
| 	generic(
 | |
| 		clk_divider     : integer range 2 to 9999 := 2;
 | |
| 		max_word_length : integer                 := 32;
 | |
| 		max_dummy_bits  : integer                 := 8
 | |
| 	);
 | |
| 	port(
 | |
| 		clk                 : in  std_logic;
 | |
| 		rst                 : in  std_logic;
 | |
| 		clr                 : in  std_logic;
 | |
| 
 | |
| 		-- SPI flash hardware signals
 | |
| 		spi_si              : out std_logic; -- SPI serial in
 | |
| 		spi_so              : in  std_logic; -- SPI serial out
 | |
| 		spi_sck             : out std_logic; -- Create clock using PLL, then supply to chip and this module
 | |
| 		spi_cs_n            : out std_logic; -- SPI chip select
 | |
| 
 | |
| 		-- Logic interface
 | |
| 		data_in_valid       : in  std_logic;
 | |
| 		data_in             : in  std_logic_vector(max_word_length - 1 downto 0);
 | |
| 		data_in_length      : in  integer range 0 to max_word_length;
 | |
| 		data_next           : out std_logic;
 | |
| 		data_out            : out std_logic_vector(max_word_length - 1 downto 0);
 | |
| 		data_out_valid      : out std_logic;
 | |
| 		data_out_length     : in  integer range 0 to max_word_length;
 | |
| 		data_out_dummy_bits : in  integer range 0 to max_dummy_bits;
 | |
| 		transmission_active : out std_logic
 | |
| 	);
 | |
| end entity flashrom_spi;
 | |
| 
 | |
| architecture RTL of flashrom_spi is
 | |
| 	type txstate_t is (IDLE, TX);
 | |
| 	signal state             : txstate_t;
 | |
| 	signal ckDiv             : integer range 0 to clk_divider - 2;
 | |
| 	signal shiftreg          : std_logic_vector(max_word_length - 1 downto 0);
 | |
| 	signal bitCounter        : integer range 0 to max_word_length - 1;
 | |
| 	signal bitCounterIn      : integer range 0 to max_word_length + max_dummy_bits - 1;
 | |
| 	signal data_in_length_i  : integer range 0 to max_word_length;
 | |
| 	signal data_out_length_i : integer range 0 to max_word_length;
 | |
| 	signal delayCycle        : std_logic;
 | |
| 	signal oneBitRead        : std_logic;
 | |
| 	signal dummy_passed      : boolean;
 | |
| begin
 | |
| 	toSpi : process(clk, rst) is
 | |
| 		procedure default_state is
 | |
| 		begin
 | |
| 			data_next      <= '0';
 | |
| 			data_out_valid <= '0';
 | |
| 		end procedure default_state;
 | |
| 
 | |
| 		procedure reset_state is
 | |
| 		begin
 | |
| 			state        <= IDLE;
 | |
| 			spi_sck      <= '0';
 | |
| 			shiftreg     <= (others => '0');
 | |
| 			bitCounter   <= 0;
 | |
| 			bitCounterIn <= 0;
 | |
| 			data_out     <= (others => '0');
 | |
| 			delayCycle   <= '0';
 | |
| 			oneBitRead   <= '0';
 | |
| 			dummy_passed <= false;
 | |
| 			default_state;
 | |
| 		end procedure reset_state;
 | |
| 	begin
 | |
| 		if rst = '1' then
 | |
| 			reset_state;
 | |
| 		elsif rising_edge(clk) then
 | |
| 			default_state;
 | |
| 			if clr = '1' then
 | |
| 				reset_state;
 | |
| 			else
 | |
| 				case state is
 | |
| 					when IDLE =>
 | |
| 						delayCycle   <= '0';
 | |
| 						spi_sck      <= '0';
 | |
| 						oneBitRead   <= '0';
 | |
| 						dummy_passed <= false;
 | |
| 						data_out     <= (others => '0');
 | |
| 						if data_in_valid = '1' then
 | |
| 							state            <= TX;
 | |
| 							bitCounter       <= 0;
 | |
| 							bitCounterIn     <= 0;
 | |
| 							data_in_length_i <= 0;
 | |
| 						end if;
 | |
| 					when TX =>
 | |
| 						if ckDiv = clk_divider - 2 then
 | |
| 							spi_sck <= not spi_sck;
 | |
| 							if spi_sck = '0' then -- rising edge
 | |
| 								if bitCounter = data_in_length_i then
 | |
| 									bitCounter <= 0;
 | |
| 									if data_in_valid = '1' then
 | |
| 										shiftreg          <= data_in;
 | |
| 										data_in_length_i  <= data_in_length - 1;
 | |
| 										data_out_length_i <= data_out_length - 1;
 | |
| 										data_next         <= '1';
 | |
| 									else
 | |
| 										delayCycle <= '1';
 | |
| 									end if;
 | |
| 								else
 | |
| 									bitCounter <= bitCounter + 1;
 | |
| 									shiftreg   <= shiftreg(shiftreg'high - 1 downto 0) & '0';
 | |
| 								end if;
 | |
| 							else        -- spi_sck = '1' (falling edge)
 | |
| 								data_out   <= data_out(data_out'high - 1 downto 0) & spi_so;
 | |
| 								oneBitRead <= '1';
 | |
| 								if bitCounterIn = 0 then
 | |
| 									if dummy_passed then
 | |
| 										data_out_valid <= '1';
 | |
| 									end if;
 | |
| 								end if;
 | |
| 								if not dummy_passed and bitCounterIn = data_out_dummy_bits then
 | |
| 									dummy_passed <= true;
 | |
| 									bitCounterIn <= 1;
 | |
| 								else
 | |
| 									if bitCounterIn = data_out_length_i then
 | |
| 										bitCounterIn <= 0;
 | |
| 									else
 | |
| 										bitCounterIn <= bitCounterIn + 1;
 | |
| 									end if;
 | |
| 									if delayCycle = '1' then
 | |
| 										spi_sck <= '0';
 | |
| 										state   <= IDLE;
 | |
| 									end if;
 | |
| 								end if;
 | |
| 							end if;
 | |
| 						else
 | |
| 							ckDiv <= ckDiv + 1;
 | |
| 						end if;
 | |
| 				end case;
 | |
| 			end if;
 | |
| 		end if;
 | |
| 	end process toSpi;
 | |
| 	spi_si   <= shiftreg(shiftreg'high);
 | |
| 	spi_cs_n <= '0' when state = TX else '1';
 | |
| 
 | |
| 	transmission_active <= '1' when state = TX else '0';
 | |
| end architecture RTL;
 |