Skip to content

Commit

Permalink
Working espi x1 boot on ruby
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanaelhuffman committed Nov 4, 2024
1 parent 9b9244b commit 4a320a3
Show file tree
Hide file tree
Showing 17 changed files with 537 additions and 133 deletions.
8 changes: 4 additions & 4 deletions hdl/ip/vhd/espi/espi_spec_regs.rdl
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,19 @@ addrmap eSPI_Spec {
field {
desc = "Flash Channel Supported";
sw = r;
} flash_support[3:3] = 0x0;
} flash_support[3:3] = 0x1;
field {
desc = "OOB Message Channel Supported";
sw = r;
} oob_support[2:2] = 0x1;
} oob_support[2:2] = 0x0;
field {
desc = "Virtual Wire Channel Supported";
sw = r;
} virt_wire_support[1:1] = 0x0;
} virt_wire_support[1:1] = 0x1;
field {
desc = "Peripheral Channel Supported";
sw = r;
} periph_support[0:0] = 0x0;
} periph_support[0:0] = 0x1;
} general_capabilities;

reg {
Expand Down
2 changes: 2 additions & 0 deletions hdl/ip/vhd/espi/espi_target_top.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ entity espi_target_top is
io : in std_logic_vector(3 downto 0);
io_o : out std_logic_vector(3 downto 0);
io_oe : out std_logic_vector(3 downto 0);
response_csn : out std_logic;
-- Interface out to the flash block
-- Read Command FIFO
flash_cfifo_data : out std_logic_vector(31 downto 0);
Expand Down Expand Up @@ -111,6 +112,7 @@ begin
io => io,
io_o => io_o,
io_oe => io_oe,
response_csn => response_csn,
dbg_chan => dbg_chan,
qspi_mode => qspi_mode,
is_rx_crc_byte => is_rx_crc_byte,
Expand Down
48 changes: 42 additions & 6 deletions hdl/ip/vhd/espi/flash_channel/flash_channel.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ end;


architecture rtl of flash_channel is

attribute mark_debug : string;
constant max_txn_size : integer := 1024;
subtype desc_index_t is natural range 0 to num_descriptors - 1;
signal dpr_waddr : std_logic_vector(11 downto 0);
Expand Down Expand Up @@ -69,22 +71,53 @@ architecture rtl of flash_channel is
compl_side_cntr : integer range 0 to 1024;
cmd_queue: command_queue_t;
dpr_write_en: std_logic;
dpr_wdata_buf: std_logic_vector(7 downto 0);
tail_desc: desc_index_t;
issue_desc: desc_index_t;
head_desc: desc_index_t;
flash_np_free : std_logic;
flash_c_avail: std_logic;
end record;
constant reg_reset : reg_type := (idle, idle, 0, 0, 0, (others => descriptor_init), '0', 0, 0, 0, '0', '0');
constant reg_reset : reg_type := (idle, idle, 0, 0, 0, (others => descriptor_init), '0', (others => '0'), 0, 0, 0, '0', '0');

signal r, rin : reg_type;
signal dpr_wdata: std_logic_vector(7 downto 0);
signal dpr_rdata: std_logic_vector(7 downto 0);
signal dpr_read_ack: std_logic;
signal dpr_wr_delay: std_logic;

attribute mark_debug of r : signal is "TRUE";
attribute mark_debug of dpr_wdata : signal is "TRUE";
attribute mark_debug of dpr_rdata : signal is "TRUE";
attribute mark_debug of dpr_read_ack : signal is "TRUE";
attribute mark_debug of dpr_wr_delay : signal is "TRUE";

begin

dbg_regs: process (clk, reset)
begin
if reset then
dpr_wdata <= (others => '0');
dpr_rdata <= (others => '0');
dpr_read_ack <= '0';
dpr_wr_delay <= '0';
elsif rising_edge(clk) then
dpr_rdata <= readdata;
dpr_wdata <= flash_rfifo_data;
dpr_read_ack <= response.ready;
dpr_wr_delay <= r.dpr_write_en;
end if;
end process;


-- Always write straight from the FIFO to the dpr so any dpr write is a fifo read ack also
flash_rfifo_rdack <= r.dpr_write_en;
flash_np_free <= r.flash_np_free;

-- flash_c_avail is set when we have pending data to be read back out, but critically this status needs to represent
-- the state *after* any current message, so if we're responding now and this response is the only one available,
-- this needs to be set to 0.

flash_c_avail <= r.flash_c_avail when enabled else '0';

flash_cfifo_data <= r.cmd_queue(r.issue_desc).sp5_addr when r.flash_cmd_state = issue_flash_addr else
Expand All @@ -104,7 +137,7 @@ begin
port map(
wclk => clk,
waddr => dpr_waddr,
wdata => flash_rfifo_data,
wdata => r.dpr_wdata_buf,
wren => r.dpr_write_en,
rclk => clk,
raddr => dpr_raddr,
Expand All @@ -114,11 +147,11 @@ begin
response.valid <= '1' when r.compl_state = read_dpr else '0';
response.tag <= r.cmd_queue(r.tail_desc).tag;
response.length <= r.cmd_queue(r.tail_desc).xfr_size_bytes;
response.cycle_type <= "00001111"; -- successful completion of with data, only complettion for a split txn
response.cycle_type <= "00001111"; -- successful completion of with data, only completion for a split txn


dpr_waddr <= To_Std_Logic_Vector(r.cmd_queue(r.issue_desc).id * max_txn_size + r.flash_write_addr_offset, 12);
dpr_raddr <= To_Std_Logic_Vector(r.cmd_queue(r.tail_desc).id * max_txn_size + r.compl_side_cntr, 12);
dpr_waddr <= To_Std_Logic_Vector(r.issue_desc * max_txn_size + r.flash_write_addr_offset, 12);
dpr_raddr <= To_Std_Logic_Vector(r.tail_desc * max_txn_size + r.compl_side_cntr, 12);

-- We have two state machines running here as both need to be able to update
-- the descriptor queues.
Expand Down Expand Up @@ -215,8 +248,11 @@ begin
v.flash_cmd_state := idle;
v.flash_side_cntr := 0;
v.issue_desc := add_wrap(r.issue_desc, desc_index_t'high);
elsif not flash_rfifo_rempty then
-- "empty" isn't strictly valid if we're acking this cycle since this write could
-- empty it. We only check for empty on a cycle where we're not acking
elsif not flash_rfifo_rempty and (not r.dpr_write_en) then
v.dpr_write_en := '1';
v.dpr_wdata_buf := flash_rfifo_data;
v.flash_write_addr_offset := r.flash_side_cntr;
v.flash_side_cntr := r.flash_side_cntr + 1;
end if;
Expand Down
3 changes: 1 addition & 2 deletions hdl/ip/vhd/espi/flash_channel/flash_channel_pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package flash_channel_pkg is
constant num_descriptors : integer := 4;

type descriptor_t is record
id : integer range 0 to num_descriptors - 1;
sp5_addr : std_logic_vector(31 downto 0);
xfr_size_bytes : std_logic_vector(11 downto 0);
ready_bytes: std_logic_vector(11 downto 0);
Expand All @@ -26,7 +25,6 @@ package flash_channel_pkg is
end record;

constant descriptor_init : descriptor_t := (
id => 0,
sp5_addr => (others => '0'),
xfr_size_bytes => (others => '0'),
ready_bytes => (others => '0'),
Expand All @@ -38,6 +36,7 @@ package flash_channel_pkg is
type command_queue_t is array(0 to num_descriptors - 1) of descriptor_t;



type flash_channel_req_t is record
espi_hdr : espi_cmd_header;
sp5_flash_address : std_logic_vector(31 downto 0);
Expand Down
2 changes: 2 additions & 0 deletions hdl/ip/vhd/espi/link_layer/link_layer_top.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ entity link_layer_top is
io_o : out std_logic_vector(3 downto 0);
io_oe : out std_logic_vector(3 downto 0);
dbg_chan : view dbg_periph_if;
response_csn : out std_logic;
-- set in registers, controls how the shifters
-- sample per sclk
qspi_mode : in qspi_mode_t;
Expand Down Expand Up @@ -74,6 +75,7 @@ begin
io => io,
io_o => io_o,
io_oe => io_oe,
response_csn => response_csn,
qspi_mode => qspi_mode,
is_tx_crc_byte => is_tx_crc_byte,
is_rx_crc_byte => is_rx_crc_byte,
Expand Down
31 changes: 29 additions & 2 deletions hdl/ip/vhd/espi/link_layer/qspi_link_layer.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ entity qspi_link_layer is
io : in std_logic_vector(3 downto 0);
io_o : out std_logic_vector(3 downto 0);
io_oe : out std_logic_vector(3 downto 0);

response_csn: out std_logic;
-- set in registers, controls how the shifters
-- sample per sclk
qspi_mode : in qspi_mode_t;
Expand Down Expand Up @@ -77,10 +79,28 @@ architecture rtl of qspi_link_layer is
signal cs_cntr : natural range 0 to 3 := 0;
constant cs_deassert_delay : natural := 2;
signal last_byte : boolean;
signal in_turnaround_last : boolean;



begin

saleae_response_cs_gen: process(clk, reset)
begin
if reset then
response_csn <= '1';
in_turnaround_last <= false;
elsif rising_edge(clk) then
in_turnaround_last <= in_turnaround;
if response_csn = '1' and response_phase and sclk = '0' then
response_csn <= '0';
elsif cs_n = '1' then
response_csn <= '1';
end if;

end if;
end process;

-- We have some fairly slow minimum delay timings for the alert pin
-- this block monitors the chip select and provides an alert_allowed
-- window for the alert processor.
Expand Down Expand Up @@ -117,6 +137,9 @@ begin
elsif rising_edge(clk) then
-- If we have an alert to send, we can send it by pulling
--io[1] low, but only when cs is not asserted.
-- it is possible that we will send a status before this
-- is needed, in which case we should not send the alert
-- since the status was current.
case alert_state is
when idle =>
if alert_needed and cs_monitor_state = alert_allowed then
Expand All @@ -125,11 +148,15 @@ begin
alert_state <= wait_for_allowed;
end if;
when wait_for_allowed =>
if cs_monitor_state = alert_allowed then
if not alert_needed then
alert_state <= idle;
elsif cs_monitor_state = alert_allowed then
alert_state <= alert;
end if;
when alert =>
if cs_n = '0' or cs_monitor_state = no_alert_allowed then
if not alert_needed then
alert_state <= idle;
elsif cs_n = '0' or cs_monitor_state = no_alert_allowed then
alert_state <= idle;
end if;
end case;
Expand Down
16 changes: 8 additions & 8 deletions hdl/ip/vhd/espi/sims/espi_tb.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -159,24 +159,24 @@ begin
-- We expect something to happen here and the alert get set when the completion
-- status is written back, so we check the crc here and then wait for the alert
-- enqueue 3 copies of the same np request
put_flash_read(net, X"00000000", 32, response_code, status, crc_ok);
check(crc_ok, "CRC Check failed");
put_flash_read(net, X"00000000", 32, response_code, status, crc_ok);
check(crc_ok, "CRC Check failed");
put_flash_read(net, X"00000000", 32, response_code, status, crc_ok);
put_flash_read(net, X"03020000", 16, response_code, status, crc_ok);
check(crc_ok, "CRC Check failed");
-- put_flash_read(net, X"03020000", 16, response_code, status, crc_ok);
-- check(crc_ok, "CRC Check failed");
-- put_flash_read(net, X"03020000", 16, response_code, status, crc_ok);
-- check(crc_ok, "CRC Check failed");

for i in 0 to 2 loop
for i in 0 to 0 loop
report "Status: " & to_hstring(status);
status_rec := unpack(status);
if status_rec.flash_c_avail = '0' then
report "Waiting, iter: " & integer'image(i);
wait_for_alert(net);
end if;
get_flash_c(net, 32, my_queue, response_code, status, crc_ok);
get_flash_c(net, 16, my_queue, response_code, status, crc_ok);
check(crc_ok, "CRC Check failed");
-- TODO: the data's not coming back right.
for j in 0 to 31 loop
for j in 0 to 15 loop
report "Flash Byte: " & to_hstring(to_unsigned(pop_byte(my_queue), 8));
end loop;
end loop;
Expand Down
44 changes: 38 additions & 6 deletions hdl/ip/vhd/espi/sims/models/fake_flash_txn_mgr.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ architecture model of fake_flash_txn_mgr is
constant cmd_queue : queue_t := new_queue;
signal addr : std_logic_vector(31 downto 0);
signal cmd_idx : natural range 0 to 1 := 0;
signal write_en : std_logic;
signal wdata : std_logic_vector(7 downto 0);

begin

Expand Down Expand Up @@ -79,24 +81,54 @@ begin
variable top : std_logic_vector(11 downto 0);
variable data : std_logic_vector(11 downto 0);
begin
flash_rdata_empty <= '1';
flash_rdata <= (others => 'X');
write_en <= '0';
loop
exit when not is_empty(cmd_queue);
wait until rising_edge(clk);
wait until falling_edge(clk);
end loop;
addr := pop(cmd_queue);
len := pop(cmd_queue);
top := len;
flash_rdata_empty <= '0';
-- push some data into the fifo
while len > 0 loop
data := top - len;
flash_rdata <= data(7 downto 0);
if rising_edge(clk) and flash_rdata_rdack = '1' then
wdata <= resize(data, wdata'length);
write_en <= '1';
if rising_edge(clk)then
len := len - 1;
wait on clk;
write_en <= '0';
wait until rising_edge(clk);
wait until rising_edge(clk);
wait until rising_edge(clk);
wait until rising_edge(clk);
wait until rising_edge(clk);
wait until rising_edge(clk);
end if;
wait on clk;
end loop;

end process;


dcfifo_xpm_inst: entity work.dcfifo_xpm
generic map(
fifo_write_depth => 4096,
data_width => 8,
showahead_mode => true
)
port map(
wclk => clk,
reset => reset,
write_en => write_en,
wdata => wdata,
wfull => open,
wusedwds => open,
rclk => clk,
rdata => flash_rdata,
rdreq => flash_rdata_rdack,
rempty => flash_rdata_empty,
rusedwds => open
);

end model;
Loading

0 comments on commit 4a320a3

Please sign in to comment.