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

Subversion Repositories tcp_ip_core_w_dhcp

[/] [tcp_ip_core_w_dhcp/] [trunk/] [spi_mod.vhd] - Rev 2

Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    20:40:35 12/04/2014 
-- Design Name: 
-- Module Name:    spi_mod - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity spi_mod is
   Port ( 	CLK_IN 							: in  STD_LOGIC;
				RST_IN 							: in  STD_LOGIC;
 
				WR_CONTINUOUS_IN 				: in  STD_LOGIC;
				WE_IN 							: in  STD_LOGIC;
				WR_ADDR_IN						: in 	STD_LOGIC_VECTOR (7 downto 0);
				WR_DATA_IN 						: in  STD_LOGIC_VECTOR (7 downto 0);
				WR_DATA_CMPLT_OUT				: out STD_LOGIC;
 
				RD_CONTINUOUS_IN 				: in  STD_LOGIC;
				RD_IN								: in	STD_LOGIC;
				RD_WIDTH_IN 					: in  STD_LOGIC;
				RD_ADDR_IN 						: in  STD_LOGIC_VECTOR (7 downto 0);
				RD_DATA_OUT 					: out STD_LOGIC_VECTOR (7 downto 0);
				RD_DATA_CMPLT_OUT				: out STD_LOGIC;
 
				SLOW_CS_EN_IN					: in STD_LOGIC;
				OPER_CMPLT_POST_CS_OUT 		: out STD_LOGIC;
 
				SDI_OUT				: out STD_LOGIC;
				SDO_IN				: in 	STD_LOGIC;
				SCLK_OUT				: out STD_LOGIC;
				CS_OUT				: out STD_LOGIC);
end spi_mod;
 
architecture Behavioral of spi_mod is
 
constant C_clk_div 				: unsigned(7 downto 0) := X"02";
constant C_spi_clk_polarity 	: std_logic := '0';
constant C_wr_len					: unsigned(3 downto 0) := X"F";
constant C_rd_8len				: unsigned(7 downto 0) := X"0F"; -- 8 bit addr, 8 bit data
constant C_rd_16len				: unsigned(7 downto 0) := X"17"; -- 8 bit addr, 16 bit data
constant C_wr_cont_len			: unsigned(3 downto 0) := X"7";
constant C_rd_cont_len			: unsigned(7 downto 0) := X"07";
constant C_oper_cmplt_init		: unsigned(7 downto 0) := X"00";
 
signal clk_counter : unsigned(7 downto 0) := C_clk_div;
signal clk_div, spi_clk, spi_clk_o : std_logic := '0';
signal cs, cs_p, cs_pp, cs_ppp : std_logic := '1';
signal wr_data_cmplt, rd_data_cmplt : std_logic := '0';
 
signal wr_bit_counter : unsigned(3 downto 0);
signal rd_bit_counter : unsigned(7 downto 0);
 
signal we_ini, we_ini_p, rd_ini, rd_ini_p, doing_wr, doing_rd : std_logic := '0';
signal operation_cmplt : std_logic := '0';
signal operation_cmplt_reg : std_logic_vector(31 downto 0);
signal wr_data_buf, wr_data_buf2 : std_logic_vector(7 downto 0);
signal rd_addr_buf, rd_data_buf : std_logic_vector(7 downto 0) := (others => '0');
signal doing_wr_p, doing_rd_p, load_countinous_wr : std_logic := '0';
signal sdi_p : std_logic := '0';
 
signal operation_cmplt_cntr : unsigned(7 downto 0) := C_oper_cmplt_init;
signal oper_cmplt_post_cs : std_logic := '0';
 
begin
 
	CS_OUT <= cs;
	SCLK_OUT <= spi_clk_o;
	SDI_OUT <= rd_addr_buf(7) when doing_rd = '1' else wr_data_buf(7);
 
	WR_DATA_CMPLT_OUT <= wr_data_cmplt;
	RD_DATA_CMPLT_OUT <= rd_data_cmplt;
 
	OPER_CMPLT_POST_CS_OUT <= oper_cmplt_post_cs;
 
	spi_clk_o <= spi_clk when (cs = '0' and (doing_wr = '1' or doing_rd = '1'))  else C_spi_clk_polarity;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			clk_counter <= clk_counter - 1;
			if clk_counter = X"00" then
				clk_counter <= C_clk_div;
			end if;
			if clk_counter = X"00" then
				clk_div <= '1';
			else
				clk_div <= '0';
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			if clk_div = '1' then
				spi_clk <= not(spi_clk);
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			we_ini_p <= we_ini;
			rd_ini_p <= rd_ini;
			if operation_cmplt = '1' then
				we_ini <= '0';
				rd_ini <= '0';
			elsif we_ini = '0' and rd_ini = '0' then
				if WE_IN = '1' then
					we_ini <= '1';
				elsif WE_IN = '0' and RD_IN = '1' then
					rd_ini <= '1';
				end if;
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			doing_wr_p <= doing_wr;
			doing_rd_p <= doing_rd;
			if we_ini = '1' and clk_div = '1' and spi_clk = '1' then -- start on next falling edge of spi clk
				doing_wr <= '1';
			elsif operation_cmplt = '1' then
				doing_wr <= '0';
			end if;
			if rd_ini = '1' and clk_div = '1' and spi_clk = '1' then -- start on next falling edge of spi clk
				doing_rd <= '1';
			elsif operation_cmplt = '1' then
				doing_rd <= '0';
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			if we_ini_p = '0' and we_ini = '1' then
				wr_data_buf <= WR_ADDR_IN;
				wr_data_buf2 <= WR_DATA_IN;
			elsif load_countinous_wr = '1' then
				wr_data_buf <= WR_DATA_IN;
			elsif doing_wr = '1' and clk_div = '1' and spi_clk_o = '1' then -- shift on falling edge
				wr_data_buf(7 downto 1) <= wr_data_buf(6 downto 0);
				wr_data_buf(0) <= wr_data_buf2(7);
				wr_data_buf2(7 downto 1) <= wr_data_buf2(6 downto 0);
				wr_data_buf2(0) <= '0';
			end if;
			if doing_wr = '1' and clk_div = '1' and spi_clk_o = '1' then
				if wr_bit_counter = X"0" then
					if WR_CONTINUOUS_IN = '1' then
						wr_bit_counter <= C_wr_cont_len;
					end if;
				else
					wr_bit_counter <= wr_bit_counter - 1;
				end if;
			elsif doing_wr = '0' then
				wr_bit_counter <= C_wr_len;
			end if;
			if doing_wr = '1' and clk_div = '1' and spi_clk_o = '1' then
				if wr_bit_counter = X"0" then
					if WR_CONTINUOUS_IN = '1' then
						load_countinous_wr <= '1';
					end if;
				end if;
			else
				load_countinous_wr <= '0';
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			if doing_wr = '1' and clk_div = '1' and spi_clk_o = '0' and wr_bit_counter = X"0" then -- final rising edge of spi clk
				wr_data_cmplt <= '1';
			else
				wr_data_cmplt <= '0';
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			operation_cmplt_reg(0) <= operation_cmplt;
			operation_cmplt_reg(31 downto 1) <= operation_cmplt_reg(30 downto 0);
			if doing_wr = '1' and clk_div = '1' and spi_clk_o = '1' and wr_bit_counter = X"0" and WR_CONTINUOUS_IN = '0' then
				operation_cmplt <= '1';
			elsif doing_rd = '1' and clk_div = '1' and spi_clk_o = '1' and rd_bit_counter = X"00" and RD_CONTINUOUS_IN = '0' then
				operation_cmplt <= '1';
			else
				operation_cmplt <= '0';
			end if;
			if operation_cmplt = '1' or doing_wr = '1' or doing_rd = '1' then
				operation_cmplt_cntr <= C_oper_cmplt_init;
			else
				operation_cmplt_cntr <= operation_cmplt_cntr - 1;
			end if;
			if WE_IN = '1' then
				cs <= '0';
			elsif RD_IN = '1' then
				cs <= '0';
			elsif operation_cmplt_reg(3) = '1' and SLOW_CS_EN_IN = '0' then
				cs <= '1';
			elsif operation_cmplt_reg(19) = '1' and SLOW_CS_EN_IN = '1' then
				cs <= '1';
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			cs_p <= cs;
			cs_pp <= cs_p;
			cs_ppp <= cs_pp;
			if cs_ppp = '0' and cs_pp = '1' then
				oper_cmplt_post_cs <= '1';
			else
				oper_cmplt_post_cs <= '0';
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			if rd_ini_p = '0' and rd_ini = '1' then
				rd_addr_buf <= RD_ADDR_IN;
			elsif doing_rd = '1' and clk_div = '1' and spi_clk_o = '1' then -- shift on falling edge
				rd_addr_buf(7 downto 1) <= rd_addr_buf(6 downto 0);
				rd_addr_buf(0) <= '0';
			end if;
			if doing_rd = '1' and clk_div = '1' and spi_clk_o = '1' then
				if rd_bit_counter = X"00" then
					if RD_CONTINUOUS_IN = '1' then
						rd_bit_counter <= C_rd_cont_len;
					end if;
				else
					rd_bit_counter <= rd_bit_counter - 1;
				end if;
			elsif doing_rd = '0' then
				if RD_WIDTH_IN = '0' then
					rd_bit_counter <= C_rd_8len;
				else
					rd_bit_counter <= C_rd_16len;
				end if;
			end if;
			if doing_rd = '1' and clk_div = '1' and spi_clk_o = '0' then 
				if rd_bit_counter < C_rd_8len then
					rd_data_buf(7 downto 1) <= rd_data_buf(6 downto 0);
					rd_data_buf(0) <= SDO_IN;
				end if;
			end if;
		end if;
	end process;
 
	process(CLK_IN)
	begin
		if rising_edge(CLK_IN) then
			if doing_rd = '1' and clk_div = '1' and spi_clk_o = '1' and rd_bit_counter = X"00" then -- final falling edge of spi clk
				rd_data_cmplt <= '1';
			else
				rd_data_cmplt <= '0';
			end if;
			if doing_rd = '1' and clk_div = '1' and spi_clk_o = '1' and rd_bit_counter = X"00" then -- final falling edge of spi clk
				RD_DATA_OUT <= rd_data_buf;
			end if;
		end if;
	end process;
 
end Behavioral;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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