signal MCC_MUX_CODE : std_logic_vector (MUX_W-1 downto 0);
signal MCC_MUX_EN : std_logic;
+ signal MUL_A : std_logic_vector (15 downto 0);
+ signal MUL_B : std_logic_vector (15 downto 0);
+ signal MUL_PROD : std_logic_vector (31 downto 0);
+
signal MASTER_IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0);
signal MASTER_IRF_DAT_O : std_logic_vector (15 downto 0);
signal MASTER_IRF_STB_O : std_logic;
signal VECTOR_IRF_STB_O : std_logic;
signal VECTOR_IRF_WE_O : std_logic;
+ signal SCALE_IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0);
+ signal SCALE_IRF_DAT_O : std_logic_vector (15 downto 0);
+ signal SCALE_IRF_STB_O : std_logic;
+ signal SCALE_IRF_WE_O : std_logic;
+ signal SCALE_SL_ACK_O : std_logic;
+ signal SCALE_SL_IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0);
+ signal SCALE_SL_STB_I : std_logic;
+
signal PWM_IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0);
signal PWM_IRF_DAT_O : std_logic_vector (15 downto 0);
signal PWM_IRF_STB_O : std_logic;
IRC_IRF_ADR_O when MCC_MUX_CODE = 0 else
BASE_IRF_ADR_O when MCC_MUX_CODE = 1 else
VECTOR_IRF_ADR_O when MCC_MUX_CODE = 2 else
+ SCALE_IRF_ADR_O when MCC_MUX_CODE = 3 else
PWM_IRF_ADR_O when MCC_MUX_CODE = 5 else
(others => '-');
IRC_IRF_DAT_O when MCC_MUX_CODE = 0 else
BASE_IRF_DAT_O when MCC_MUX_CODE = 1 else
VECTOR_IRF_DAT_O when MCC_MUX_CODE = 2 else
+ SCALE_IRF_DAT_O when MCC_MUX_CODE = 3 else
PWM_IRF_DAT_O when MCC_MUX_CODE = 5 else
(others => '-');
IRC_IRF_STB_O when MCC_MUX_CODE = 0 else
BASE_IRF_STB_O when MCC_MUX_CODE = 1 else
VECTOR_IRF_STB_O when MCC_MUX_CODE = 2 else
+ SCALE_IRF_STB_O when MCC_MUX_CODE = 3 else
PWM_IRF_STB_O when MCC_MUX_CODE = 5 else
'0';
IRC_IRF_WE_O when MCC_MUX_CODE = 0 else
BASE_IRF_WE_O when MCC_MUX_CODE = 1 else
VECTOR_IRF_WE_O when MCC_MUX_CODE = 2 else
+ SCALE_IRF_WE_O when MCC_MUX_CODE = 3 else
'0';
IRF_STB_O => MASTER_IRF_STB_O,
IRF_WE_O => MASTER_IRF_WE_O);
+ multiplier_1 : entity work.multiplier
+ port map (
+ A => MUL_A,
+ B => MUL_B,
+ prod => MUL_PROD);
+
irc_dump_1 : entity work.irc_dump
generic map (
IRF_ADR_W => IRF_ADR_W,
IRF_ADR_W => 5,
A_BASE => 16#04#,
P_BASE => 16#10#,
- P1_OFF => 16#01#,
- P2_OFF => 16#05#,
- P3_OFF => 16#09#)
+ P1_OFF => 16#00#,
+ P2_OFF => 16#04#,
+ P3_OFF => 16#08#)
port map (
ACK_O => MCC_ACK (2),
CLK_I => CLK_I,
LUT_DAT_I => LUT_DAT_I,
LUT_STB_O => LUT_STB_O);
+ vector_scale_sequencer : entity work.sequencer
+ generic map (
+ IRF_ADR_W => IRF_ADR_W,
+ P_BASE => P_BASE,
+ P_SIZE => P_SIZE)
+ port map (
+ ACK_O => MCC_ACK (3),
+ CLK_I => CLK_I,
+ RST_I => RST_I,
+ STB_I => MCC_STB (3),
+ IRF_ADR_O => SCALE_IRF_ADR_O,
+ SL_ACK_I => SCALE_SL_ACK_O,
+ SL_IRF_ADR_I => SCALE_SL_IRF_ADR_O,
+ SL_STB_O => SCALE_SL_STB_I,
+ SL_MUX_CODE => open);
+
+ vector_scale_1 : entity work.vector_scale
+ generic map (
+ IRF_ADR_W => IRF_ADR_W,
+ BASE => 0,
+ SCALE_OFF => 5,
+ PHASE_BASE => P_BASE,
+ VECTOR_OFF => 0,
+ SCALED_OFF => 1,
+ VECTOR_W => LUT_DAT_W)
+ port map (
+ ACK_O => SCALE_SL_ACK_O,
+ CLK_I => CLK_I,
+ RST_I => RST_I,
+ STB_I => SCALE_SL_STB_I,
+ MUL_A => MUL_A,
+ MUL_B => MUL_B,
+ MUL_PROD => MUL_PROD,
+ IRF_ACK_I => IRF_ACK_I,
+ IRF_ADR_O => SCALE_SL_IRF_ADR_O,
+ IRF_DAT_I => IRF_DAT_I,
+ IRF_DAT_O => SCALE_IRF_DAT_O,
+ IRF_STB_O => SCALE_IRF_STB_O,
+ IRF_WE_O => SCALE_IRF_WE_O);
+
+
pwm_dump_sequencer : entity work.sequencer
generic map (
IRF_ADR_W => IRF_ADR_W,
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_signed.all;
+
+--------------------------------------------------------------------------------
+
+entity multiplier is
+ port (
+ A : in std_logic_vector (15 downto 0);
+ B : in std_logic_vector (15 downto 0);
+ prod : out std_logic_vector (31 downto 0));
+end multiplier;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of multiplier is
+
+--------------------------------------------------------------------------------
+
+begin
+
+ prod <= A * B;
+
+end behavioral;
+
# bottom to up order (e.g. the top entity is the last in this list). Otherwise
# it won't compile.
-VHDL_MAIN = tb_mcc
+VHDL_MAIN = tb_vector_scale
VHDL_ENTITIES = counter.o \
pwm.o \
wave_table.o \
priority_encoder.o \
mcc_master.o \
sequencer.o \
+ multiplier.o \
+ vector_scale.o \
pwm_dump.o \
irc_dump.o \
irc_base.o \
--- /dev/null
+[timestart] 5270000000
+[size] 1280 769
+[pos] -1 -1
+*-32.512638 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+@24
+test_vector_no[31:0]
+@200
+-
+@420
+a[15:0]
+b[15:0]
+prod[31:0]
+@200
+-
+@22
+a[15:0]
+b[15:0]
+prod[31:0]
+[pattern_trace] 1
+[pattern_trace] 0
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_signed.all;
+
+entity tb_multiplier is
+end tb_multiplier;
+
+--------------------------------------------------------------------------------
+
+architecture testbench of tb_multiplier is
+
+ constant period : time := 2 us;
+ constant offset : time := 0 us;
+
+
+ signal clk : std_logic;
+ signal reset : std_logic;
+
+ signal A : std_logic_vector (15 downto 0);
+ signal B : std_logic_vector (15 downto 0);
+ signal prod : std_logic_vector (31 downto 0);
+
+ signal test_vector_no : integer := 0;
+
+
+ type test_vector_t is record
+ A : std_logic_vector (15 downto 0);
+ B : std_logic_vector (15 downto 0);
+ prod : std_logic_vector (31 downto 0);
+ end record;
+
+ type test_vector_array is array (natural range<>) of test_vector_t;
+
+ constant test_vectors : test_vector_array := (
+ (X"0000", X"0000", X"00000000"),
+ (X"0000", X"FFFF", X"00000000"),
+ (X"0001", X"0001", X"00000001"),
+ (X"7FFF", X"7FFF", X"3FFF0001"),
+ (X"FFFF", X"0001", X"FFFFFFFF"),
+ (X"FFFF", X"FFFF", X"00000001"),
+ (X"8000", X"7FFF", X"C0008000"),
+ (X"8000", X"FFFF", X"00008000"),
+ (X"8001", X"8001", X"BFFEFFFF"),
+ (X"8000", X"8000", X"C0000000"));
+
+--------------------------------------------------------------------------------
+
+begin
+
+ uut : entity work.multiplier
+ port map (
+ A => A,
+ B => B,
+ prod => prod);
+
+
+ CLK_PROC : process
+ begin
+ clk <= '0';
+ wait for offset;
+
+ loop
+ clk <= '1';
+ wait for period/2;
+ clk <= '0';
+ wait for period/2;
+ end loop;
+ end process;
+
+
+ RSET_PROC : process
+ begin
+ reset <= '0';
+ wait for 1.5 * period;
+ reset <= '1';
+ wait for 1 * period;
+ reset <= '0';
+ wait;
+ end process;
+
+
+ TEST_VECTOR_PROC : process
+ begin
+ A <= (others => '0');
+ B <= (others => '0');
+
+ wait for offset;
+ wait for 3 * period;
+
+ for i in test_vectors'RANGE loop
+ test_vector_no <= i;
+
+ A <= test_vectors(i).A;
+ B <= test_vectors(i).B;
+ wait for period;
+
+ assert prod = test_vectors(i).prod
+ report "Invalid product - test vector no. " & integer'image(i)
+ severity warning;
+ end loop;
+
+ wait;
+ end process;
+
+end testbench;
+
--- /dev/null
+[timestart] 0
+[size] 1280 769
+[pos] -1 -1
+*-31.470821 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+@28
+rst_i
+clk_i
+stb_i
+ack_o
+@200
+-
+@22
+dbg_mem0x05[15:0]
+dbg_mem0x10[15:0]
+dbg_mem0x11[15:0]
+@200
+-
+@22
+mul_a[15:0]
+mul_b[15:0]
+mul_prod[31:0]
+@200
+-
+@28
+irf_stb_o
+irf_we_o
+@c00023
+irf_adr_o[4:0]
+@28
+(0)irf_adr_o[4:0]
+(1)irf_adr_o[4:0]
+(2)irf_adr_o[4:0]
+(3)irf_adr_o[4:0]
+(4)irf_adr_o[4:0]
+@1401201
+-group_end
+@22
+uut.irf_dat_i[15:0]
+irf_dat_o[15:0]
+[pattern_trace] 1
+[pattern_trace] 0
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity tb_vector_scale is
+end tb_vector_scale;
+
+--------------------------------------------------------------------------------
+
+architecture testbench of tb_vector_scale is
+
+ constant period : time := 500 ns;
+ constant offset : time := 0 us;
+
+ constant IRF_ADR_W : integer := 5;
+
+
+ signal ACK_O : std_logic;
+ signal CLK_I : std_logic;
+ signal RST_I : std_logic;
+ signal STB_I : std_logic;
+
+ signal IRF_ACK_I : std_logic;
+ signal IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0);
+ signal IRF_CYC_O : std_logic;
+ signal IRF_DAT_I : std_logic_vector (15 downto 0);
+ signal IRF_DAT_O : std_logic_vector (15 downto 0);
+ signal IRF_STB_O : std_logic;
+ signal IRF_WE_O : std_logic;
+
+ signal MUL_A : std_logic_vector (15 downto 0);
+ signal MUL_B : std_logic_vector (15 downto 0);
+ signal MUL_PROD : std_logic_vector (31 downto 0);
+
+
+ subtype word_t is std_logic_vector (15 downto 0);
+
+ signal dbg_mem0x05 : word_t := (others => '0');
+ signal dbg_mem0x10 : word_t := (others => '0');
+ signal dbg_mem0x11 : word_t := (others => '0');
+ signal dbg_ack : std_logic := '0';
+
+--------------------------------------------------------------------------------
+
+begin
+
+ uut : entity work.vector_scale
+ generic map (
+ IRF_ADR_W => IRF_ADR_W,
+ BASE => 0,
+ SCALE_OFF => 5,
+ PHASE_BASE => 16,
+ VECTOR_OFF => 0,
+ SCALED_OFF => 1,
+ VECTOR_W => 10)
+ port map (
+ ACK_O => ACK_O,
+ CLK_I => CLK_I,
+ RST_I => RST_I,
+ STB_I => STB_I,
+ MUL_A => MUL_A,
+ MUL_B => MUL_B,
+ MUL_PROD => MUL_PROD,
+ IRF_ACK_I => IRF_ACK_I,
+ IRF_ADR_O => IRF_ADR_O,
+ IRF_DAT_I => IRF_DAT_I,
+ IRF_DAT_O => IRF_DAT_O,
+ IRF_STB_O => IRF_STB_O,
+ IRF_WE_O => IRF_WE_O);
+
+ multiplier_1 : entity work.multiplier
+ port map (
+ A => MUL_A,
+ B => MUL_B,
+ prod => MUL_PROD);
+
+
+ SYSCON_CLK : process is
+ begin
+ CLK_I <= '0';
+ wait for offset;
+ loop
+ CLK_I <= '1';
+ wait for period/2;
+ CLK_I <= '0';
+ wait for period/2;
+ end loop;
+ end process;
+
+ SYSCON_RST : process is
+ begin
+ RST_I <= '0';
+ wait for offset;
+ wait for 0.75*period;
+ RST_I <= '1';
+ wait for 2*period;
+ RST_I <= '0';
+ wait;
+ end process;
+
+
+ DBG_MEM : process (IRF_STB_O, CLK_I) is
+ begin
+ IRF_ACK_I <= IRF_STB_O and (IRF_WE_O or dbg_ack);
+
+ if rising_edge(CLK_I) then
+ dbg_ack <= IRF_STB_O;
+ end if;
+
+ if rising_edge(CLK_I) and IRF_STB_O = '1' then
+ if IRF_WE_O = '0' then
+ case conv_integer(IRF_ADR_O) is
+ when 16#05# => IRF_DAT_I <= dbg_mem0x05;
+ when 16#10# => IRF_DAT_I <= dbg_mem0x10;
+ when 16#11# => IRF_DAT_I <= dbg_mem0x11;
+ when others =>
+ IRF_DAT_I <= (others => '0');
+ report "Reading from non-existing register" severity warning;
+ end case;
+ else
+ case conv_integer(IRF_ADR_O) is
+ --when 16#05# => dbg_mem0x05 <= IRF_DAT_O;
+ --when 16#10# => dbg_mem0x10 <= IRF_DAT_O;
+ when 16#11# => dbg_mem0x11 <= IRF_DAT_O;
+ when others =>
+ report "Writing to read-only registers" severity error;
+ end case;
+ end if;
+ end if;
+ end process;
+
+--------------------------------------------------------------------------------
+
+ UUT_FEED : process is
+ begin
+ STB_I <= '0';
+
+ wait for offset;
+ wait for 4*period;
+
+ for i in 0 to 10 loop
+ dbg_mem0x10 <= "0000000111111111";
+
+ dbg_mem0x05 <= conv_std_logic_vector(i*(2**10), 16);
+
+ wait for 0.75*period;
+ STB_I <= '1';
+ wait for 0.25*period;
+ wait until rising_edge(CLK_I) and ACK_O = '1';
+ wait for 0.25*period;
+ STB_I <= '0';
+ wait for 0.75*period;
+
+ wait for 4*period;
+ end loop;
+
+ wait;
+ end process;
+
+end testbench;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_signed.all;
+
+--------------------------------------------------------------------------------
+
+entity vector_scale is
+ generic (
+ IRF_ADR_W : integer := 5;
+ BASE : integer := 0;
+ SCALE_OFF : integer := 5;
+ PHASE_BASE : integer := 16;
+ VECTOR_OFF : integer := 0;
+ SCALED_OFF : integer := 1;
+ VECTOR_W : integer := 10);
+ port (
+ -- Primary slave intefrace
+ ACK_O : out std_logic;
+ CLK_I : in std_logic;
+ RST_I : in std_logic;
+ STB_I : in std_logic;
+ -- Multiplier interface
+ MUL_A : out std_logic_vector (15 downto 0);
+ MUL_B : out std_logic_vector (15 downto 0);
+ MUL_PROD : in std_logic_vector (31 downto 0);
+ -- Shared dual-port memory
+ IRF_ACK_I : in std_logic;
+ IRF_ADR_O : out std_logic_vector (IRF_ADR_W-1 downto 0);
+ IRF_DAT_I : in std_logic_vector (15 downto 0);
+ IRF_DAT_O : out std_logic_vector (15 downto 0);
+ IRF_STB_O : out std_logic;
+ IRF_WE_O : out std_logic);
+end entity vector_scale;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of vector_scale is
+
+ constant SCALE_SUBDIV : integer := 10;
+
+ type state_t is (ready, load_scale, load_vector, save_scaled, done);
+ subtype irf_adr_t is std_logic_vector (IRF_ADR_W-1 downto 0);
+
+ constant SCALE_ADR : irf_adr_t := conv_std_logic_vector(BASE + SCALE_OFF, IRF_ADR_W);
+ constant VECTOR_ADR : irf_adr_t := conv_std_logic_vector(PHASE_BASE + VECTOR_OFF, IRF_ADR_W);
+ constant SCALED_ADR : irf_adr_t := conv_std_logic_vector(PHASE_BASE + SCALED_OFF, IRF_ADR_W);
+
+ signal state : state_t;
+
+ signal INNER_ACK : std_logic;
+
+
+ function twos_to_biased (twos : std_logic_vector) return std_logic_vector is
+ variable result : std_logic_vector (twos'RANGE);
+ begin
+ result := twos;
+ result(result'HIGH) := not twos(twos'HIGH);
+ return result;
+ end;
+
+ function biased_to_twos (biased : std_logic_vector) return std_logic_vector is
+ variable result : std_logic_vector (biased'range);
+ begin
+ result := biased;
+ result(result'HIGH) := not biased(biased'HIGH);
+ return result;
+ end;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ ACK_O <= STB_I and INNER_ACK;
+
+ IRF_DAT_O <= "000000" & twos_to_biased(conv_std_logic_vector(signed(MUL_PROD(15+SCALE_SUBDIV downto SCALE_SUBDIV)), 10));
+
+
+ FSM : process (CLK_I, RST_I) is
+ begin
+ if RST_I = '1' then
+ state <= ready;
+ INNER_ACK <= '0';
+ IRF_STB_O <= '0';
+ IRF_WE_O <= '0';
+
+ elsif rising_edge(CLK_I) then
+ case state is
+ when ready =>
+ if STB_I = '1' then
+ state <= load_scale;
+ IRF_ADR_O <= SCALE_ADR;
+ IRF_STB_O <= '1';
+ end if;
+
+ when load_scale =>
+ state <= load_vector;
+ IRF_ADR_O <= VECTOR_ADR;
+
+ when load_vector =>
+ state <= save_scaled;
+ IRF_ADR_O <= SCALED_ADR;
+ MUL_A <= IRF_DAT_I;
+
+ when save_scaled =>
+ state <= done;
+ INNER_ACK <= '1';
+ IRF_WE_O <= '1';
+ MUL_B <= conv_std_logic_vector(signed(biased_to_twos(IRF_DAT_I(VECTOR_W-1 downto 0))), 16);
+
+ when done =>
+ IRF_STB_O <= '0';
+ IRF_WE_O <= '0';
+ if STB_I = '0' then
+ state <= ready;
+ INNER_ACK <= '0';
+ end if;
+ end case;
+ end if;
+ end process;
+
+end architecture behavioral;
+