diff options
Diffstat (limited to 'fpga/usrp3/lib/vivado_ipi/axi_regfile/axi_regfile.vhd')
| -rw-r--r-- | fpga/usrp3/lib/vivado_ipi/axi_regfile/axi_regfile.vhd | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/vivado_ipi/axi_regfile/axi_regfile.vhd b/fpga/usrp3/lib/vivado_ipi/axi_regfile/axi_regfile.vhd new file mode 100644 index 000000000..3ec84543f --- /dev/null +++ b/fpga/usrp3/lib/vivado_ipi/axi_regfile/axi_regfile.vhd @@ -0,0 +1,144 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity axi_regfile is +generic ( + NUM_REGS : integer := 16 +); +port ( + regs : out std_logic_vector(NUM_REGS*32-1 downto 0); + + S_AXI_ACLK : in std_logic; + S_AXI_ARESETN : in std_logic; + S_AXI_AWADDR : in std_logic_vector(11 downto 0); + S_AXI_AWVALID : in std_logic; + S_AXI_AWREADY : out std_logic; + S_AXI_WDATA : in std_logic_vector(31 downto 0); + S_AXI_WSTRB : in std_logic_vector(3 downto 0); + S_AXI_WVALID : in std_logic; + S_AXI_WREADY : out std_logic; + S_AXI_BRESP : out std_logic_vector(1 downto 0); + S_AXI_BVALID : out std_logic; + S_AXI_BREADY : in std_logic; + S_AXI_ARADDR : in std_logic_vector(11 downto 0); + S_AXI_ARVALID : in std_logic; + S_AXI_ARREADY : out std_logic; + S_AXI_RDATA : out std_logic_vector(31 downto 0); + S_AXI_RRESP : out std_logic_vector(1 downto 0); + S_AXI_RVALID : out std_logic; + S_AXI_RREADY : in std_logic +); +end axi_regfile; + +architecture arch of axi_regfile is + type regfile_t is array (integer range <>) of std_logic_vector(31 downto 0); + signal read_token : std_logic; + signal write_addr : std_logic_vector(S_AXI_AWADDR'left downto S_AXI_AWADDR'right); + signal write_strb : std_logic_vector(3 downto 0); + signal write_addr_token : std_logic; + signal write_data : std_logic_vector(31 downto 0); + signal write_data_token : std_logic; + signal soft_reset : std_logic; + signal regs_r : regfile_t(NUM_REGS-1 downto 0); +begin + + S_AXI_ARREADY <= not read_token; + S_AXI_RVALID <= read_token; + S_AXI_RRESP <= "00"; + + S_AXI_AWREADY <= not write_addr_token; + S_AXI_WREADY <= not write_data_token; + S_AXI_BVALID <= write_addr_token and write_data_token; + S_AXI_BRESP <= "00"; + + --Port assignment from registers + reg_distribution : process (regs_r) + begin + for i in 0 to NUM_REGS-1 loop + regs(32*(i+1)-1 downto 32*i) <= regs_r(i); + end loop; + end process reg_distribution; + + --Register reads + read_proc : process (S_AXI_ACLK) + variable read_addr : integer; + begin + if rising_edge(S_AXI_ACLK) then + read_addr := to_integer(unsigned(S_AXI_ARADDR(S_AXI_ARADDR'left downto S_AXI_ARADDR'right+2))); + + if (S_AXI_ARESETN = '0') then + read_token <= '0'; + elsif (S_AXI_ARVALID = '1') and (read_token = '0') then + read_token <= '1'; + elsif (S_AXI_RREADY = '1') and (read_token = '1') then + read_token <= '0'; + end if; + + if (S_AXI_ARVALID = '1') and (read_token = '0') then + S_AXI_RDATA <= (others => '0'); + for i in 0 to NUM_REGS-1 loop + if (read_addr = i) then + S_AXI_RDATA <= regs_r(i); + end if; + end loop; + end if; + end if; + end process read_proc; + + write_proc : process (S_AXI_ACLK) + begin + if rising_edge(S_AXI_ACLK) then + if (S_AXI_ARESETN = '0') then + write_addr_token <= '0'; + write_data_token <= '0'; + write_strb <= (others => '0'); + else + if (S_AXI_AWVALID = '1') and (write_addr_token = '0') then + write_addr_token <= '1'; + elsif (S_AXI_BREADY = '1') and (write_addr_token = '1') and (write_data_token = '1') then + write_addr_token <= '0'; + end if; + + if (S_AXI_WVALID = '1') and (write_data_token = '0') then + write_data_token <= '1'; + elsif (S_AXI_BREADY = '1') and (write_addr_token = '1') and (write_data_token = '1') then + write_data_token <= '0'; + end if; + end if; + + if (S_AXI_AWVALID = '1') and (write_addr_token = '0') then + write_addr <= S_AXI_AWADDR; + end if; + + if (S_AXI_WVALID = '1') and (write_data_token = '0') then + write_data <= S_AXI_WDATA; + write_strb <= S_AXI_WSTRB; + end if; + end if; + end process write_proc; + + -- Update registers on write + write_reg : process (S_AXI_ACLK) + variable write_addr_int : integer; + begin + if rising_edge(S_AXI_ACLK) then + write_addr_int := to_integer(unsigned(write_addr(write_addr'left downto 2))); + + if (S_AXI_ARESETN = '0') or (soft_reset = '1') then + --Initial states for each signal + soft_reset <= '0'; + elsif (write_addr_token = '1') and (write_data_token = '1') then + for i in 0 to NUM_REGS-1 loop + if (write_addr_int = i) then + for j in write_strb'left downto write_strb'right loop + regs_r(i)(j*8+7 downto j*8) <= write_data(j*8+7 downto j*8); + end loop; + end if; + end loop; + end if; + end if; + end process write_reg; + +end arch; + |
