aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/vivado_ipi/axi_regfile/axi_regfile.vhd
diff options
context:
space:
mode:
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.vhd144
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;
+