|
| 1 | +library ieee; |
| 2 | +use ieee.std_logic_1164.all; |
| 3 | +use ieee.numeric_std_unsigned.all; |
| 4 | + |
| 5 | +use work.incrementer_pkg.all; |
| 6 | + |
| 7 | +entity incrementer is |
| 8 | + generic( |
| 9 | + delay : positive := 1); |
| 10 | + port( |
| 11 | + clk : in std_logic; |
| 12 | + |
| 13 | + input_tdata : in std_logic_vector; |
| 14 | + input_tvalid : in std_logic; |
| 15 | + input_tready : out std_logic; |
| 16 | + input_tlast : in std_logic := '1'; |
| 17 | + |
| 18 | + output_tdata : out std_logic_vector; |
| 19 | + output_tvalid : out std_logic := '0'; |
| 20 | + output_tready : in std_logic := '1'; |
| 21 | + output_tlast : out std_logic := '0'; |
| 22 | + |
| 23 | + ctrl_arready : out std_logic := '0'; |
| 24 | + ctrl_arvalid : in std_logic := '0'; |
| 25 | + ctrl_araddr : in std_logic_vector(7 downto 0) := x"00"; |
| 26 | + |
| 27 | + ctrl_rready : in std_logic := '0'; |
| 28 | + ctrl_rvalid : out std_logic := '0'; |
| 29 | + ctrl_rdata : out std_logic_vector(31 downto 0) := (others => '0'); |
| 30 | + ctrl_rresp : out std_logic_vector(1 downto 0) := "00"; |
| 31 | + |
| 32 | + ctrl_awready : out std_logic := '0'; |
| 33 | + ctrl_awvalid : in std_logic := '0'; |
| 34 | + ctrl_awaddr : in std_logic_vector(7 downto 0) := x"00"; |
| 35 | + |
| 36 | + ctrl_wready : out std_logic := '0'; |
| 37 | + ctrl_wvalid : in std_logic := '0'; |
| 38 | + ctrl_wdata : in std_logic_vector(31 downto 0) := (others => '0'); |
| 39 | + ctrl_wstrb : in std_logic_vector(3 downto 0) := x"0"; |
| 40 | + |
| 41 | + ctrl_bvalid : out std_logic := '0'; |
| 42 | + ctrl_bready : in std_logic := '0'; |
| 43 | + ctrl_bresp : out std_logic_vector(1 downto 0) := "00"); |
| 44 | +begin |
| 45 | + assert input_tdata'length = output_tdata'length; |
| 46 | +end; |
| 47 | + |
| 48 | +architecture a of incrementer is |
| 49 | + type state_t is (idle, |
| 50 | + writing, |
| 51 | + write_response, |
| 52 | + reading); |
| 53 | + |
| 54 | + signal increment : std_logic_vector(input_tdata'length - 1 downto 0) := (0 => '1', others => '0'); |
| 55 | + signal state : state_t := idle; |
| 56 | + signal addr : std_logic_vector(ctrl_araddr'range); |
| 57 | +begin |
| 58 | + main : process is |
| 59 | + type delay_line_t is array (natural range <>) of std_logic_vector(input_tdata'length + 1 downto 0); |
| 60 | + variable delay_line : delay_line_t(1 to delay + 1) := (others => (others => '0')); |
| 61 | + begin |
| 62 | + wait until rising_edge(clk); |
| 63 | + if not output_tvalid or output_tready then |
| 64 | + delay_line(1) := input_tlast & (input_tvalid and input_tready) & input_tdata; |
| 65 | + delay_line(2 to delay) := delay_line(1 to delay - 1); |
| 66 | + end if; |
| 67 | + output_tlast <= delay_line(delay)(input_tdata'length + 1); |
| 68 | + output_tvalid <= delay_line(delay)(input_tdata'length); |
| 69 | + output_tdata <= delay_line(delay)(input_tdata'length - 1 downto 0) + increment; |
| 70 | + end process main; |
| 71 | + |
| 72 | + input_tready <= not output_tvalid or output_tready; |
| 73 | + |
| 74 | + ctrl : process is |
| 75 | + constant axi_response_ok : std_logic_vector(1 downto 0) := "00"; |
| 76 | + constant axi_response_decerr : std_logic_vector(1 downto 0) := "11"; |
| 77 | + |
| 78 | + -- Compare addresses of 32-bit words discarding byte address |
| 79 | + function cmp_word_address(byte_addr : std_logic_vector; |
| 80 | + word_addr : natural) return boolean is |
| 81 | + begin |
| 82 | + return to_integer(byte_addr(byte_addr'left downto 2)) = word_addr/4; |
| 83 | + end; |
| 84 | + |
| 85 | + begin |
| 86 | + wait until rising_edge(clk); |
| 87 | + |
| 88 | + ctrl_arready <= '0'; |
| 89 | + ctrl_awready <= '0'; |
| 90 | + ctrl_wready <= '0'; |
| 91 | + ctrl_rvalid <= '0'; |
| 92 | + ctrl_rdata <= (others => '0'); |
| 93 | + |
| 94 | + case state is |
| 95 | + when idle => |
| 96 | + |
| 97 | + if ctrl_arvalid then |
| 98 | + ctrl_arready <= '1'; |
| 99 | + addr <= ctrl_araddr; |
| 100 | + state <= reading; |
| 101 | + |
| 102 | + elsif ctrl_awvalid then |
| 103 | + ctrl_awready <= '1'; |
| 104 | + addr <= ctrl_awaddr; |
| 105 | + state <= writing; |
| 106 | + end if; |
| 107 | + |
| 108 | + when writing => |
| 109 | + if ctrl_wvalid then |
| 110 | + ctrl_wready <= '1'; |
| 111 | + |
| 112 | + ctrl_bvalid <= '1'; |
| 113 | + ctrl_bresp <= axi_response_ok; |
| 114 | + |
| 115 | + state <= write_response; |
| 116 | + |
| 117 | + -- Ignore byte write enable |
| 118 | + if cmp_word_address(addr, increment_reg_addr) then |
| 119 | + increment <= ctrl_wdata(increment'length - 1 downto 0); |
| 120 | + end if; |
| 121 | + end if; |
| 122 | + |
| 123 | + when write_response => |
| 124 | + if ctrl_bready then |
| 125 | + ctrl_bvalid <= '0'; |
| 126 | + state <= idle; |
| 127 | + end if; |
| 128 | + |
| 129 | + when reading => |
| 130 | + if not ctrl_rvalid then |
| 131 | + ctrl_rvalid <= '1'; |
| 132 | + ctrl_rresp <= axi_response_ok; |
| 133 | + |
| 134 | + if cmp_word_address(addr, increment_reg_addr) then |
| 135 | + ctrl_rdata(increment'range) <= increment; |
| 136 | + else |
| 137 | + ctrl_rresp <= axi_response_decerr; |
| 138 | + end if; |
| 139 | + |
| 140 | + elsif ctrl_rready then |
| 141 | + state <= idle; |
| 142 | + end if; |
| 143 | + end case; |
| 144 | + |
| 145 | + end process ctrl; |
| 146 | +end; |
0 commit comments