trashernet-soc/fpga/hdl/design/aps6404l_wb.vhd

137 lines
3.6 KiB
VHDL

-- -------------------------------------------------------------------------- --
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
-- -------------------------------------------------------------------------- --
-- TODO
-- -------------------------------------------------------------------------- --
-- Author : Markus Koch <markus@notsyncing.net>
-- Contributors : None
-- License : Mozilla Public License (MPL) Version 2
-- -------------------------------------------------------------------------- --
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library generics;
use generics.wishbone_pkg.all;
entity aps6404l_wb is
port(
clk : in std_logic;
rst : in std_logic; --
-- Wishbone IF
wb_o : out wishbone_slave_out; -- Wishbone bus (out)
wb_i : in wishbone_slave_in; -- Wishbone bus (in)
-- PSRAM IF
psram_ce_n : out std_logic;
psram_sclk : out std_logic;
psram_sio : inout std_logic_vector(3 downto 0) --
);
end entity aps6404l_wb;
architecture rtl of aps6404l_wb is
signal apsc_addr : std_logic_vector(23 downto 0);
signal apsc_data_in : std_logic_vector(7 downto 0);
signal apsc_data_in_next : std_logic;
signal apsc_data_out : std_logic_vector(7 downto 0);
signal apsc_data_out_valid : std_logic;
signal apsc_write_en : std_logic;
signal apsc_read_en : std_logic;
signal bit_cnt : integer range 0 to 4;
signal data : std_logic_vector(wb_i.dat'range);
begin
aps6404l_controller_inst : entity work.aps6404l_controller
port map(
clk => clk,
rst => rst,
addr => apsc_addr,
data_in => apsc_data_in,
data_in_next => apsc_data_in_next,
data_out => apsc_data_out,
data_out_valid => apsc_data_out_valid,
write_en => apsc_write_en,
read_en => apsc_read_en,
psram_ce_n => psram_ce_n,
psram_sclk => psram_sclk,
psram_sio => psram_sio
);
main : process(clk, rst) is
variable start_addr : integer range 0 to 3;
variable stop_addr : integer range 0 to 3;
variable success : std_logic;
begin
if rst then
wb_o.ack <= '0';
bit_cnt <= 0;
elsif rising_edge(clk) then
wb_o.ack <= '0';
if bit_cnt = 0 then
apsc_read_en <= '0';
apsc_write_en <= '0';
start_addr := 0;
for i in 0 to 3 loop
if wb_i.sel(i) = '1' then
start_addr := i;
exit;
end if;
end loop;
stop_addr := 0;
for i in 3 downto 0 loop
if wb_i.sel(i) = '1' then
stop_addr := i;
exit;
end if;
end loop;
apsc_addr <= wb_i.adr(apsc_addr'length - 1 downto 2) & std_logic_vector(to_unsigned(start_addr, 2));
data <= wb_i.dat;
if not wb_o.ack and wb_i.stb and wb_i.cyc then
bit_cnt <= 4;
end if;
else
success := '0';
if bit_cnt >= (4 - stop_addr) and bit_cnt <= (4 - start_addr) then
apsc_read_en <= not wb_i.we;
apsc_write_en <= wb_i.we;
else
apsc_read_en <= '0';
apsc_write_en <= '0';
success := '1';
end if;
if wb_i.we and apsc_data_in_next then
success := '1';
elsif not wb_i.we and apsc_data_out_valid then
success := '1';
end if;
if success then
bit_cnt <= bit_cnt - 1;
wb_o.dat <= apsc_data_out & wb_o.dat(wb_o.dat'high downto 8);
data <= x"--" & data(data'high downto 8);
if bit_cnt = 1 then
wb_o.ack <= '1';
end if;
end if;
end if;
end if;
end process main;
apsc_data_in <= data(apsc_data_in'range);
wb_o.err <= '0';
wb_o.rty <= '0';
wb_o.stall <= not wb_o.ack;
end architecture rtl;