179 lines
4.7 KiB
VHDL
179 lines
4.7 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;
|
|
|
|
use std.textio.all;
|
|
|
|
entity aps6404l is
|
|
generic(
|
|
LOG_EN : boolean := true
|
|
);
|
|
port(
|
|
ce_n : in std_logic;
|
|
sclk : in std_logic;
|
|
sio : inout std_logic_vector(3 downto 0)
|
|
);
|
|
end entity aps6404l;
|
|
|
|
architecture bench of aps6404l is
|
|
procedure print(text : string) is
|
|
variable buf : line;
|
|
begin
|
|
if not LOG_EN then
|
|
return;
|
|
end if;
|
|
write(buf, string'("aps6404l: "));
|
|
write(buf, text);
|
|
WriteLine(OUTPUT, buf);
|
|
end procedure print;
|
|
|
|
begin
|
|
test : process is
|
|
type rx_state_t is (COMMAND, READ, WRITE, COMPLETE);
|
|
type byte_vector is array (natural range <>) of std_logic_vector(7 downto 0);
|
|
variable mem : byte_vector(0 to 1023);
|
|
variable bytes : byte_vector(0 to 32);
|
|
variable cnt, bytecnt : integer;
|
|
variable state : rx_state_t;
|
|
|
|
variable mode : integer := 0;
|
|
variable wrap_boundary : boolean := false;
|
|
|
|
variable dout : std_logic_vector(7 downto 0);
|
|
variable addr : integer;
|
|
|
|
variable sio_temp : std_logic_vector(sio'range);
|
|
|
|
procedure handle(command_edge : boolean) is
|
|
begin
|
|
if command_edge then
|
|
case state is
|
|
when COMMAND =>
|
|
case bytes(0) is
|
|
when x"66" =>
|
|
print(" SPI reset enter");
|
|
state := COMPLETE;
|
|
|
|
when x"99" =>
|
|
print(" SPI reset execute");
|
|
mode := 0;
|
|
wrap_boundary := false;
|
|
state := COMPLETE;
|
|
|
|
when x"35" =>
|
|
print(" QPI enter");
|
|
mode := 1;
|
|
state := COMPLETE;
|
|
|
|
when x"F5" =>
|
|
print(" QPI exit");
|
|
mode := 0;
|
|
state := COMPLETE;
|
|
|
|
when x"C0" =>
|
|
print(" Wrap Boundary Toggle");
|
|
wrap_boundary := not wrap_boundary;
|
|
state := COMPLETE;
|
|
|
|
when x"0B" =>
|
|
print(" QPI Read Slow");
|
|
state := READ;
|
|
|
|
when x"EB" =>
|
|
print(" QPI Read Fast");
|
|
state := READ;
|
|
|
|
when x"02" =>
|
|
print(" QPI Write (1)");
|
|
state := WRITE;
|
|
|
|
when x"38" =>
|
|
print(" QPI Write (2)");
|
|
state := WRITE;
|
|
|
|
when others =>
|
|
print(" Unknown command: 0x" & to_hstring(bytes(0)));
|
|
state := COMPLETE;
|
|
end case;
|
|
|
|
when READ =>
|
|
if bytecnt = 3 then
|
|
print(" Addr: " & to_hstring(bytes(1)) & to_hstring(bytes(2)) & to_hstring(bytes(3)));
|
|
addr := to_integer(unsigned(std_logic_vector'(bytes(1), bytes(2), bytes(3))));
|
|
elsif bytecnt > 4 then
|
|
dout := mem(addr);
|
|
print(" Read " & integer'image(addr) & ": " & to_hstring(mem(addr)));
|
|
addr := addr + 1;
|
|
end if;
|
|
|
|
when WRITE =>
|
|
if bytecnt = 3 then
|
|
print(" Addr: " & to_hstring(bytes(1)) & to_hstring(bytes(2)) & to_hstring(bytes(3)));
|
|
addr := to_integer(unsigned(std_logic_vector'(bytes(1), bytes(2), bytes(3))));
|
|
elsif bytecnt > 3 then
|
|
print(" Write " & integer'image(addr) & ": " & to_hstring(bytes(bytecnt)));
|
|
mem(addr) := bytes(bytecnt);
|
|
addr := addr + 1;
|
|
end if;
|
|
|
|
when COMPLETE =>
|
|
null;
|
|
end case;
|
|
|
|
bytecnt := bytecnt + 1;
|
|
end if;
|
|
|
|
if state = READ and bytecnt > 4 then
|
|
sio_temp := dout(7 downto 4) when command_edge else dout(3 downto 0);
|
|
sio <= sio_temp after 5 ns;
|
|
end if;
|
|
end procedure handle;
|
|
|
|
begin
|
|
sio <= (others => 'Z');
|
|
wait until ce_n = '0';
|
|
print("Selected.");
|
|
bytes := (others => (others => 'U'));
|
|
cnt := 0;
|
|
bytecnt := 0;
|
|
state := COMMAND;
|
|
loop
|
|
wait on sclk, ce_n;
|
|
|
|
if mode = 0 then -- SPI
|
|
if falling_edge(sclk) then
|
|
bytes(cnt / 8)(7 - (cnt mod 8)) := sio(0);
|
|
cnt := cnt + 1;
|
|
if cnt mod 4 = 0 then
|
|
handle(cnt mod 8 = 0);
|
|
end if;
|
|
end if;
|
|
else -- QPI
|
|
if falling_edge(sclk) then
|
|
bytes(cnt / 2)((1 - (cnt mod 2) + 1) * 4 - 1 downto (1 - (cnt mod 2)) * 4) := sio;
|
|
cnt := cnt + 1;
|
|
end if;
|
|
if falling_edge(sclk) then
|
|
|
|
handle(cnt mod 2 = 0);
|
|
|
|
end if;
|
|
end if;
|
|
|
|
exit when ce_n = '1';
|
|
end loop;
|
|
print("Deselected.");
|
|
end process test;
|
|
|
|
end architecture bench;
|