⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memio.vhd

📁 最新VHDL 模块
💻 VHD
字号:
--
--	memio.vhd
--
--	external memory and IO for JOP3
--
--		addr, wr are one cycle earlier than data
--		dout one cycle after read (ior)
--
--	resources on ACEX1K30-3
--		 24 LCs, xx MHz		only io ports
--		395 LCs, 73 MHz		plus uart and memory
--		777 LCs, 53 MHz		plus ecp and jfetch
--		659 LCs, 67 MHz		without jfetch (for jop3)
--
--	first mapping (for ldp, stp):
--
--		0	io-address
--		1	data read/write
--		2	st	mem_rd_addr		start read
--		2	ld	mem_rd_data		read data
--		3	st	mem_wr_addr		store write address
--		3	ld	mem_status		busy flag
--		4	st	mem_wr_data		start write
--
--	io address mapping:
--
--		0	in, out port (12 Bit)
--		1	status
--		2	uart data (rd/wr)
--		3	reserved for ecp
--		4-6	ext. memory interface
--
--		10	system clock counter (24 MHz)
--		11	ms clock counter
--		12	display out
--		13	keybord (i/o)
--		14	triac out, sense u/i in
--
--	status word:
--		0	uart transmit data register empty
--		1	uart read data register full
--		2	ecp transmit data register empty
--		3	ecp read data register full
--
--
--
--
--	memory mapping (compatible with JOP1)
--	
--		x00000-x7ffff	external ram (w mirror)	max. 512 kW (4*4 MBit)
--		x80000-xfffff	external rom (w mirror)	max. 512 kB (4 MBit)
--
--	ram: 32 bit word
--		mapping ain(16 downto 0) to a(18 downto 2), ignoring ain(18,17)
--	rom: 8 bit word (for flash programming)
--		mapping ain(18 downto 0) to a(18 downto 0)
--
--	todo:
--		ecp, time, byte code fetch,...
--		'real' write and read buffers (read_addr, 2nd write_addr....)
--		mem_bsy could go low again earlier
--			=> new mem start in last state of rd or wr
--		mem_cancel
--		ff against meta stability on all inputs
--
--
--	2001-05-15	first version (only inp, outp)
--	2001-05-27	added uart (from JOP1)
--	2001-05-29	added memory interface
--	2001-06-02	byte code fetch logic
--	2001-06-04	system clock counter
--	2001-06-06	ms counter, jtbl output not registered (1 cycle less on jp)
--				jopd read 16 bit signed or 8 bit unsigned java bc operand
--	2001-06-07	compute java pc branch address from jopd and take it with st jbranch
--	2001-06-08	calculate cond. for ifgt (from accu) and take it with 'st jbrgt'
--	2001-06-10	do all cond branches
--	2001-06-12	added ecp
--	2001-07-14	remove java fetch for jop3
--	2001-07-18	change for Xilinx
--	2001-10-24	changed rom_cnt to 5 (problems with programing!)
--	2001-10-26	changed nrom_cs and nrd to Z/0 (for config PLD) not so good?
--	2001-10-29	indirect addressing
--	2001-11-22	plus display, keyboard, triacs
--	2001-11-30	mem access direct and indirect
--	2001-12-08	only direct mem access, reorder addresses, ioa_width 3
--	2001-12-22	nrom_cs and nrd back to 1/0 (map in jop.vhd)
--
--


Library IEEE ;
use IEEE.std_logic_1164.all ;
use ieee.numeric_std.all ;

entity memio is
generic (clk_freq : integer := 24000000; width : integer := 32; ioa_width : integer := 3;
	pc_width	: integer := 10;	-- address bits of internal instruction rom
	ram_cnt : integer := 3; rom_cnt : integer := 5);

port (

-- jop interface

	clk, reset	: in std_logic;

	din			: in std_logic_vector(width-1 downto 0);
	addr		: in std_logic_vector(ioa_width-1 downto 0);
	rd, wr		: in std_logic;

	dout		: out std_logic_vector(width-1 downto 0);

-- external mem interface

	a			: out std_logic_vector(18 downto 0);
	d			: inout std_logic_vector(7 downto 0);
	nram_cs		: out std_logic;
	nrom_cs		: out std_logic;
	nrd			: out std_logic;
	nwr			: out std_logic;

	max_oe		: out std_logic;

-- serial interface

	txd			: out std_logic;
	rxd			: in std_logic;
	cts			: in std_logic;
	rts			: out std_logic;

-- lpt interface

	lpt_d		: inout std_logic_vector(7 downto 0);
	lpt_s		: out std_logic_vector(7 downto 3);
	lpt_c		: in std_logic_vector(3 downto 0);

-- display

	disp		: out std_logic_vector(5 downto 0);

-- keyboard

	key_in		: in std_logic_vector(3 downto 0);
	key_out		: out std_logic_vector(3 downto 0);

-- triacs

	tr_p		: out std_logic_vector(2 downto 0);
	tr_dir		: out std_logic;
	sense_u		: in std_logic_vector(2 downto 0);
	sense_i		: in std_logic_vector(3 downto 0);

-- io ports

	inp			: in std_logic_vector(11 downto 0);
	outp		: out std_logic_vector(11 downto 0)

);
end memio ;

architecture rtl of memio is

component uart is
generic (clk_freq : integer; baud_rate : integer);
port (
	clk		: in std_logic;
	reset	: in std_logic;

	txd		: out std_logic;
	rxd		: in std_logic;

	din		: in std_logic_vector(7 downto 0);		-- send data
	dout	: out std_logic_vector(7 downto 0);		-- rvc data

	wr		: in std_logic;		-- send data
	tdre	: out std_logic;	-- transmit data register empty

	rd		: in std_logic;		-- read data
	rdrf	: out std_logic;	-- receive data register full

	cts		: in std_logic;
	rts		: out std_logic
);
end component uart;

component ecp is

port (
	clk		: in std_logic;
	reset	: in std_logic;

	lpt_d	: inout std_logic_vector(7 downto 0);
	lpt_s	: out std_logic_vector(7 downto 3);
	lpt_c	: in std_logic_vector(3 downto 0);

	din		: in std_logic_vector(7 downto 0);		-- send data
	dout	: out std_logic_vector(7 downto 0);		-- rvc data

	wr		: in std_logic;			-- send data
	tdre	: out std_logic;		-- transmit data register empty

	rd		: in std_logic;			-- read data
	rdrf	: out std_logic			-- receive data register full
);
end component ecp;


--
--	signals for indirect addressing
--
	signal io_addr			: std_logic_vector(3 downto 0);
	signal io_addr_wr		: std_logic;

	signal port_wr			: std_logic;		-- output port wr ena
	signal disp_wr			: std_logic;
	signal key_wr			: std_logic;
	signal tr_wr			: std_logic;

--
--	signals for uart connection
--
	signal ua_dout			: std_logic_vector(7 downto 0);
	signal ua_wr, ua_tdre	: std_logic;
	signal ua_rd, ua_rdrf	: std_logic;

--
--	signals for ecp connection
--
	signal ecp_dout			: std_logic_vector(7 downto 0);
	signal ecp_wr, ecp_tdre	: std_logic;
	signal ecp_rd, ecp_rdrf	: std_logic;

--
--	signals for mem interface
--
	type state_type		is (
							idl, rd1, rd2, rd3, rd4, wr1, wr2, wr3, wr4
						);
	signal state 		: state_type;

	signal mem_wr_addr		: std_logic_vector(19 downto 0);
	signal mem_dout			: std_logic_vector(width-1 downto 0);
	signal mem_din			: std_logic_vector(width-1 downto 0);
	signal mem_rd			: std_logic;
	signal mem_wr			: std_logic;
	signal mem_bsy			: std_logic;

	signal addr_wr			: std_logic;
	signal nwr_int			: std_logic;
	signal ram_access		: std_logic;

--
--	signal for timers
--
	signal clock_cnt		: unsigned (31 downto 0);
	signal clock_ms			: unsigned (31 downto 0);

begin

	cmp_uart : uart generic map (clk_freq, 115200)
			port map (clk, reset, txd, rxd,
				din(7 downto 0), ua_dout,
				ua_wr, ua_tdre,
				ua_rd, ua_rdrf,
				cts, rts
		);
--	cmp_ecp: ecp port map ( clk, reset, lpt_d, lpt_s, lpt_c,
--		din(7 downto 0), ecp_dout, ecp_wr, ecp_tdre, ecp_rd, ecp_rdrf);
lpt_d <= (others => 'Z');
lpt_s(6 downto 3) <= lpt_c;
lpt_s(7) <= '0';



--
--	read
--
process(clk, reset, rd, addr, io_addr, inp, ua_rdrf, ua_tdre, ua_dout, key_in, sense_u, sense_i)
begin
	if (reset='1') then
		ua_rd <= '0';
		ecp_rd <= '0';
		dout <= std_logic_vector(to_unsigned(0, width));
	elsif rising_edge(clk) then
		ua_rd <= '0';
		ecp_rd <= '0';
		dout <= std_logic_vector(to_unsigned(0, width));

		if (rd='1') then
			if (addr="010") then
				dout <= mem_din;
			elsif (addr="011") then
				dout <= std_logic_vector(to_unsigned(0, width-1)) & mem_bsy;
			else
				case io_addr(3 downto 0) is			-- use only io_addr
					when "0000" =>
						dout <= std_logic_vector(to_unsigned(0, width-12)) & inp;
					when "0001" =>
						dout <= std_logic_vector(to_unsigned(0, width-4)) 
										& ecp_rdrf & ecp_tdre & ua_rdrf & ua_tdre;
					when "0010" =>
						dout <= std_logic_vector(to_unsigned(0, width-8)) & ua_dout;
						ua_rd <= '1';
					when "0011" =>
						dout <= std_logic_vector(to_unsigned(0, width-8)) & ecp_dout;
						ecp_rd <= '1';
					when "1010" =>
						dout <= std_logic_vector(clock_cnt);
					when "1011" =>
						dout <= std_logic_vector(clock_ms);
					when "1101" =>
						dout <= std_logic_vector(to_unsigned(0, width-4)) & key_in;
					when "1110" =>
						dout <= std_logic_vector(to_unsigned(0, width-7)) & sense_i & sense_u;
					when others =>
						null;
				end case;
			end if;
		end if;
	end if;
end process;


--
--	write
--
process(clk, reset, rd, wr)
begin
	if (reset='1') then
		io_addr_wr <= '0';

		ua_wr <= '0';
		ecp_wr <= '0';
		port_wr <= '0';
		mem_rd <= '0';
		mem_wr <= '0';
		addr_wr <= '0';
		disp_wr <= '0';
		key_wr <= '0';
		tr_wr <= '0';


	elsif rising_edge(clk) then
		io_addr_wr <= '0';

		ua_wr <= '0';
		ecp_wr <= '0';
		port_wr <= '0';
		mem_rd <= '0';
		mem_wr <= '0';
		addr_wr <= '0';
		disp_wr <= '0';
		key_wr <= '0';
		tr_wr <= '0';

		if (wr='1') then
			if (addr="000") then
				io_addr_wr <= '1';		-- store real io address
			elsif (addr="010") then
				mem_rd <= '1';			-- start read
			elsif (addr="011") then
				addr_wr <= '1';			-- store write address
			elsif (addr="100") then
				mem_wr <= '1';			-- start write
			else
				case io_addr(3 downto 0) is
					when "0000" =>
						port_wr <= '1';
					when "0010" =>
						ua_wr <= '1';
					when "0011" =>
						ecp_wr <= '1';
					when "1100" =>
						disp_wr <= '1';
					when "1101" =>
						key_wr <= '1';
					when "1110" =>
						tr_wr <= '1';
					when others =>
						null;
				end case;
			end if;
		end if;
	end if;
end process;

--
--	io_addr, port buffer, wr_addr write
--		one cycle after io write (address is avaliable one cycle before ex stage)
--
process(clk, reset, din, port_wr, disp_wr, key_wr, tr_wr, addr_wr)

begin
	if (reset='1') then

		io_addr <= (others => '0');
		outp <= (others => '0');
		mem_wr_addr <= std_logic_vector(to_unsigned(0, 20));
		disp <= (others => '0');
		key_out <= (others => '0');
		tr_p <= (others => '0');
		tr_dir <= '0';

	elsif rising_edge(clk) then

		if (io_addr_wr='1') then
			io_addr <= din(3 downto 0);
		end if;
		if (port_wr='1') then
			outp <= din(11 downto 0);
		end if;
		if (addr_wr='1') then
			mem_wr_addr <= din(19 downto 0);	-- store write address
		end if;
		if (disp_wr='1') then
			disp <= din(5 downto 0);
		end if;
		if (key_wr='1') then
			key_out <= din(3 downto 0);
		end if;
		if (tr_wr='1') then
			tr_p <= din(2 downto 0);
			tr_dir <= din(3);
		end if;

	end if;
end process;


	max_oe <= '0';

--
--	'delay' nwr 1/2 cycle -> change on falling edge
--
process(clk, reset, nwr_int)

begin
	if (reset='1') then
		nwr <= '1';
	elsif falling_edge(clk) then
		nwr <= nwr_int;
	end if;

end process;

--
--	state machine for external memory (single byte static ram, flash)
--
process(clk, reset, din, mem_wr_addr, mem_rd, mem_wr)

	variable i : integer range 0 to 7;

begin
	if (reset='1') then
		state <= idl;
		a <= "ZZZZZZZZZZZZZZZZZZZ";
		d <= "ZZZZZZZZ";
		nram_cs <= '1';
		nrom_cs <= '1';
		nrd <= '1';
		nwr_int <= '1';
		ram_access <= '1';
		mem_din <= std_logic_vector(to_unsigned(0, width));
		mem_dout <= std_logic_vector(to_unsigned(0, width));
		mem_bsy <= '0';

	elsif rising_edge(clk) then

		case state is

			when idl =>
				a <= "ZZZZZZZZZZZZZZZZZZZ";
				d <= "ZZZZZZZZ";
				nrd <= '1';
				nwr_int <= '1';
				nram_cs <= '1';
				nrom_cs <= '1';
				ram_access <= '1';
				mem_bsy <= '0';

				if (mem_rd='1') then
					if (din(19)='1') then
						a <= din(18 downto 0);
						nrom_cs <= '0';
						ram_access <= '0';
						i := rom_cnt;
					else
						a <= din(16 downto 0) & "00";
						nram_cs <= '0';
						ram_access <= '1';
						i := ram_cnt;
					end if;
					mem_bsy <= '1';
					nrd <= '0';
					state <= rd1;
				elsif (mem_wr='1') then
					mem_dout <= din;
					if (mem_wr_addr(19)='1') then
						a <= mem_wr_addr(18 downto 0);
						nrom_cs <= '0';
						ram_access <= '0';
						i := rom_cnt;
					else
						a <= mem_wr_addr(16 downto 0) & "00";
						nram_cs <= '0';
						ram_access <= '1';
						i := ram_cnt;
					end if;
					mem_bsy <= '1';
					nwr_int <= '0';
					state <= wr1;
				end if;

--
--	memory read
--
			when rd1 =>
				i := i-1;
				if (i=0) then
					if (ram_access='1') then
						state <= rd2;
						mem_din(7 downto 0) <= d;
						a(1 downto 0) <= "01";
						i := ram_cnt;
					else
						state <= idl;
						mem_bsy <= '0';
						mem_din <= std_logic_vector(to_unsigned(0, width-8)) & d;
					end if;
				end if;

			when rd2 =>
				i := i-1;
				if (i=0) then
					state <= rd3;
					mem_din(15 downto 8) <= d;
					a(1 downto 0) <= "10";
					i := ram_cnt;
				end if;
					
			when rd3 =>
				i := i-1;
				if (i=0) then
					state <= rd4;
					mem_din(23 downto 16) <= d;
					a(1 downto 0) <= "11";
					i := ram_cnt;
				end if;
					
			when rd4 =>
				i := i-1;
				if (i=0) then
					state <= idl;
					mem_din(31 downto 24) <= d;
					mem_bsy <= '0';
				end if;
--
--	memory write
--
			when wr1 =>
				i := i-1;
				d <= mem_dout(7 downto 0);
				if (i=1) then
					nwr_int <= '1';
				end if;
				if (i=0) then
					if (ram_access='1') then
						nwr_int <= '0';
						state <= wr2;
						a(1 downto 0) <= "01";
						i := ram_cnt;
					else
						state <= idl;
						mem_bsy <= '0';
					end if;
				end if;

			when wr2 =>
				i := i-1;
				d <= mem_dout(15 downto 8);
				nwr_int <= '0';
				if (i=1) then
					nwr_int <= '1';
				end if;
				if (i=0) then
					state <= wr3;
					nwr_int <= '0';
					a(1 downto 0) <= "10";
					i := ram_cnt;
				end if;
					
			when wr3 =>
				i := i-1;
				d <= mem_dout(23 downto 16);
				if (i=1) then
					nwr_int <= '1';
				end if;
				if (i=0) then
					state <= wr4;
					nwr_int <= '0';
					a(1 downto 0) <= "11";
					i := ram_cnt;
				end if;
					
			when wr4 =>
				i := i-1;
				d <= mem_dout(31 downto 24);
				if (i=1) then
					nwr_int <= '1';
				end if;
				if (i=0) then
					state <= idl;
					mem_bsy <= '0';
					nwr_int <= '1';
				end if;
					
		end case;
					
	end if;
end process;

--
--	24 MHz clock
--

process(clk, reset)

begin
	if (reset='1') then
		clock_cnt <= to_unsigned(0, clock_cnt'length);

	elsif rising_edge(clk) then
		clock_cnt <= clock_cnt+1;
	end if;

end process;

process(clk, reset)

	variable div		: integer range 0 to 23999;

begin
	if (reset='1') then
		div := 0;
		clock_ms <= to_unsigned(0, clock_ms'length);

	elsif rising_edge(clk) then

		if (div=23999) then		-- 24 MHz
			div := 0;
			clock_ms <= clock_ms+1;
		else
			div := div+1;
		end if;

	end if;

end process;

end rtl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -