added support for multi word addressable writes

This commit is contained in:
Erik Örtenberg 2025-03-04 16:06:30 +01:00
parent 547ff21a53
commit a5c9190e2d
3 changed files with 75 additions and 15 deletions

View File

@ -71,7 +71,7 @@ begin
READ_RESPONSE when "01000",
READ_RESPONSE when "01100",
NO_OP when others;
comb_proc: process(ext_in, int_out, curr_response, st)
comb_proc: process(ext_in, int_out, curr_response, st, cmd)
begin
-- Outputs
ext_out <= create_io_type_out_from_ext_protocol(st.ext_out_reg);
@ -128,8 +128,12 @@ begin
end if;
when TX_HEADER =>
-- The header only takes one word (cycle) to transmit.
-- Continue to body directly afterwards.
next_state <= TX_BODY;
-- Continue to body or address directly afterwards.
if st.cmd_reg = WRITE_ADD then
next_state <= ADDR1;
else
next_state <= TX_BODY;
end if;
when TX_BODY =>
-- Here we want to stay in TX_BODY for the duration of a packet.
-- Right now, we transfer one single word at a time for simplicity
@ -148,7 +152,11 @@ begin
when RX_HEADER =>
-- The header only takes one word (cycle) to transmit.
-- Continue to awaiting response directly afterwards.
next_state <= RX_RESPONSE;
if st.cmd_reg = WRITE_ADD then
next_state <= ADDR1;
else
next_state <= RX_RESPONSE;
end if;
when RX_RESPONSE =>
-- Wait for read response.
if curr_response = READ_RESPONSE then
@ -165,6 +173,8 @@ begin
when ADDR2 =>
next_state <= ADDR3;
when ADDR3 =>
next_state <= ADDR4;
when ADDR4 =>
if st.cmd_reg = WRITE or st.cmd_reg = WRITE_ADD then
next_state <= TX_BODY;
else
@ -178,6 +188,11 @@ begin
int_in.write_enable_in <= '0';
case st.curr_state is
when IDLE =>
if cmd = WRITE or cmd = WRITE_ADD then
ext_out_data_cmd := get_cmd_bits(cmd) & get_size_bits(cmd_size);
elsif cmd = READ or cmd = READ_ADD then
ext_out_data_cmd := get_cmd_bits(cmd) & get_size_bits(cmd_size);
end if;
when TX_HEADER =>
if st.cmd_reg = WRITE_ADD then
ext_out_data_cmd := st.addr_reg(7 downto 0);
@ -186,8 +201,13 @@ begin
int_in.is_full_out <= '0';
end if;
when TX_BODY =>
ext_out_data_cmd := int_out.payload;
int_in.is_full_out <= '0';
if st.write_stage > 0 then
int_in.is_full_out <= '0';
ext_out_data_cmd := int_out.payload;
else
ext_out_data_cmd := (others => '0');
end if;
when TX_ACK =>
when RX_HEADER =>
ext_out_data_cmd := get_cmd_bits(st.cmd_reg) & get_size_bits(cmd_size);
@ -199,6 +219,9 @@ begin
ext_out_data_cmd := st.addr_reg(23 downto 16);
when ADDR3 =>
ext_out_data_cmd := st.addr_reg(31 downto 24);
when ADDR4 =>
int_in.is_full_out <= '0';
ext_out_data_cmd := int_out.payload;
end case;
next_parity_out <= calc_parity(ext_out_data_cmd);
--- DEBUG GLOBAL BINDINGS ---
@ -236,20 +259,20 @@ begin
st.cmd_reg <= cmd;
end if;
when TX_HEADER =>
if st.cmd_reg = WRITE then
if st.cmd_reg = WRITE_ADD then
st.write_stage <= 2**(cmd_size - 1) - 1;
else
st.write_stage <= 2**(cmd_size - 1) - 1;
elsif st.cmd_reg = WRITE_ADD then
st.write_stage <= 2**(cmd_size - 1) + 3;
end if;
when TX_BODY =>
if st.write_stage > 0 then
st.write_stage <= st.write_stage - 1;
end if;
when RX_HEADER =>
if st.cmd_reg = READ then
if st.cmd_reg = READ_ADD then
st.read_stage <= 2**(cmd_size - 1);
else
st.read_stage <= 2**(cmd_size - 1) - 1;
elsif st.cmd_reg = READ_ADD then
st.read_stage <= 2**(cmd_size - 1) + 3;
end if;
when RX_BODY =>
if st.read_stage > 0 then

View File

@ -13,6 +13,7 @@ architecture tb of socbridge_driver_tb is
signal clk : std_logic := '0';
signal rst : std_logic;
signal cmd : command_t;
signal address : std_logic_vector(31 downto 0);
signal cmd_size : positive;
signal ext_in : ext_socbridge_in_t;
signal ext_out : ext_socbridge_out_t;
@ -62,6 +63,7 @@ architecture tb of socbridge_driver_tb is
clk : in std_logic;
rst : in std_logic;
cmd : in command_t;
address : in std_logic_vector(31 downto 0);
cmd_size: in positive;
ext_in : in ext_socbridge_in_t;
ext_out : out ext_socbridge_out_t;
@ -76,6 +78,7 @@ begin
clk => clk,
rst => rst,
cmd => cmd,
address => address,
cmd_size => cmd_size,
ext_in => ext_in,
ext_out => ext_out,
@ -140,7 +143,7 @@ begin
check_next_state(TX_ACK);
wait for CLK_PERIOD;
expected_out <= "00000000";
check_next_state(IDLE);
check_next_state(TX_ACK);
wait for CLK_PERIOD;
expected_out <= "00000000";
check_next_state(IDLE);
@ -162,7 +165,30 @@ begin
wait for CLK_PERIOD;
expected_out <= "00000000";
check_next_state(IDLE);
wait for CLK_PERIOD /4;
check_next_state(TX_HEADER);
wait for CLK_PERIOD * 3 / 4;
expected_out <= get_cmd_bits(WRITE_ADD) & get_size_bits(2);
check_next_state(ADDR1);
wait for CLK_PERIOD;
expected_out <= x"FA";
check_next_state(ADDR2);
wait for CLK_PERIOD;
expected_out <= x"A0";
check_next_state(ADDR3);
wait for CLK_PERIOD;
expected_out <= x"0F";
check_next_state(ADDR4);
wait for CLK_PERIOD;
expected_out <= x"FA";
check_next_state(TX_BODY);
wait for CLK_PERIOD;
expected_out <= "00000100";
check_next_state(TX_BODY);
wait for CLK_PERIOD;
expected_out <= "00001000";
wait for CLK_PERIOD;
expected_out <= "00000000";
wait;
end process verify_signals;
@ -175,6 +201,12 @@ begin
cmd <= WRITE;
wait for CLK_PERIOD;
cmd <= NO_OP;
wait for CLK_PERIOD * 10;
cmd <= WRITE_ADD;
address <= x"FA0FA0FA";
wait for CLK_PERIOD;
cmd <= NO_OP;
address <= (others => '0');
wait;
end process command_stimulus;
@ -194,8 +226,13 @@ begin
wait for 2 * CLK_PERIOD;
rst <= '0';
wait for CLK_PERIOD / 2;
wait for 3* CLK_PERIOD;
wait for 4* CLK_PERIOD;
curr_word <= "00001001";
wait for CLK_PERIOD;
curr_word <= "00000000";
wait for CLK_PERIOD * 10;
curr_word <= "00101001";
wait;
end process external_stimulus;

View File

@ -16,7 +16,7 @@ package socbridge_driver_tb_pkg is
(NO_OP, WRITE_ACK, READ_RESPONSE);
type state_t is
(IDLE, ADDR1, ADDR2, ADDR3,
(IDLE, ADDR1, ADDR2, ADDR3, ADDR4,
TX_HEADER, TX_BODY, TX_ACK,
RX_HEADER, RX_RESPONSE, RX_BODY);