OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [riverlib/] [core/] [arith/] [int_mul.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
-----------------------------------------------------------------------------
2
--! @file
3
--! @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
--! @author    Sergey Khabarov - sergeykhbr@gmail.com
5
--! @brief     Integer multiplier.
6
--! @details   Implemented algorithm provides 4 clocks per instruction
7
------------------------------------------------------------------------------
8
 
9
library ieee;
10
use ieee.std_logic_1164.all;
11
library commonlib;
12
use commonlib.types_common.all;
13
--! RIVER CPU specific library.
14
library riverlib;
15
--! RIVER CPU configuration constants.
16
use riverlib.river_cfg.all;
17
 
18
 
19
entity IntMul is
20
  port (
21
    i_clk  : in std_logic;
22
    i_nrst : in std_logic;
23
    i_ena : in std_logic;                                -- Enable bit
24
    i_unsigned : in std_logic;                           -- Unsigned operands
25
    i_high : in std_logic;                               -- High multiplied bits [127:64]
26
    i_rv32 : in std_logic;                               -- 32-bits operands enable
27
    i_a1 : in std_logic_vector(RISCV_ARCH-1 downto 0);   -- Operand 1
28
    i_a2 : in std_logic_vector(RISCV_ARCH-1 downto 0);   -- Operand 1
29
    o_res : out std_logic_vector(RISCV_ARCH-1 downto 0); -- Result
30
    o_valid : out std_logic;                             -- Result is valid
31
    o_busy : out std_logic                               -- Multiclock instruction under processing
32
  );
33
end;
34
 
35
architecture arch_IntMul of IntMul is
36
 
37
  type Level0Type is array (0 to 31) of std_logic_vector(65 downto 0);
38
  type Level1Type is array (0 to 15) of std_logic_vector(68 downto 0);
39
  type Level2Type is array (0 to 7) of std_logic_vector(73 downto 0);
40
  type Level3Type is array (0 to 3) of std_logic_vector(82 downto 0);
41
  type Level4Type is array (0 to 1) of std_logic_vector(99 downto 0);
42
 
43
  type RegistersType is record
44
      busy : std_logic;
45
      ena : std_logic_vector(3 downto 0);
46
      a1 : std_logic_vector(RISCV_ARCH-1 downto 0);
47
      a2 : std_logic_vector(RISCV_ARCH-1 downto 0);
48
      unsign : std_logic;
49
      high : std_logic;
50
      rv32 : std_logic;
51
      lvl1 : Level1Type;
52
      lvl3 : Level3Type;
53
      result : std_logic_vector(127 downto 0);
54
  end record;
55
 
56
  signal r, rin : RegistersType;
57
 
58
begin
59
 
60
 
61
  comb : process(i_nrst, i_ena, i_unsigned, i_high, i_rv32, i_a1, i_a2, r)
62
    variable v : RegistersType;
63
    variable wb_mux_lvl0 : std_logic_vector(1 downto 0);
64
    variable wb_lvl0 : Level0Type;
65
    variable wb_lvl2 : Level2Type;
66
    variable wb_lvl4 : Level4Type;
67
    variable wb_lvl5 : std_logic_vector(127 downto 0);
68
    variable wb_res32 : std_logic_vector(127 downto 0);
69
    variable wb_res : std_logic_vector(RISCV_ARCH-1 downto 0);
70
  begin
71
 
72
    v := r;
73
 
74
    v.ena := r.ena(2 downto 0) & (i_ena and not r.busy);
75
 
76
    if i_ena = '1' then
77
        v.busy := '1';
78
        if i_rv32 = '1' then
79
            v.a1(31 downto 0) := i_a1(31 downto 0);
80
            if (not i_unsigned and i_a1(31)) = '1' then
81
                v.a1(63 downto 32) := (others => '1');
82
            end if;
83
            v.a2(31 downto 0) := i_a2(31 downto 0);
84
            if (not i_unsigned and i_a2(31)) = '1' then
85
                v.a2(63 downto 32) := (others => '1');
86
            end if;
87
        else
88
            v.a1 := i_a1;
89
            v.a2 := i_a2;
90
        end if;
91
        v.rv32 := i_rv32;
92
        v.unsign := i_unsigned;
93
        v.high := i_high;
94
    end if;
95
 
96
    if r.ena(0) = '1' then
97
        for i in 0 to 31 loop
98
            wb_mux_lvl0 := r.a2(2*i + 1 downto 2*i);
99
            if wb_mux_lvl0 = "00" then
100
                wb_lvl0(i) := (others => '0');
101
            elsif wb_mux_lvl0 = "01" then
102
                wb_lvl0(i) := ("00" & r.a1);
103
            elsif wb_mux_lvl0 = "10" then
104
                wb_lvl0(i) := ("0" & r.a1 & "0");
105
            else
106
                wb_lvl0(i) := ("00" & r.a1) + ("0" & r.a1 & "0");
107
            end if;
108
        end loop;
109
 
110
        for i in 0 to 15 loop
111
            v.lvl1(i) := ("0" & wb_lvl0(2*i + 1) & "00")
112
                       + ("000" & wb_lvl0(2*i));
113
        end loop;
114
    end if;
115
 
116
    if r.ena(1) = '1' then
117
        for i in 0 to 7 loop
118
            wb_lvl2(i) := ("0" & r.lvl1(2*i + 1) & "0000")
119
                        + ("00000" & r.lvl1(2*i));
120
        end loop;
121
 
122
        for i in 0 to 3 loop
123
            v.lvl3(i) := ("0" & wb_lvl2(2*i + 1) & "00000000")
124
                       + ("000000000" & wb_lvl2(2*i));
125
        end loop;
126
    end if;
127
 
128
    if r.ena(2) = '1' then
129
        v.busy := '0';
130
        for i in 0 to 1 loop
131
            wb_lvl4(i) := ("0" & r.lvl3(2*i + 1) & "0000000000000000")
132
                        + ("00000000000000000" & r.lvl3(2*i));
133
        end loop;
134
 
135
        wb_lvl5 := (wb_lvl4(1)(95 downto 0) & X"00000000")
136
                 + (X"0000000" & wb_lvl4(0));
137
        if r.rv32 = '1' then
138
            wb_res32(31 downto 0) := wb_lvl5(31 downto 0);
139
            if r.unsign = '1' or wb_lvl5(31) = '0' then
140
                wb_res32(127 downto 32) := (others => '0');
141
            else
142
                wb_res32(127 downto 32) := (others => '1');
143
            end if;
144
            v.result := wb_res32;
145
        else
146
            v.result := wb_lvl5;
147
        end if;
148
    end if;
149
 
150
    wb_res := r.result(63 downto 0);
151
    if r.high = '1' then
152
        wb_res := r.result(127 downto 64);  --! not tested yet
153
    end if;
154
 
155
    if i_nrst = '0' then
156
        v.busy := '0';
157
        v.result := (others => '0');
158
        v.ena := (others => '0');
159
        v.a1 := (others => '0');
160
        v.a2 := (others => '0');
161
        v.rv32 := '0';
162
        v.unsign := '0';
163
        v.high := '0';
164
    end if;
165
 
166
    o_res <= wb_res;
167
    o_valid <= r.ena(3);
168
    o_busy <= r.busy;
169
 
170
    rin <= v;
171
  end process;
172
 
173
  -- registers:
174
  regs : process(i_clk)
175
  begin
176
     if rising_edge(i_clk) then
177
        r <= rin;
178
     end if;
179
  end process;
180
 
181
end;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.