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

Subversion Repositories simpcon

[/] [simpcon/] [trunk/] [vhdl/] [sc_spi.vhd] - Rev 29

Compare with Previous | Blame | View Log

--
--
--		address map:
--
--			0	SS Register
--			1	SCLK Divider
--			2	Data in
--			3	Data out
--			4	Interrupt Config Status
--
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.jop_types.all;
 
entity sc_spi is
 
generic (addr_bits : integer;
	clk_freq : integer);
port (
	clk		: in std_logic;
	reset	: in std_logic;
 
-- SimpCon interface
 
	address		: in std_logic_vector(addr_bits-1 downto 0);
	wr_data		: in std_logic_vector(31 downto 0);
	rd, wr		: in std_logic;
	rd_data		: out std_logic_vector(31 downto 0);
	rdy_cnt		: out unsigned(1 downto 0);
 
-- SPI Con
 
	slave_s	: out std_logic_vector(7 downto 0);
	miso	: in std_logic;
	mosi	: out std_logic;
	sclk	: out std_logic;
 
);
end sc_spi;
 
architecture rtl of sc_spi is
 
	signal spi_out		: std_logic_vector(7 downto 0);
	signal spi_in		: std_logic_vector(7 downto 0);
 
	signal read_ack		: std_logic;
	signal fifo_wr	: std_logic;
 
--
--	
	constant WS		: integer := (clk_freq/20000000)+1;
	signal cnt			: integer range 0 to WS;
 
--
--	FIFO signals
--
	signal tf_dout		: std_logic_vector(7 downto 0); -- fifo out
	signal tf_rd		: std_logic;
	signal tf_empty		: std_logic;
	signal tf_full		: std_logic;
 
	signal rf_din		: std_logic_vector(7 downto 0); -- fifo input
	signal rf_wr		: std_logic;
	signal rf_empty		: std_logic;
	signal rf_full		: std_logic;
 
 
--
--	USB interface signals
--
	type state_type		is (idle, inact, rx1, rx2, tx1, tx2);
	signal state 		: state_type;
 
	signal spi_dout		: std_logic_vector(7 downto 0);
	signal spi_din		: std_logic_vector(7 downto 0);
 
	--signal nrxf_buf		: std_logic_vector(1 downto 0);
	--signal ntxe_buf		: std_logic_vector(1 downto 0);
	--signal rdr, wrr		: std_logic_vector(7 downto 0);
	--signal data_oe		: std_logic;
 
begin
 
	rdy_cnt <= "00";	-- no wait states
	rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24));
--
--	The registered MUX is all we need for a SimpCon read.
--	The read data is stored in registered rd_data.
--
process(clk, reset)
begin
 
	if (reset='1') then
		rd_data(7 downto 0) <= (others => '0');
	elsif rising_edge(clk) then
 
		read_ack <= '0';
		if rd='1' then
			case address(2 downto 0) is
				when "000" =>
					rd_data(7 downto 0) <= slave_s;
					rd_data(31 downto 8) <= (others => '0');
				when "001" =>
					rd_data(7 downto 0) <= WS;
					rd_data(31 downto 8) <= (others => '0');
				when "010" =>
					rd_data(7 downto 0) <= spi_din;
					rd_data(31 downto 8) <= (others => '0');
				when "011" =>
					rd_data(7 downto 0) <= spi_dout;
					rd_data(31 downto 8) <= (others => '0');	
				when "100" =>
					rd_data(7 downto 0) <= spi_dout;
					rd_data(31 downto 8) <= (others => '0');						
--				when "111" =>
				when others =>
					rd_data(0) <= '0';
					rd_data(31 downto 1) <= (others => '0');
			end case;
		end if;
	end if;
 
			if wr='1' then
			case address(2 downto 0) is
				when "000" =>
					irq_in.irq_ena <= wr_data(0);
				when "001" =>
					irq_cnt <= wr_data;
					int_ack <= '1';
				when "010" =>
					spi_din <= wr_data;;
				when "011" =>
					spi_dout <= wr_data;;
				when "100" =>
					spi_dout <= wr_data;;
				when "110" =>
					-- nothing, processor id is read only
				when others =>
--				when "111" =>
					sync_in.s_in <= wr_data(0);
			end case;
		end if;
 
end process;
 
 
	-- we don't use the send immediate
	nsi <= '1';
 
 
--
--	receive fifo
--
	rxfifo: entity work.fifo generic map (
				width => 8,
				depth => 4,
				thres => 2	-- we don't care about the half signal
			) port map (
				clk => clk,
				reset => reset,
				din => rf_din,
				dout => usb_dout,
				rd => read_ack,
				wr => rf_wr,
				empty => rf_empty,
				full => rf_full,
				half => open
			);
 
--
--	transmit fifo
--
	txfifo: entity work.fifo generic map (
				width => 8,
				depth => 4,
				thres => 2	-- we don't care about the half signal
			) port map (
				clk => clk,
				reset => reset,
				din => wr_data(7 downto 0),
				dout => tf_dout,
				rd => tf_rd,
				wr => fifo_wr,
				empty => tf_empty,
				full => tf_full,
				half => open
			);
 
 
--
--	state machine for the usb bus
--
process(clk, reset)
 
begin
 
	if (reset='1') then
		state <= idle;
		nrxf_buf <= "11";
		ntxe_buf <= "11";
		cnt <= WS;
 
		rdr <= (others => '0');
		wrr <= (others => '0');
 
		tf_rd <= '0';
		rf_wr <= '0';
 
		nrd <= '1';
		ft_wr <= '0';
 
	elsif rising_edge(clk) then
 
		-- input register
		nrxf_buf(0) <= nrxf;
		nrxf_buf(1) <= nrxf_buf(0);
		ntxe_buf(0) <= ntxe;
		ntxe_buf(1) <= ntxe_buf(0);
 
		case state is
 
			when idle =>
				cnt <= WS;
				tf_rd <= '0';
				rf_wr <= '0';
				nrd <= '1';
				ft_wr <= '0';
				data_oe <= '0';
				if rf_full='0' and nrxf_buf(1)='0' then
					nrd <= '0';
					state <= rx1;
				elsif tf_empty='0' and ntxe_buf(1)='0' then
					ft_wr <= '1';
					wrr <= tf_dout;
					tf_rd <= '1';
					state <= tx1;
				end if;
 
			when inact =>
				tf_rd <= '0';
				rf_wr <= '0';
				nrd <= '1';
				ft_wr <= '0';
				data_oe <= '0';
				cnt <= cnt-1;
				if cnt=0 then
					state <= idle;
				end if;
 
 
			when rx1 =>
				cnt <= cnt-1;
				if cnt=0 then
					state <= rx2;
					rdr <= data;
				end if;
 
			when rx2 =>
				nrd <= '1';
				rf_wr <= '1';
				cnt <= WS;
				state <= inact;
 
			when tx1 =>
				tf_rd <= '0';
				data_oe <= '1';
				cnt <= cnt-1;
				if cnt=0 then
					state <= tx2;
					ft_wr <= '0';
				end if;
 
			when tx2 =>
				data_oe <= '0';
				cnt <= WS;
				state <= inact;
 
		end case;
	end if;
 
end process;
 
	data <= wrr when data_oe='1' else (others => 'Z');
	rf_din <= data;
 
end rtl;
 

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.