diff --git a/sim/L0_rtps_out_test1.do b/sim/L0_rtps_out_test1.do index e622024..ae9f1ed 100644 --- a/sim/L0_rtps_out_test1.do +++ b/sim/L0_rtps_out_test1.do @@ -1,37 +1,48 @@ onerror {resume} quietly WaveActivateNextPane {} 0 add wave -noupdate -divider SYSTEM -add wave -noupdate /L0_rtps_out_test1/uut/clk -add wave -noupdate /L0_rtps_out_test1/uut/reset +add wave -noupdate /l0_rtps_out_test1/uut/clk +add wave -noupdate /l0_rtps_out_test1/uut/reset add wave -noupdate -divider TESTBENCH -add wave -noupdate /L0_rtps_out_test1/start -add wave -noupdate /L0_rtps_out_test1/packet_sent +add wave -noupdate /l0_rtps_out_test1/start +add wave -noupdate /l0_rtps_out_test1/packet_sent add wave -noupdate -divider INPUT -add wave -noupdate -radix hexadecimal /L0_rtps_out_test1/uut/data_in -add wave -noupdate /L0_rtps_out_test1/uut/last_word_in -add wave -noupdate /L0_rtps_out_test1/uut/rd -add wave -noupdate /L0_rtps_out_test1/uut/empty +add wave -noupdate -radix hexadecimal /l0_rtps_out_test1/uut/data_in +add wave -noupdate /l0_rtps_out_test1/uut/last_word_in +add wave -noupdate /l0_rtps_out_test1/uut/rd +add wave -noupdate /l0_rtps_out_test1/uut/empty add wave -noupdate -divider OUTPUT -add wave -noupdate -radix hexadecimal /L0_rtps_out_test1/uut/data_out -add wave -noupdate /L0_rtps_out_test1/uut/wr -add wave -noupdate /L0_rtps_out_test1/uut/full +add wave -noupdate -radix hexadecimal /l0_rtps_out_test1/uut/data_out +add wave -noupdate /l0_rtps_out_test1/uut/wr +add wave -noupdate /l0_rtps_out_test1/uut/full add wave -noupdate -divider {INPUT FSM} -add wave -noupdate /L0_rtps_out_test1/uut/input_stage -add wave -noupdate /L0_rtps_out_test1/uut/input_stage_next -add wave -noupdate /L0_rtps_out_test1/uut/in_pntr -add wave -noupdate /L0_rtps_out_test1/uut/selector -add wave -noupdate -radix unsigned /L0_rtps_out_test1/uut/length +add wave -noupdate /l0_rtps_out_test1/uut/input_stage +add wave -noupdate /l0_rtps_out_test1/uut/input_stage_next +add wave -noupdate -radix unsigned /l0_rtps_out_test1/uut/in_pntr +add wave -noupdate /l0_rtps_out_test1/uut/selector +add wave -noupdate -radix unsigned /l0_rtps_out_test1/uut/length add wave -noupdate -divider {OUTPUT FSM} -add wave -noupdate /L0_rtps_out_test1/uut/output_stage -add wave -noupdate /L0_rtps_out_test1/uut/output_stage_next -add wave -noupdate /L0_rtps_out_test1/uut/out_pntr -add wave -noupdate -radix unsigned /L0_rtps_out_test1/uut/packet_end +add wave -noupdate /l0_rtps_out_test1/uut/output_stage +add wave -noupdate /l0_rtps_out_test1/uut/output_stage_next +add wave -noupdate -radix unsigned /l0_rtps_out_test1/uut/out_pntr +add wave -noupdate -radix unsigned /l0_rtps_out_test1/uut/packet_end add wave -noupdate -divider MISC -add wave -noupdate /L0_rtps_out_test1/uut/filled -add wave -noupdate /L0_rtps_out_test1/uut/reset_filled -add wave -noupdate /L0_rtps_out_test1/uut/set_filled +add wave -noupdate /l0_rtps_out_test1/uut/filled +add wave -noupdate /l0_rtps_out_test1/uut/reset_filled +add wave -noupdate /l0_rtps_out_test1/uut/set_filled +add wave -noupdate -divider RAM +add wave -noupdate -expand -group READ -radix unsigned /l0_rtps_out_test1/uut/buffer_inst/raddr +add wave -noupdate -expand -group READ /l0_rtps_out_test1/uut/buffer_inst/rvalid_in +add wave -noupdate -expand -group READ /l0_rtps_out_test1/uut/buffer_inst/rready_in +add wave -noupdate -expand -group READ /l0_rtps_out_test1/uut/buffer_inst/rvalid_out +add wave -noupdate -expand -group READ /l0_rtps_out_test1/uut/buffer_inst/rready_out +add wave -noupdate -expand -group READ -radix hexadecimal /l0_rtps_out_test1/uut/buffer_inst/rdata_out +add wave -noupdate -expand -group WRITE -radix unsigned /l0_rtps_out_test1/uut/buffer_inst/waddr +add wave -noupdate -expand -group WRITE /l0_rtps_out_test1/uut/buffer_inst/wvalid_in +add wave -noupdate -expand -group WRITE /l0_rtps_out_test1/uut/buffer_inst/wready_in +add wave -noupdate -expand -group WRITE -radix hexadecimal /l0_rtps_out_test1/uut/buffer_inst/wdata_in TreeUpdate [SetDefaultTree] -WaveRestoreCursors {Error {2175000 ps} 1} {Cursor {12626 ps} 0} +WaveRestoreCursors {Cursor {2275000 ps} 0} quietly wave cursor active 1 configure wave -namecolwidth 150 configure wave -valuecolwidth 100 @@ -47,4 +58,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update -WaveRestoreZoom {1663 ns} {2687 ns} +WaveRestoreZoom {1735800 ps} {2759800 ps} diff --git a/src/Tests/Level_0/L0_rtps_out_test1.vhd b/src/Tests/Level_0/L0_rtps_out_test1.vhd index 3a0ae0c..89db1e4 100644 --- a/src/Tests/Level_0/L0_rtps_out_test1.vhd +++ b/src/Tests/Level_0/L0_rtps_out_test1.vhd @@ -170,7 +170,9 @@ begin t3 := RV.RandInt(0, t1-1); Log("T3: " & to_string(t3), DEBUG); -- Generate 2 Packets + Log("T1 Packet", DEBUG); gen_rand_packet(0, stimulus(t1)); + Log("T1 Packet", DEBUG); gen_rand_packet(0, stimulus(t1)); -- Push T1 Packet 0 push_reference(0, stimulus(t1)); @@ -178,9 +180,13 @@ begin -- Wait for UUT do reach t1 wait until rd_sig(t1) = '1'; -- Generate 2 Packets for T2 and T3 + Log("T2 Packet", DEBUG); gen_rand_packet(0, stimulus(t2)); + Log("T2 Packet", DEBUG); gen_rand_packet(0, stimulus(t2)); + Log("T3 Packet", DEBUG); gen_rand_packet(0, stimulus(t3)); + Log("T3 Packet", DEBUG); gen_rand_packet(0, stimulus(t3)); -- Push T2 Packet 0 push_reference(0, stimulus(t2)); @@ -204,16 +210,22 @@ begin stimulus(t3) := tmp_packet; Log("Begin Test 2", INFO); -- Min Valid Packet + Log("T1 Packet", DEBUG); gen_rand_packet(4, stimulus(t1)); push_reference(0, stimulus(t1)); -- MAX Valid Packet + Log("T2 Packet", DEBUG); gen_rand_packet(MAX_SIZE, stimulus(t2)); push_reference(0, stimulus(t2)); -- Invalid Packet (Over size) + Log("T3 Packet", DEBUG); gen_rand_packet(MAX_SIZE+1, stimulus(t3)); -- Invalid Packet [Packet too small] + Log("T1 Packet", DEBUG); gen_rand_packet(3, stimulus(t1)); + Log("T1 Packet", DEBUG); gen_rand_packet(2, stimulus(t1)); + Log("T1 Packet", DEBUG); gen_rand_packet(1, stimulus(t1)); start_test; -- Wait until all but t1 sent diff --git a/src/Tests/testbench.pro b/src/Tests/testbench.pro index df36ef3..f1aafef 100644 --- a/src/Tests/testbench.pro +++ b/src/Tests/testbench.pro @@ -10,10 +10,14 @@ analyze ../rtps_test_package.vhd analyze ../single_port_ram.vhd analyze ../single_port_ram_Altera.vhd analyze single_port_ram_cfg.vhd +analyze ../dual_port_ram.vhd +analyze ../dual_port_ram_Altera.vhd +analyze dual_port_ram_cfg.vhd analyze ../FWFT_FIFO.vhd analyze ../FWFT_FIFO_Altera.vhd analyze FWFT_FIFO_cfg.vhd analyze ../mem_ctrl.vhd +analyze ../dp_mem_ctrl.vhd analyze ../rtps_handler.vhd analyze ../rtps_builtin_endpoint.vhd analyze ../rtps_out.vhd @@ -40,10 +44,14 @@ analyze ../rtps_test_package.vhd analyze ../single_port_ram.vhd analyze ../single_port_ram_Altera.vhd analyze single_port_ram_cfg.vhd +analyze ../dual_port_ram.vhd +analyze ../dual_port_ram_Altera.vhd +analyze dual_port_ram_cfg.vhd analyze ../FWFT_FIFO.vhd analyze ../FWFT_FIFO_Altera.vhd analyze FWFT_FIFO_cfg.vhd analyze ../mem_ctrl.vhd +analyze ../dp_mem_ctrl.vhd analyze ../rtps_handler.vhd analyze ../rtps_builtin_endpoint.vhd analyze ../rtps_out.vhd @@ -70,10 +78,14 @@ analyze ../rtps_test_package.vhd analyze ../single_port_ram.vhd analyze ../single_port_ram_Altera.vhd analyze single_port_ram_cfg.vhd +analyze ../dual_port_ram.vhd +analyze ../dual_port_ram_Altera.vhd +analyze dual_port_ram_cfg.vhd analyze ../FWFT_FIFO.vhd analyze ../FWFT_FIFO_Altera.vhd analyze FWFT_FIFO_cfg.vhd analyze ../mem_ctrl.vhd +analyze ../dp_mem_ctrl.vhd analyze ../rtps_handler.vhd analyze ../rtps_builtin_endpoint.vhd analyze ../rtps_out.vhd @@ -101,10 +113,14 @@ analyze ../rtps_test_package.vhd analyze ../single_port_ram.vhd analyze ../single_port_ram_Altera.vhd analyze single_port_ram_cfg.vhd +analyze ../dual_port_ram.vhd +analyze ../dual_port_ram_Altera.vhd +analyze dual_port_ram_cfg.vhd analyze ../FWFT_FIFO.vhd analyze ../FWFT_FIFO_Altera.vhd analyze FWFT_FIFO_cfg.vhd analyze ../mem_ctrl.vhd +analyze ../dp_mem_ctrl.vhd analyze ../rtps_handler.vhd analyze ../rtps_builtin_endpoint.vhd analyze ../rtps_out.vhd @@ -133,10 +149,14 @@ analyze ../rtps_test_package.vhd analyze ../single_port_ram.vhd analyze ../single_port_ram_Altera.vhd analyze single_port_ram_cfg.vhd +analyze ../dual_port_ram.vhd +analyze ../dual_port_ram_Altera.vhd +analyze dual_port_ram_cfg.vhd analyze ../FWFT_FIFO.vhd analyze ../FWFT_FIFO_Altera.vhd analyze FWFT_FIFO_cfg.vhd analyze ../mem_ctrl.vhd +analyze ../dp_mem_ctrl.vhd analyze ../rtps_handler.vhd analyze ../rtps_builtin_endpoint.vhd analyze ../rtps_out.vhd diff --git a/src/rtps_out.vhd b/src/rtps_out.vhd index 9f2028f..10b5e90 100644 --- a/src/rtps_out.vhd +++ b/src/rtps_out.vhd @@ -5,6 +5,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; +use work.math_pkg.all; use work.rtps_package.all; use work.user_config.all; use work.rtps_config_package.all; @@ -32,16 +33,19 @@ end entity; architecture arch of rtps_out is + -- *CONSTANT DECLARATION* + constant BUFFER_ADDR_WIDTH : natural := log2c(MAX_BUFFER_SIZE); + -- *TYPE DECLARATION* type BUFFER_TYPE is array (0 to MAX_BUFFER_SIZE-1) of std_logic_vector(WORD_WIDTH-1 downto 0); type INPUT_STAGE_TYPE is (IDLE, SRC_ADDR_HEADER, DEST_ADDR_HEADER, PORT_HEADER, READ, SKIP); - type OUTPUT_STAGE_TYPE is (IDLE, SRC_ADDR_HEADER, DEST_ADDR_HEADER, PORT_HEADER, PACKET_LENGTH, WRITE); + type OUTPUT_STAGE_TYPE is (IDLE, SRC_ADDR_HEADER, DEST_ADDR_HEADER, PORT_HEADER, PACKET_LENGTH, WRITE_PRIMER, WRITE, FINALIZE_WRITE); -- *SIGNAL DECLARATION* signal selector, selector_next : natural range 0 to NUM_ENDPOINTS; signal buff, buff_next : BUFFER_TYPE; - signal in_pntr, in_pntr_next : natural range 0 to MAX_BUFFER_SIZE; - signal out_pntr, out_pntr_next : natural range 0 to MAX_BUFFER_SIZE; + signal in_pntr, in_pntr_next : unsigned(BUFFER_ADDR_WIDTH downto 0); + signal out_pntr, out_pntr_next : unsigned(BUFFER_ADDR_WIDTH downto 0); signal length, length_next : unsigned(WORD_WIDTH-1 downto 0); signal packet_end, packet_end_next : unsigned(WORD_WIDTH-1 downto 0); signal input_stage, input_stage_next : INPUT_STAGE_TYPE; @@ -51,9 +55,36 @@ architecture arch of rtps_out is signal dest_addr, dest_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); signal ports, ports_next : std_logic_vector((UDP_PORT_WIDTH*2)-1 downto 0); + signal rvalid_in, rready_in, rvalid_out, rready_out, wready_in, wvalid_in : std_logic; + signal rdata_out, wdata_in : std_logic_vector(WORD_WIDTH-1 downto 0); begin - + + buffer_inst : entity work.dp_mem_ctrl(arch) + generic map ( + ADDR_WIDTH => BUFFER_ADDR_WIDTH, + DATA_WIDTH => WORD_WIDTH, + MEMORY_DEPTH => MAX_BUFFER_SIZE, + MAX_BURST_LENGTH => 2 + ) + port map ( + -- SYSTEM + clk => clk, + reset => reset, + -- READ PORT + raddr => std_logic_vector(out_pntr(BUFFER_ADDR_WIDTH-1 downto 0)), + rvalid_in => rvalid_in, + rready_in => rready_in, + rvalid_out => rvalid_out, + rready_out => rready_out, + rdata_out => rdata_out, + -- WRITE PORT + waddr => std_logic_vector(in_pntr(BUFFER_ADDR_WIDTH-1 downto 0)), + wvalid_in => wvalid_in, + wready_in => wready_in, + wdata_in => wdata_in + ); + in_prc : process (all) begin -- DEFAULT @@ -65,17 +96,21 @@ begin ports_next <= ports; buff_next <= buff; length_next <= length; + -- DEFAULT Unregistered rd <= (others => '0'); set_filled <= '0'; + wvalid_in <= '0'; + wdata_in <= (others => '0'); case (input_stage) is when IDLE => -- Currently Selected Input FIFO is empty if (empty(selector) = '1') then - -- Select next input FIFO + -- Wrap from End to BEgining (Circular selection) if (selector = NUM_ENDPOINTS) then selector_next <= 0; else + -- Select next input FIFO selector_next <= selector + 1; end if; else @@ -83,7 +118,7 @@ begin if (filled = '0' and out_pntr /= 0) then -- Read from input FIFO input_stage_next <= SRC_ADDR_HEADER; - in_pntr_next <= 0; + in_pntr_next <= (others => '0'); end if; end if; when SRC_ADDR_HEADER => @@ -97,8 +132,8 @@ begin if (last_word_in(selector) = '1') then -- Skip input_stage_next <= IDLE; - in_pntr_next <= MAX_BUFFER_SIZE; - -- Select next input FIFO + in_pntr_next <= to_unsigned(MAX_BUFFER_SIZE, in_pntr'length); + -- Select next input FIFO (Prevent lifelock) if (selector = NUM_ENDPOINTS) then selector_next <= 0; else @@ -117,8 +152,8 @@ begin if (last_word_in(selector) = '1') then -- Skip input_stage_next <= IDLE; - in_pntr_next <= MAX_BUFFER_SIZE; - -- Select next input FIFO + in_pntr_next <= to_unsigned(MAX_BUFFER_SIZE, in_pntr'length); + -- Select next input FIFO (Prevent lifelock) if (selector = NUM_ENDPOINTS) then selector_next <= 0; else @@ -129,16 +164,16 @@ begin when PORT_HEADER => -- Input FIFO Guard if (empty(selector) = '0') then - rd(selector) <= '1'; - ports_next <= data_in(selector); - input_stage_next<= READ; + rd(selector) <= '1'; + ports_next <= data_in(selector); + input_stage_next <= READ; -- SANITY CHECK: Skip Packet if last word in before actual packet if (last_word_in(selector) = '1') then -- Skip input_stage_next <= IDLE; - in_pntr_next <= MAX_BUFFER_SIZE; - -- Select next input FIFO + in_pntr_next <= to_unsigned(MAX_BUFFER_SIZE, in_pntr'length); + -- Select next input FIFO (Prevent lifelock) if (selector = NUM_ENDPOINTS) then selector_next <= 0; else @@ -151,29 +186,34 @@ begin if (out_pntr > in_pntr) then -- Input FIFO Guard if (empty(selector) = '0') then - rd(selector) <= '1'; - buff_next(in_pntr) <= data_in(selector); - in_pntr_next <= in_pntr + 1; - - -- Last Input Word - if (last_word_in(selector) = '1') then - -- Set Length - length_next <= to_unsigned(in_pntr, WORD_WIDTH); - -- Mark Buffer Ready for Output - set_filled <= '1'; - -- DONE - input_stage_next <= IDLE; - in_pntr_next <= MAX_BUFFER_SIZE; - -- Select next input FIFO - if (selector = NUM_ENDPOINTS) then - selector_next <= 0; - else - selector_next <= selector + 1; + wdata_in <= data_in(selector); + wvalid_in <= '1'; + -- Memory Guard + if (wready_in = '1') then + rd(selector) <= '1'; + in_pntr_next <= in_pntr + 1; + + -- Last Input Word + if (last_word_in(selector) = '1') then + assert (in_pntr'length <= WORD_WIDTH) severity FAILURE; + -- Set Length + length_next <= resize(in_pntr, WORD_WIDTH); + -- Mark Buffer Ready for Output + set_filled <= '1'; + -- DONE + input_stage_next <= IDLE; + in_pntr_next <= to_unsigned(MAX_BUFFER_SIZE, in_pntr'length); + -- Select next input FIFO (Prevent lifelock) + if (selector = NUM_ENDPOINTS) then + selector_next <= 0; + else + selector_next <= selector + 1; + end if; + -- Overflow (Packet larger than buffer) + elsif (in_pntr = MAX_BUFFER_SIZE-1) then + -- SKIP PACKET + input_stage_next <= SKIP; end if; - -- Overflow (Packet larger than buffer) - elsif (in_pntr = MAX_BUFFER_SIZE-1) then - -- SKIP PACKET - input_stage_next <= SKIP; end if; end if; end if; @@ -186,8 +226,8 @@ begin if (last_word_in(selector) = '1') then -- DONE input_stage_next <= IDLE; - in_pntr_next <= MAX_BUFFER_SIZE; - -- Select next input FIFO + in_pntr_next <= to_unsigned(MAX_BUFFER_SIZE, in_pntr'length); + -- Select next input FIFO (Prevent lifelock) if (selector = NUM_ENDPOINTS) then selector_next <= 0; else @@ -208,14 +248,17 @@ begin wr <= '0'; data_out <= (others => '0'); packet_end_next <= packet_end; + -- DEFAULT Unregistered reset_filled <= '0'; + rvalid_in <= '0'; + rready_out <= '0'; case (output_stage) is when IDLE => -- Wait until Buffer is Ready if (filled = '1') then output_stage_next <= SRC_ADDR_HEADER; - out_pntr_next <= 0; + out_pntr_next <= (others => '0'); -- Mark Buffer as being processed reset_filled <= '1'; end if; @@ -246,21 +289,52 @@ begin wr <= '1'; data_out <= std_logic_vector(length + 1); packet_end_next <= length; - output_stage_next <= WRITE; + output_stage_next <= WRITE_PRIMER; + end if; + when WRITE_PRIMER => + -- Prime the Memory Controller with Read Requests + -- XXX: Optimized for Read Latency = 1 + rvalid_in <= '1'; + -- + if (rready_in = '1') then + if (out_pntr = packet_end) then + -- DONE Reading + output_stage_next <= FINALIZE_WRITE; + out_pntr_next <= to_unsigned(MAX_BUFFER_SIZE, out_pntr'length); + else + output_stage_next <= WRITE; + out_pntr_next <= out_pntr + 1; + end if; end if; when WRITE => -- Output FIFO Guard - if (full = '0') then - wr <= '1'; - out_pntr_next <= out_pntr + 1; - data_out <= buff(out_pntr); + if (full = '0' and rvalid_out = '1') then + data_out <= rdata_out; - if (out_pntr = packet_end) then - -- DONE - output_stage_next <= IDLE; - out_pntr_next <= MAX_BUFFER_SIZE; + -- Memory Guard + if (rready_in = '1') then + rvalid_in <= '1'; + rready_out <= '1'; + wr <= '1'; + out_pntr_next <= out_pntr + 1; + + if (out_pntr = packet_end) then + -- DONE Reading + output_stage_next <= FINALIZE_WRITE; + out_pntr_next <= to_unsigned(MAX_BUFFER_SIZE, out_pntr'length); + end if; end if; end if; + when FINALIZE_WRITE => + -- Output FIFO Guard + if (full = '0' and rvalid_out = '1') then + data_out <= rdata_out; + rready_out <= '1'; + wr <= '1'; + + -- DONE + output_stage_next <= IDLE; + end if; when others => null; end case; @@ -291,8 +365,8 @@ begin input_stage <= IDLE; output_stage <= IDLE; selector <= 0; - in_pntr <= MAX_BUFFER_SIZE; - out_pntr <= MAX_BUFFER_SIZE; + in_pntr <= to_unsigned(MAX_BUFFER_SIZE, in_pntr'length); + out_pntr <= to_unsigned(MAX_BUFFER_SIZE, out_pntr'length); src_addr <= IPv4_ADDRESS_INVALID; dest_addr <= IPv4_ADDRESS_INVALID; ports <= UDP_PORT_INVALID & UDP_PORT_INVALID;