--
--	plasma_cyc.vhd
--
--	top level of plasma for cycore borad with EP1C12
--
--	2007-04-24	creation
--
--


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity plasma_cyc is

generic (
	ram_cnt		: integer := 2		-- clock cycles for external ram
);

port (
	clk		: in std_logic;
--
--	serial interface
--
	ser_txd			: out std_logic;
	ser_rxd			: in std_logic;
	ser_ncts		: in std_logic;
	ser_nrts		: out std_logic;

--
--	watchdog
--
	wd		: out std_logic;
	freeio	: out std_logic;

--
--	two ram banks
--
	rama_a		: out std_logic_vector(17 downto 0);
	rama_d		: inout std_logic_vector(15 downto 0);
	rama_ncs	: out std_logic;
	rama_noe	: out std_logic;
	rama_nlb	: out std_logic;
	rama_nub	: out std_logic;
	rama_nwe	: out std_logic;
	ramb_a		: out std_logic_vector(17 downto 0);
	ramb_d		: inout std_logic_vector(15 downto 0);
	ramb_ncs	: out std_logic;
	ramb_noe	: out std_logic;
	ramb_nlb	: out std_logic;
	ramb_nub	: out std_logic;
	ramb_nwe	: out std_logic;

--
--	config/program flash and big nand flash
--
	fl_a	: out std_logic_vector(18 downto 0);
	fl_d	: inout std_logic_vector(7 downto 0);
	fl_ncs	: out std_logic;
	fl_ncsb	: out std_logic;
	fl_noe	: out std_logic;
	fl_nwe	: out std_logic;
	fl_rdy	: in std_logic;

--
--	I/O pins of board
--
	io_b	: inout std_logic_vector(10 downto 1);
	io_l	: inout std_logic_vector(20 downto 1);
	io_r	: inout std_logic_vector(20 downto 1);
	io_t	: inout std_logic_vector(6 downto 1)
);
end plasma_cyc;

architecture rtl of plasma_cyc is

--
--	components:
--

--component pll is
--generic (multiply_by : natural; divide_by : natural);
--port (
--	inclk0		: in std_logic;
--	c0			: out std_logic
--);
--end component;

--
--	Signals
--
	signal clk_int			: std_logic;

	signal int_res			: std_logic;
	signal res_cnt			: unsigned(2 downto 0) := "000";	-- for the simulation

	attribute altera_attribute : string;
	attribute altera_attribute of res_cnt : signal is "POWER_UP_LEVEL=LOW";

--
--	plasma memory connection
--
   signal mem_address  : std_logic_vector(31 downto 2);
   signal data_write   : std_logic_vector(31 downto 0);
   signal data_reg     : std_logic_vector(31 downto 0);
   signal write_byte_enable : std_logic_vector(3 downto 0);
   signal mem_pause_in : std_logic;

   signal gpio0_out   : std_logic_vector(31 downto 0);
   signal gpioA_in    : std_logic_vector(31 downto 0);

	signal wd_out			: std_logic;
	signal nwe				: std_logic;
	signal we_dly			: std_logic;

-- memory interface

	signal ram_addr			: std_logic_vector(17 downto 0);
	signal ram_dout			: std_logic_vector(31 downto 0);
	signal ram_din			: std_logic_vector(31 downto 0);
	signal ram_dout_en		: std_logic;
	signal ram_ncs			: std_logic;
	signal ram_noe			: std_logic;
	signal ram_nwe			: std_logic;

begin

--
--	intern reset
--	no extern reset, epm7064 has too less pins
--

process(clk_int)
begin
	if rising_edge(clk_int) then
		if (res_cnt/="111") then
			res_cnt <= res_cnt+1;
		end if;

		int_res <= not res_cnt(0) or not res_cnt(1) or not res_cnt(2);
	end if;
end process;

--
--	components of jop
--
--	pll_inst : pll generic map(
--		multiply_by => pll_mult,
--		divide_by => pll_div
--	)
--	port map (
--		inclk0	 => clk,
--		c0	 => clk_int
--	);
	clk_int <= clk;

--
--	delayed RAM nwe with neg. edge clock
--
process(clk_int)
begin
	if falling_edge(clk_int) then
		ram_nwe <= nwe;
	end if;
end process;

	wd <= wd_out;

--
--	issue with plasma:
--		no signal when a read (or write starts)
--		how shall we implement the wait state logic?
--			on an address change???
--
--	minor issue (typical in some designs):
--		RAM address is on a combinatorial path from the register file
--		RAM read is in a combinatorial path to the register file
--			no registers in the pins are possible (except with explicite wait states)
--
--	regiter file issue:
--		there is no pipeline stage for the register read
--		Therefore, the register file, and the resulting read muxes,
--		have to be implemented in LCs!
--

   u1_plasma: entity work.plasma 
      generic map (memory_type => "ALTERA_LPM",
                   log_file    => "UNUSED")
      PORT MAP (
         clk               => clk_int,
         reset             => int_res,
         uart_write        => ser_txd,
         uart_read         => ser_rxd,
 
         address           => mem_address,
         data_write        => ram_dout,
         data_read         => ram_din,
         write_byte_enable => write_byte_enable,
         mem_pause_in      => mem_pause_in,
         
         gpio0_out         => gpio0_out,
         gpioA_in          => gpioA_in);
         
	ser_nrts <= '0';
	gpioA_in <= (others => '0');

	wd_out <= gpio0_out(0);


process(clk, int_res)
begin
	if (int_res = '1') then
		we_dly <= '0';
	elsif rising_edge(clk) then
		we_dly <= not nwe;
	end if;
end process;

	mem_pause_in <= not nwe and not we_dly;

   ram_control:   
   process(mem_address, write_byte_enable, data_write, we_dly)
   begin

      ram_dout_en <= '0';
      ram_ncs <= '1';
      ramb_nub <= '1';
      ramb_nlb <= '1';
      rama_nub <= '1';
      rama_nlb <= '1';
      nwe <= '1';
      ram_noe  <= '1';

      if mem_address(30 downto 28) = "001" then  --RAM
         ram_ncs <= '0';
         if write_byte_enable = "0000" then      --read
            ram_dout_en <= '0';
            nwe <= '1';
            ram_noe  <= '0';
            ramb_nub <= '0';
            ramb_nlb <= '0';
            rama_nub <= '0';
			rama_nlb <= '0';
         else                                    --write
            ram_dout_en <= '1';
			if we_dly='0' then
            	nwe <= '0';
			end if;
            ram_noe  <= '1';
            ramb_nub <= not write_byte_enable(3);
            ramb_nlb <= not write_byte_enable(2);
            rama_nub <= not write_byte_enable(1);
            rama_nlb <= not write_byte_enable(0);
         end if;
      end if;
   end process; --ram_control

	ram_addr <= mem_address(19 downto 2);

	process(ram_dout_en, ram_dout)
	begin
		if ram_dout_en='1' then
			rama_d <= ram_dout(15 downto 0);
			ramb_d <= ram_dout(31 downto 16);
		else
			rama_d <= (others => 'Z');
			ramb_d <= (others => 'Z');
		end if;
	end process;
	ram_din <= ramb_d & rama_d;

	rama_a <= ram_addr;
	rama_ncs <= ram_ncs;
	rama_noe <= ram_noe;
	rama_nwe <= ram_nwe;

	ramb_a <= ram_addr;
	ramb_ncs <= ram_ncs;
	ramb_noe <= ram_noe;
	ramb_nwe <= ram_nwe;

	freeio <= 'Z';

	fl_ncs <= '1';
	fl_ncsb <= '1';
	fl_nwe <= '1';
	fl_noe <= '1';

end rtl;
