126 lines
4.1 KiB
VHDL
126 lines
4.1 KiB
VHDL
-- wg_mem
|
|
--
|
|
-- Generate weights using stream of idx
|
|
--
|
|
-- Inputs are spike index and location of kernel to read
|
|
--
|
|
-- Current implementation assumes that all weights are cached
|
|
-- and that sizes of and KI and KO are powers of 2
|
|
|
|
use work.pkg_sbs.all;
|
|
|
|
entity wg_mem is
|
|
generic (
|
|
LOG2_H : natural := 2; -- size of H (number of output IPs per
|
|
-- output location)
|
|
LOG2_KI : natural := 4; -- number IPs per input (thus spike index)
|
|
LOG2_KO : natural := 3); -- number connections from IPi
|
|
-- block to IPo block (thus,
|
|
-- number of output IPs of full connected,
|
|
-- kernel size in conv)
|
|
port (
|
|
clk, rstn : in bit;
|
|
|
|
-- Initial update
|
|
do_init_str : in bit; -- First step in init process
|
|
do_init_nxt : in bit; -- Next step in init process
|
|
w_init : in real; -- Weight value to update
|
|
|
|
-- Normal
|
|
idx : in bit_vector(LOG2_KI-1 downto 0); -- Index of spike
|
|
pos : in bit_vector(LOG2_KO-1 downto 0); -- Location of output (edge, kernel)
|
|
ena_idx : in bit;
|
|
busy_idx : out bit;
|
|
ena_w : out bit; -- Send a weight
|
|
w : out real); -- stream of states
|
|
|
|
end entity wg_mem;
|
|
|
|
library ieee;
|
|
use ieee.numeric_bit.all;
|
|
|
|
architecture rtl of wg_mem is
|
|
|
|
signal busy_rg, busy_nxt, i_done, idx_done, pos_done : bit;
|
|
signal idx_rg, idx_nxt : unsigned(LOG2_KI-1 downto 0);
|
|
signal pos_rg, pos_nxt : unsigned(LOG2_KO-1 downto 0);
|
|
signal i_rg, i_nxt : unsigned(LOG2_H-1 downto 0);
|
|
|
|
-- All these params could be configurable..
|
|
constant I_LAST : unsigned(LOG2_H-1 downto 0) := (others=>'1');
|
|
constant IDX_LAST : unsigned(LOG2_KI-1 downto 0) := (others=>'1');
|
|
constant POS_LAST : unsigned(LOG2_KO-1 downto 0) := (others=>'1');
|
|
|
|
constant I_ZERO : unsigned(LOG2_H-1 downto 0) := (others=>'0');
|
|
constant IDX_ZERO : unsigned(LOG2_KI-1 downto 0) := (others=>'0');
|
|
constant POS_ZERO : unsigned(LOG2_KO-1 downto 0) := (others=>'0');
|
|
|
|
-- Memory
|
|
signal mem_addr, mem_addr_nxt : unsigned(LOG2_H+LOG2_KI+LOG2_KO-1 downto 0);
|
|
signal mem_wr, mem_rd : bit;
|
|
|
|
begin -- architecture rtl
|
|
|
|
busy_idx <= busy_rg;
|
|
ena_w <= busy_rg;
|
|
|
|
i_done <= '1' when i_rg = I_ZERO else '0';
|
|
idx_done <= '1' when idx_rg = IDX_ZERO else '0';
|
|
pos_done <= '1' when pos_rg = POS_ZERO else '0';
|
|
|
|
busy_nxt <= '1' when ena_idx='1' else
|
|
'0' when i_done='1' else
|
|
busy_rg;
|
|
|
|
i_nxt <= I_LAST when (ena_idx='1') or (do_init_str='1') else
|
|
i_nxt-1 when (busy_rg='1') or (do_init_nxt='1') else
|
|
i_rg;
|
|
|
|
idx_nxt <= unsigned(idx) when ena_idx='1' else
|
|
IDX_LAST when do_init_str='1' else
|
|
idx_nxt-1 when (do_init_nxt='1') and (i_done='1') else
|
|
idx_rg;
|
|
|
|
pos_nxt <= unsigned(pos) when ena_idx='1' else
|
|
POS_LAST when do_init_str='1' else
|
|
pos_nxt-1 when (do_init_nxt='1') and (idx_done='1') else
|
|
pos_rg;
|
|
|
|
reg: process (clk, rstn) is
|
|
begin -- process reg
|
|
if rstn = '0' then -- asynchronous reset (active low)
|
|
idx_rg <= IDX_LAST;
|
|
pos_rg <= POS_LAST;
|
|
i_rg <= I_LAST;
|
|
busy_rg <= '0';
|
|
elsif clk'event and clk = '1' then -- rising clock edge
|
|
idx_rg <= idx_nxt;
|
|
pos_rg <= pos_nxt;
|
|
i_rg <= i_nxt;
|
|
busy_rg <= busy_nxt;
|
|
end if;
|
|
end process reg;
|
|
|
|
|
|
mem_addr_nxt <= pos_nxt & idx_nxt & i_nxt;
|
|
mem_wr <= do_init_str or do_init_nxt;
|
|
mem_rd <= '1';
|
|
|
|
-- Implementation of a synchronous single port memory
|
|
mem: process (clk) is
|
|
constant mem_size : natural := 2**(mem_addr'length);
|
|
type mem_ty is array (0 to mem_size-1) of real;
|
|
variable w_mem : mem_ty;
|
|
begin -- process mem
|
|
if clk'event and clk = '1' then -- rising clock edge
|
|
mem_addr <= mem_addr_nxt;
|
|
if mem_wr='1' then
|
|
w_mem(to_integer(mem_addr)) := w_init;
|
|
end if;
|
|
if mem_rd='1' then
|
|
w <= w_mem(to_integer(mem_addr));
|
|
end if;
|
|
end if;
|
|
end process mem;
|
|
|
|
end architecture rtl;
|