repo2/sockit/avalon_arm_regs.vhdl
311 | markw | ---------------------------------------------------------------------------
|
|
-- (c) 2014 mark watson
|
|||
-- I am happy for anyone to use this for non-commercial use.
|
|||
-- If my vhdl files are used commercially or otherwise sold,
|
|||
-- please contact me for explicit permission at scrameta (gmail).
|
|||
-- This applies for source and binary form and derived works.
|
|||
---------------------------------------------------------------------------
|
|||
LIBRARY ieee;
|
|||
USE ieee.std_logic_1164.all;
|
|||
use ieee.numeric_std.all;
|
|||
ENTITY avalon_arm_regs IS
|
|||
GENERIC
|
|||
(
|
|||
platform : integer := 1 -- So ROM can detect which type of system...
|
|||
);
|
|||
PORT
|
|||
(
|
|||
CLK : IN STD_LOGIC;
|
|||
RESET_N : IN STD_LOGIC;
|
|||
POKEY_ENABLE : in std_logic;
|
|||
-- avalon signals
|
|||
CHIPSELECT : IN STD_LOGIC;
|
|||
ADDRESS : IN STD_LOGIC_VECTOR(10 downto 0);
|
|||
READ: IN STD_LOGIC;
|
|||
READDATA : OUT STD_LOGIC_VECTOR(31 downto 0);
|
|||
WRITE : IN STD_LOGIC;
|
|||
WRITEDATA : IN STD_LOGIC_VECTOR(31 downto 0);
|
|||
BYTEENABLE : IN STD_LOGIC_VECTOR(3 downto 0);
|
|||
-- GENERIC INPUT REGS (need to synchronize upstream...)
|
|||
IN1 : in std_logic_vector(31 downto 0);
|
|||
IN2 : in std_logic_vector(31 downto 0);
|
|||
IN3 : in std_logic_vector(31 downto 0);
|
|||
IN4 : in std_logic_vector(31 downto 0);
|
|||
-- GENERIC OUTPUT REGS
|
|||
OUT1 : out std_logic_vector(31 downto 0);
|
|||
OUT2 : out std_logic_vector(31 downto 0);
|
|||
OUT3 : out std_logic_vector(31 downto 0);
|
|||
OUT4 : out std_logic_vector(31 downto 0);
|
|||
OUT5 : out std_logic_vector(31 downto 0);
|
|||
OUT6 : out std_logic_vector(31 downto 0);
|
|||
-- ATARI interface (in future we can also turbo load by directly hitting memory...)
|
|||
SIO_DATA_IN : out std_logic;
|
|||
SIO_COMMAND : in std_logic;
|
|||
SIO_DATA_OUT : in std_logic
|
|||
);
|
|||
END avalon_arm_regs;
|
|||
ARCHITECTURE vhdl OF avalon_arm_regs IS
|
|||
function vectorize(s: std_logic) return std_logic_vector is
|
|||
variable v: std_logic_vector(0 downto 0);
|
|||
begin
|
|||
v(0) := s;
|
|||
return v;
|
|||
end;
|
|||
signal device_decoded : std_logic_vector(7 downto 0);
|
|||
signal device_wr_en : std_logic_vector(7 downto 0);
|
|||
signal device_rd_en : std_logic_vector(7 downto 0);
|
|||
signal addr_decoded : std_logic_vector(15 downto 0);
|
|||
signal out1_next : std_logic_vector(31 downto 0);
|
|||
signal out1_reg : std_logic_vector(31 downto 0);
|
|||
signal out2_next : std_logic_vector(31 downto 0);
|
|||
signal out2_reg : std_logic_vector(31 downto 0);
|
|||
signal out3_next : std_logic_vector(31 downto 0);
|
|||
signal out3_reg : std_logic_vector(31 downto 0);
|
|||
signal out4_next : std_logic_vector(31 downto 0);
|
|||
signal out4_reg : std_logic_vector(31 downto 0);
|
|||
signal out5_next : std_logic_vector(31 downto 0);
|
|||
signal out5_reg : std_logic_vector(31 downto 0);
|
|||
signal out6_next : std_logic_vector(31 downto 0);
|
|||
signal out6_reg : std_logic_vector(31 downto 0);
|
|||
signal pokey_data_out : std_logic_vector(7 downto 0);
|
|||
signal subtimer_next : std_logic_vector(10 downto 0);
|
|||
signal subtimer_reg : std_logic_vector(10 downto 0);
|
|||
signal timer_next : std_logic_vector(31 downto 0);
|
|||
signal timer_reg : std_logic_vector(31 downto 0);
|
|||
signal data_out_regs : std_logic_vector(31 downto 0);
|
|||
signal data_out_mux : std_logic_vector(31 downto 0);
|
|||
signal read_sel : std_logic;
|
|||
signal write_sel : std_logic;
|
|||
begin
|
|||
-- register
|
|||
process(clk,reset_n)
|
|||
begin
|
|||
if (reset_n='0') then
|
|||
out1_reg <= (others=>'0');
|
|||
out2_reg <= (others=>'0');
|
|||
out3_reg <= (others=>'0');
|
|||
out4_reg <= (others=>'0');
|
|||
out5_reg <= (others=>'0');
|
|||
out6_reg <= (others=>'0');
|
|||
subtimer_reg <= (others=>'0');
|
|||
timer_reg <= (others=>'0');
|
|||
elsif (clk'event and clk='1') then
|
|||
out1_reg <= out1_next;
|
|||
out2_reg <= out2_next;
|
|||
out3_reg <= out3_next;
|
|||
out4_reg <= out4_next;
|
|||
out5_reg <= out5_next;
|
|||
out6_reg <= out6_next;
|
|||
subtimer_reg <= subtimer_next;
|
|||
timer_reg <= timer_next;
|
|||
end if;
|
|||
end process;
|
|||
-- decode address
|
|||
decode_addr : entity work.complete_address_decoder
|
|||
generic map(width=>4)
|
|||
port map (addr_in=>address(3 downto 0), addr_decoded=>addr_decoded);
|
|||
decode_device : entity work.complete_address_decoder
|
|||
generic map(width=>3)
|
|||
port map (addr_in=>address(10 downto 8), addr_decoded=>device_decoded);
|
|||
-- device decode
|
|||
-- 0x000 - own regs (0)
|
|||
-- 0x100 - pokey (1)
|
|||
write_sel <= write and chipselect;
|
|||
read_sel <= read and chipselect;
|
|||
device_wr_en <= device_decoded and (write_sel&write_sel&write_sel&write_sel&write_sel&write_sel&write_sel&write_sel);
|
|||
device_rd_en <= device_decoded and (read_sel&read_sel&read_sel&read_sel&read_sel&read_sel&read_sel&read_sel);
|
|||
-- uart - another Pokey! Running at atari frequency.
|
|||
-- with a state machine to capture command packets
|
|||
-- can not easily poll frequently enough with zpu when also polling usb
|
|||
-- pokey1 : entity work.pokey
|
|||
-- port map (clk=>clk,ENABLE_179=>pokey_enable,addr=>addr(3 downto 0),data_in=>WRITEDATA(7 downto 0),wr_en=>device_wr_en(1),
|
|||
-- reset_n=>reset_n,keyboard_response=>"11",pot_in=>X"00",
|
|||
-- sio_in1=>sio_data_out,sio_in2=>'1',sio_in3=>'1', -- TODO, pokey dir...
|
|||
-- data_out=>pokey_data_out,
|
|||
-- sio_out1=>sio_data_in);
|
|||
pokey1 : entity work.sio_device
|
|||
PORT MAP
|
|||
(
|
|||
CLK => CLK,
|
|||
ADDR => address(4 downto 0),
|
|||
CPU_DATA_IN => WRITEDATA(7 downto 0),
|
|||
EN => device_rd_en(1),
|
|||
WR_EN => device_wr_en(1),
|
|||
RESET_N => reset_n,
|
|||
POKEY_ENABLE => pokey_enable,
|
|||
SIO_DATA_IN => sio_data_in,
|
|||
SIO_COMMAND => sio_command,
|
|||
SIO_DATA_OUT => sio_data_out,
|
|||
-- CPU interface
|
|||
DATA_OUT => pokey_data_out
|
|||
);
|
|||
-- timer for approx ms
|
|||
process(timer_reg,subtimer_reg, pokey_enable)
|
|||
begin
|
|||
timer_next <= timer_reg;
|
|||
subtimer_next <= subtimer_reg;
|
|||
if (pokey_enable = '1') then
|
|||
subtimer_next <= std_logic_vector(unsigned(subtimer_reg)-1);
|
|||
end if;
|
|||
if (subtimer_reg = "000"&x"00") then
|
|||
subtimer_next <= std_logic_vector(to_unsigned(11#1790#,11));
|
|||
timer_next <= std_logic_vector(unsigned(timer_reg)+1);
|
|||
end if;
|
|||
end process;
|
|||
process(device_decoded, data_out_regs, pokey_data_out)
|
|||
begin
|
|||
data_out_mux <= (others=>'0');
|
|||
if (device_decoded(0) = '1') then
|
|||
data_out_mux <= data_out_regs;
|
|||
end if;
|
|||
if (device_decoded(1) = '1') then
|
|||
data_out_mux(7 downto 0) <= pokey_data_out;
|
|||
end if;
|
|||
end process;
|
|||
-- hardware regs for ZPU
|
|||
--
|
|||
-- 0-3: GENERIC INPUT (RO)
|
|||
-- 4-7: GENERIC OUTPUT (R/W)
|
|||
-- 8: W:PAUSE, R:Timer (1ms)
|
|||
-- 9: SPI_DATA
|
|||
-- SPI_DATA (DONE)
|
|||
-- W - write data (starts transmission)
|
|||
-- R - read data (wait for complete first)
|
|||
-- 10: SPI_STATE
|
|||
-- SPI_STATE/SPI_CTRL (DONE)
|
|||
-- R: 0=busy
|
|||
-- W: 0=select_n, speed
|
|||
-- 11: SIO
|
|||
-- SIO
|
|||
-- R: 0=CMD
|
|||
-- 12: TYPE
|
|||
-- FPGA board (DONE)
|
|||
-- R(32 bits) 0=DE1
|
|||
-- 13 : SPI_DMA
|
|||
-- W(15 downto 0 = addr),(31 downto 16 = endAddr)
|
|||
-- 14-15 : GENERIC OUTPUT (R/W)
|
|||
-- 16-31: POKEY! Low bytes only... i.e. pokey reg every 4 bytes...
|
|||
-- Writes to registers
|
|||
process(WRITEDATA,device_wr_en,address,addr_decoded, out1_reg, out2_reg, out3_reg, out4_reg, out5_reg, out6_reg, pokey_enable)
|
|||
begin
|
|||
out1_next <= out1_reg;
|
|||
out2_next <= out2_reg;
|
|||
out3_next <= out3_reg;
|
|||
out4_next <= out4_reg;
|
|||
out5_next <= out5_reg;
|
|||
out6_next <= out6_reg;
|
|||
if (device_wr_en(0) = '1') then
|
|||
if(addr_decoded(4) = '1') then
|
|||
out1_next <= WRITEDATA;
|
|||
end if;
|
|||
if(addr_decoded(5) = '1') then
|
|||
out2_next <= WRITEDATA;
|
|||
end if;
|
|||
if(addr_decoded(6) = '1') then
|
|||
out3_next <= WRITEDATA;
|
|||
end if;
|
|||
if(addr_decoded(7) = '1') then
|
|||
out4_next <= WRITEDATA;
|
|||
end if;
|
|||
if(addr_decoded(14) = '1') then
|
|||
out5_next <= WRITEDATA;
|
|||
end if;
|
|||
if(addr_decoded(15) = '1') then
|
|||
out6_next <= WRITEDATA;
|
|||
end if;
|
|||
end if;
|
|||
end process;
|
|||
-- Read from registers
|
|||
process(address,addr_decoded, in1, in2, in3, in4, out1_reg, out2_reg, out3_reg, out4_reg, out5_reg, out6_reg, SIO_COMMAND, timer_reg)
|
|||
begin
|
|||
data_out_regs <= (others=>'0');
|
|||
if (addr_decoded(0) = '1') then
|
|||
data_out_regs <= in1;
|
|||
end if;
|
|||
if (addr_decoded(1) = '1') then
|
|||
data_out_regs <= in2;
|
|||
end if;
|
|||
if (addr_decoded(2) = '1') then
|
|||
data_out_regs <= in3;
|
|||
end if;
|
|||
if (addr_decoded(3) = '1') then
|
|||
data_out_regs <= in4;
|
|||
end if;
|
|||
if (addr_decoded(4) = '1') then
|
|||
data_out_regs <= out1_reg;
|
|||
end if;
|
|||
if (addr_decoded(5) = '1') then
|
|||
data_out_regs <= out2_reg;
|
|||
end if;
|
|||
if (addr_decoded(6) = '1') then
|
|||
data_out_regs <= out3_reg;
|
|||
end if;
|
|||
if (addr_decoded(7) = '1') then
|
|||
data_out_regs <= out4_reg;
|
|||
end if;
|
|||
if (addr_decoded(14) = '1') then
|
|||
data_out_regs <= out5_reg;
|
|||
end if;
|
|||
if (addr_decoded(15) = '1') then
|
|||
data_out_regs <= out6_reg;
|
|||
end if;
|
|||
if (addr_decoded(8) = '1') then
|
|||
data_out_regs <= timer_reg;
|
|||
end if;
|
|||
if(addr_decoded(11) = '1') then
|
|||
data_out_regs(0) <= SIO_COMMAND;
|
|||
end if;
|
|||
if (addr_decoded(12) = '1') then
|
|||
data_out_regs <= std_logic_vector(to_unsigned(platform,32));
|
|||
end if;
|
|||
end process;
|
|||
-- outputs
|
|||
out1 <= out1_reg;
|
|||
out2 <= out2_reg;
|
|||
out3 <= out3_reg;
|
|||
out4 <= out4_reg;
|
|||
out5 <= out5_reg;
|
|||
out6 <= out6_reg;
|
|||
READDATA <= data_out_mux;
|
|||
end vhdl;
|
|||