OpenCores
URL https://opencores.org/ocsvn/pmodsf3driver/pmodsf3driver/trunk

Subversion Repositories pmodsf3driver

[/] [pmodsf3driver/] [trunk/] [hw/] [sources/] [PmodSF3Driver.vhd] - Rev 2

Compare with Previous | Blame | View Log

------------------------------------------------------------------------
-- Engineer:    Dalmasso Loic
-- Create Date: 04/03/2025
-- Module Name: PmodSF3Driver
-- Description:
--      Pmod SF3 Driver for the 32 MB NOR Flash memory MT25QL256ABA.
--		The communication with the Flash uses the SPI protocol (Simple, Dual or Quad SPI modes, dynamically configurable).
--      User specifies the System Input Clock and the Pmod SF3 Driver dynamically computes the SPI Serial Clock Frequency according to the actual Dummy Cycles
--		User specifies the maximum bytes buffer used for data read & write.
--		For each read/write operation, user specifies the number of expected address and data bytes, 'i_addr_bytes' and 'i_data_bytes' respectively.
--
-- Usage:
--		The 'o_ready' signal indicates this module is ready to start new SPI transmission.
--		The 'i_start' signal starts the SPI communication, according to the mode 'i_rw' (Read or Write memory), command/address/data bytes and the expected number of bytes.
--		In Read operation, when the 'o_data_ready', data from memory is available in 'o_data' signal.
--
-- Generics
--		sys_clock: System Input Clock Frequency (Hz)
--		max_data_byte: Maximum number of Data Bytes in the driver
-- Ports
--		Input 	-	i_sys_clock: System Input Clock
--		Input 	-	i_reset: Module Reset ('0': No Reset, '1': Reset)
--		Input	-	i_start: Start SPI Transmission ('0': No Start, '1': Start)
--		Input 	-	i_rw: Read / Write Mode ('0': Write, '1': Read)
--		Input 	-	i_command: FLASH Command Byte
--		Input 	-	i_addr_bytes: Number of Address Bytes
--		Input 	-	i_addr: FLASH Address Bytes
--		Input 	-	i_data_bytes: Number of Data Bytes to Read/Write
--		Input 	-	i_data: FLASH Data Bytes to Write
--		Output 	-	o_data: Read FLASH Data Bytes
--		Output 	-	o_data_ready: FLASH Data Output Ready (Read Mode) ('0': NOT Ready, '1': Ready)
--		Output 	-	o_ready: Module Ready ('0': NOT Ready, '1': Ready)
--		Output 	-	o_reset: FLASH Reset ('0': Reset, '1': No Reset)
--		Output 	-	o_sclk: SPI Serial Clock
--		In/Out 	-	io_dq: SPI Data Lines (Simple, Dual or Quad Modes)
--		Output 	-	o_ss: SPI Slave Select Line ('0': Enable, '1': Disable)
--		Output 	-	o_using_sys_freq: System Input Clock as SPI Serial Clock Frequency ('0': Disable, '1': Enable)
------------------------------------------------------------------------
 
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
 
ENTITY PmodSF3Driver is
 
GENERIC(
	sys_clock: INTEGER := 100_000_000;
	max_data_byte: INTEGER := 1
);
 
PORT(
	i_sys_clock: IN STD_LOGIC;
	i_reset: IN STD_LOGIC;
    i_start: IN STD_LOGIC;
    i_rw: IN STD_LOGIC;
    i_command: IN UNSIGNED(7 downto 0);
	i_addr_bytes: IN INTEGER range 0 to 4;
    i_addr: IN UNSIGNED(23 downto 0);
    i_data_bytes: IN INTEGER range 0 to max_data_byte;
	i_data: IN UNSIGNED((max_data_byte*8)-1 downto 0);
	o_data: OUT UNSIGNED((max_data_byte*8)-1 downto 0);
	o_data_ready: OUT STD_LOGIC;
    o_ready: OUT STD_LOGIC;
	o_reset: OUT STD_LOGIC;
	o_sclk: OUT STD_LOGIC;
	io_dq: INOUT STD_LOGIC_VECTOR(3 downto 0);
	o_ss: OUT STD_LOGIC;
	o_spi_using_sys_freq: OUT STD_LOGIC
);
 
END PmodSF3Driver;
 
ARCHITECTURE Behavioral of PmodSF3Driver is
 
------------------------------------------------------------------------
-- Component Declarations
------------------------------------------------------------------------
 
COMPONENT PmodSF3SPIController is
 
PORT(
	-- Module Control
	i_sys_clock: IN STD_LOGIC;
	i_sys_clock_en: IN STD_LOGIC;
	i_reset: IN STD_LOGIC;
	i_start: IN STD_LOGIC;
	-- SPI Mode Config (Single, Dual or Quad)
	i_spi_single_enable: IN STD_LOGIC;
	i_spi_dual_enable: IN STD_LOGIC;
	-- Memory Command/Addr/Data
	i_mode: IN STD_LOGIC;
	i_command: IN UNSIGNED(7 downto 0);
	i_addr_bytes: IN INTEGER range 0 to 3;
	i_addr: IN UNSIGNED(23 downto 0);
	i_dummy_cycles: IN INTEGER range 0 to 14;
	i_data_bytes: IN INTEGER;
	i_data_w: IN UNSIGNED(7 downto 0);
	o_next_data_w: OUT STD_LOGIC;
	o_data_r: OUT UNSIGNED(7 downto 0);
	o_data_ready: OUT STD_LOGIC;
	-- Module Outputs
	o_ready: OUT STD_LOGIC;
	o_reset: OUT STD_LOGIC;
	o_sclk: OUT STD_LOGIC;
	io_dq: INOUT STD_LOGIC_VECTOR(3 downto 0);
	o_ss: OUT STD_LOGIC
);
 
END COMPONENT;
 
COMPONENT PmodSF3SPIFrequencyGenerator is
 
GENERIC(
    sys_clock: INTEGER := 100_000_000
);
 
PORT(
	i_sys_clock: IN STD_LOGIC;
	i_reset: IN STD_LOGIC;
	i_spi_single_enable: IN STD_LOGIC;
	i_spi_dual_enable: IN STD_LOGIC;
	i_dummy_cycles: IN INTEGER range 0 to 14;
	o_spi_freq: OUT STD_LOGIC;
	o_using_sys_freq: OUT STD_LOGIC
);
 
END COMPONENT;
 
COMPONENT PmodSF3DummyCycles is
 
PORT(
	i_sys_clock: IN STD_LOGIC;
	i_reset: IN STD_LOGIC;
	i_end_of_tx: IN STD_LOGIC;
    i_command: IN UNSIGNED(7 downto 0);
	i_new_data_to_mem: IN STD_LOGIC;
    i_data_to_mem: IN UNSIGNED(7 downto 0);
	i_data_from_mem_ready: IN STD_LOGIC;
    i_data_from_mem: IN UNSIGNED(7 downto 0);
    o_dummy_cycles: OUT INTEGER range 0 to 14
);
 
END COMPONENT;
 
COMPONENT PmodSF3SPIModes is
 
PORT(
	i_sys_clock: IN STD_LOGIC;
	i_reset: IN STD_LOGIC;
	i_end_of_tx: IN STD_LOGIC;
    i_command: IN UNSIGNED(7 downto 0);
	i_new_data_to_mem: IN STD_LOGIC;
    i_data_to_mem: IN UNSIGNED(7 downto 0);
	i_data_from_mem_ready: IN STD_LOGIC;
    i_data_from_mem: IN UNSIGNED(7 downto 0);
    o_spi_single_enable: OUT STD_LOGIC;
    o_spi_dual_enable: OUT STD_LOGIC;
    o_spi_quad_enable: OUT STD_LOGIC
);
 
END COMPONENT;
 
------------------------------------------------------------------------
-- Constant Declarations
------------------------------------------------------------------------
-- Memory Read Mode
constant MEM_READ_MODE: STD_LOGIC := '1';
 
-- Data Write MSB/LSB Indexes
constant DATA_HIGH_BIT_MSB : INTEGER := (max_data_byte*8)-1;
constant DATA_HIGH_BIT_LSB : INTEGER := (max_data_byte*8)-8;
 
-- Data Write Unused Bit
constant DATA_BIT_UNUSED: STD_LOGIC := '0';
 
------------------------------------------------------------------------
-- Signal Declarations
------------------------------------------------------------------------
-- Pmod SF3 Driver States
TYPE pmodPSF3State is (IDLE, START, IN_PROGRESS, REFRESH_CONFIG, COMPLETED);
signal state: pmodPSF3State := IDLE;
signal next_state: pmodPSF3State;
 
-- Memory Write Mode
signal mem_mode_reg: STD_LOGIC := '0';
 
-- Data Write & Read Registers
signal data_w_reg: UNSIGNED((max_data_byte*8)-1 downto 0) := (others => '0');
signal next_data_sig: STD_LOGIC := '0';
signal data_r_reg: UNSIGNED((max_data_byte*8)-1 downto 0) := (others => '0');
signal data_r_byte: UNSIGNED(7 downto 0) := (others => '0');
signal data_ready_sig: STD_LOGIC := '0';
 
-- Data Read Ready
signal data_ready_reg: STD_LOGIC := '0';
 
-- Dummy Cycles
signal dummy_cycles: INTEGER range 0 to 14 := 0;
 
-- SPI Controller Ready
signal spi_ready: STD_LOGIC := '0';
 
-- SPI Modes
signal spi_single_enable: STD_LOGIC := '0';
signal spi_dual_enable: STD_LOGIC := '0';
signal spi_quad_enable: STD_LOGIC := '0'; 
 
-- SPI Frequency Generator
signal spi_freq_en: STD_LOGIC := '0';
 
-- SPI Controller Reset
signal spi_reset: STD_LOGIC := '0';
 
-- SPI Controller Start
signal spi_start: STD_LOGIC := '0';
 
------------------------------------------------------------------------
-- Module Implementation
------------------------------------------------------------------------
begin
 
	-----------------------------------
	-- Pmod SF3 Driver State Machine --
	-----------------------------------
	-- Pmod SF3 State
	process(i_sys_clock)
	begin
		if rising_edge(i_sys_clock) then
 
			-- Reset
			if (i_reset = '1') then
				state <= IDLE;
 
			else
				state <= next_state;
			end if;
 
		end if;
	end process;
 
	-- Pmod SF3 Next State
	process(state, i_start, spi_ready)
	begin
		case state is
			-- IDLE
			when IDLE =>	if (i_start = '1') then
								next_state <= START;
							else
								next_state <= IDLE;
							end if;
 
			-- Start
			when START =>	if (spi_ready = '0') then
								next_state <= IN_PROGRESS;
							else
								next_state <= START;
							end if;
 
			-- In Progress
			when IN_PROGRESS =>	if (spi_ready = '1') then
									next_state <= REFRESH_CONFIG;
								else
									next_state <= IN_PROGRESS;
								end if;
 
			-- Refresh Configurations
			when REFRESH_CONFIG => next_state <= COMPLETED;
 
			-- Completed
			when others => next_state <= IDLE;
		end case;
	end process;
 
	-------------------------
	-- Memory Mode Handler --
	-------------------------
	process(i_sys_clock)
	begin
		if rising_edge(i_sys_clock) then
 
			-- Load Memory Mode Input
			if (state = IDLE) then
				mem_mode_reg <= i_rw;
			end if;
		end if;
	end process;
 
	------------------------
	-- Data Write Handler --
	------------------------
	process(i_sys_clock)
	begin
		if rising_edge(i_sys_clock) then
 
			-- Load Data Write
			if (state = IDLE) then
				data_w_reg <= i_data;
 
			-- Data Write Left-Shift
			elsif (state = IN_PROGRESS) and (next_data_sig = '1') then
 
				-- Single SPI Mode
				if (spi_single_enable = '1') then
					data_w_reg <= data_w_reg(DATA_HIGH_BIT_MSB-1 downto 0) & DATA_BIT_UNUSED;
 
				-- Dual SPI Mode
				elsif (spi_dual_enable = '1') then
					data_w_reg <= data_w_reg(DATA_HIGH_BIT_MSB-2 downto 0) & DATA_BIT_UNUSED & DATA_BIT_UNUSED;
 
				-- Quad SPI Mode
				else
					data_w_reg <= data_w_reg(DATA_HIGH_BIT_MSB-4 downto 0) & DATA_BIT_UNUSED & DATA_BIT_UNUSED & DATA_BIT_UNUSED & DATA_BIT_UNUSED;
				end if;
 
			end if;
		end if;
	end process;
 
	-----------------------
	-- Data Read Handler --
	-----------------------
	process(i_sys_clock)
	begin
		if rising_edge(i_sys_clock) then
 
			-- Data Read Left-Shift
			if (state = IN_PROGRESS) and (data_ready_sig = '1') then
 
				-- Data Read on 1-Byte
				if (max_data_byte = 1) then
					data_r_reg <= data_r_byte;
 
				-- Data Read on n-Bytes
				else
					data_r_reg <= data_r_reg(DATA_HIGH_BIT_LSB-1 downto 0) & data_r_byte;
				end if;
			end if;			
		end if;
	end process;
	o_data <= data_r_reg;
 
	-----------------------------
	-- Data Read Ready Handler --
	-----------------------------
	process(i_sys_clock)
	begin
		if rising_edge(i_sys_clock) then
 
			-- Enable Read Data Valid (End of Read Cycle)
			if (mem_mode_reg = MEM_READ_MODE) and (state = COMPLETED) then
				data_ready_reg <= '1';
 
			-- Disable Read Data Valid (New cycle)
			elsif (state = START) then
				data_ready_reg <= '0';
			end if;
 
		end if;
	end process;
	o_data_ready <= data_ready_reg;
 
	---------------------------
	-- Pmod SF3 Ready Status --
	---------------------------
	o_ready <= '1' when state = IDLE else '0';
 
	--------------------------------------
	-- Pmod SF3 SPI Frequency Generator --
	--------------------------------------
	inst_PmodSF3SPIFrequencyGenerator: PmodSF3SPIFrequencyGenerator
		GENERIC map (
			sys_clock => sys_clock)
 
		PORT map (
			i_sys_clock => i_sys_clock,
			i_reset => i_reset,
			i_spi_single_enable => spi_single_enable,
			i_spi_dual_enable => spi_dual_enable,
			i_dummy_cycles => dummy_cycles,
			o_spi_freq => spi_freq_en,
			o_using_sys_freq => o_spi_using_sys_freq);
 
	--------------------------------------
	-- Pmod SF3 Dummy Cycles Controller --
	--------------------------------------
	inst_PmodSF3DummyCycles: PmodSF3DummyCycles
		PORT map (
			i_sys_clock => i_sys_clock,
			i_reset => i_reset,
			i_end_of_tx => spi_ready,
			i_command => i_command,
			i_new_data_to_mem => next_data_sig,
			i_data_to_mem => data_w_reg(DATA_HIGH_BIT_MSB downto DATA_HIGH_BIT_LSB),
			i_data_from_mem_ready => data_ready_sig,
			i_data_from_mem => data_r_byte,
			o_dummy_cycles => dummy_cycles);
 
	------------------------
	-- Pmod SF3 SPI Modes --
	------------------------
	inst_PmodSF3SPIModes: PmodSF3SPIModes
		PORT map (
			i_sys_clock => i_sys_clock,
			i_reset => i_reset,
			i_end_of_tx => spi_ready,
			i_command => i_command,
			i_new_data_to_mem => next_data_sig,
			i_data_to_mem => data_w_reg(DATA_HIGH_BIT_MSB downto DATA_HIGH_BIT_LSB),
			i_data_from_mem_ready => data_ready_sig,
			i_data_from_mem => data_r_byte,
			o_spi_single_enable => spi_single_enable,
			o_spi_dual_enable => spi_dual_enable,
			o_spi_quad_enable => spi_quad_enable);
 
	-----------------------------------
	-- Pmod SF3 SPI Controller Reset --
	-----------------------------------
	process(i_sys_clock)
	begin
		if rising_edge(i_sys_clock) then
 
			-- Start SPI Controller
			if (state = IDLE) then
				spi_reset <= '1';
			else
				spi_reset <= '0';
			end if;
		end if;
	end process;
 
	-----------------------------------
	-- Pmod SF3 SPI Controller Start --
	-----------------------------------
	process(i_sys_clock)
	begin
		if rising_edge(i_sys_clock) then
 
			-- Start SPI Controller
			if (state = START) then
				spi_start <= '1';
			else
				spi_start <= '0';
			end if;
		end if;
	end process;
 
	-----------------------------
	-- Pmod SF3 SPI Controller --
	-----------------------------
	inst_PmodSF3SPIController: PmodSF3SPIController
		PORT map (
			i_sys_clock => i_sys_clock,
			i_sys_clock_en => spi_freq_en,
			i_reset => spi_reset,
			i_start => spi_start,
			i_spi_single_enable => spi_single_enable,
			i_spi_dual_enable => spi_dual_enable,
			i_mode => i_rw,
			i_command => i_command,
			i_addr_bytes => i_addr_bytes,
			i_addr => i_addr,
			i_dummy_cycles => dummy_cycles,
			i_data_bytes => i_data_bytes,
			i_data_w => data_w_reg(DATA_HIGH_BIT_MSB downto DATA_HIGH_BIT_LSB),
			o_next_data_w => next_data_sig,
			o_data_r => data_r_byte,
			o_data_ready => data_ready_sig,
			o_ready => spi_ready,
			o_reset => o_reset,
			o_sclk => o_sclk,
			io_dq => io_dq,
			o_ss => o_ss);
 
end Behavioral;

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.