1--------------------------------------------------------------------------------
2-- light52_muldiv.vhdl -- Simple multiplier/divider module.
3--------------------------------------------------------------------------------
4-- The 8051 mul and div instructions are both unsigned and operands are 8 bit.
5--
6-- This module implements the division as a sequential state machine which takes
7-- 8 cycles to complete.
8-- The multiplier can be implemented as sequential or as combinational, in which
9-- case it will use a DSP block in those architectures that support it.
10-- No attempt has been made to make this module generic or reusable.
11--
12-- If you want a combinational multiplier but don't want to waste a DSP block
13-- in this module, you need to modify this file adding whatever synthesis
14-- pragmas your tool of choice needs.
15--
16-- Note that unlike the division state machine, the combinational product logic
17-- is always operating: when SEQUENTIAL_MULTIPLIER=true, prod_out equals
18-- data_a * data_b with a latency of 1 clock cycle, and mul_ready is hardwired
19-- to '1'.
20--
21-- FIXME explain division algorithm.
22--------------------------------------------------------------------------------
23-- GENERICS:
24--
25-- SEQUENTIAL_MULTIPLIER        -- Sequential vs. combinational multiplier.
26--  When true, a sequential implementation will be used for the multiplier,
27--  which will usually save a lot of logic or a dedicated multiplier.
28--  When false, a combinational registered multiplier will be used.
29--
30--------------------------------------------------------------------------------
31-- INTERFACE SIGNALS:
32--
33-- clk :            Clock, active rising edge.
34-- reset :          Synchronous reset. Clears only the control registers not
35--                  visible to the programmer -- not the output registers.
36--
37-- data_a :         Numerator input, should be connected to the ACC register.
38-- data_b :         Denominator input, should be connected to the B register.
39-- start :          Assert for 1 cycle to start the division state machine
40--                  (and the product if SEQUENTIAL_MULTIPLIER=true);
41--
42-- prod_out :       Product output, valid only when mul_ready='1'.
43-- quot_out :       Quotient output, valid only when div_ready='1'.
44-- rem_out :        Remainder output, valid only when div_ready='1'.
45-- div_ov_out :     Division overflow flag, valid only when div_ready='1'.
46-- mul_ov_out :     Product overflow flag, valid only when mul_ready='1'.
47--
48-- mul_ready :      Asserted permanently if SEQUENTIAL_MULTIPLIER=false.
49-- div_ready :      Deasserted the cycle after start is asserted.
50--                  Asserted when the division has completed.
51--
52--------------------------------------------------------------------------------
53-- Copyright (C) 2012 Jose A. Ruiz
54--
55-- This source file may be used and distributed without
56-- restriction provided that this copyright statement is not
57-- removed from the file and that any derivative work contains
58-- the original copyright notice and the associated disclaimer.
59--
60-- This source file is free software; you can redistribute it
61-- and/or modify it under the terms of the GNU Lesser General
62-- Public License as published by the Free Software Foundation;
63-- either version 2.1 of the License, or (at your option) any
64-- later version.
65--
66-- This source is distributed in the hope that it will be
67-- useful, but WITHOUT ANY WARRANTY; without even the implied
68-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
69-- PURPOSE.  See the GNU Lesser General Public License for more
70-- details.
71--
72-- You should have received a copy of the GNU Lesser General
73-- Public License along with this source; if not, download it
74-- from http://www.opencores.org/lgpl.shtml
75--------------------------------------------------------------------------------
76
77library ieee;
78use ieee.std_logic_1164.all;
79use ieee.numeric_std.all;
80
81use work.light52_pkg.all;
82use work.light52_ucode_pkg.all;
83
84entity light52_muldiv is
85    generic (
86        SEQUENTIAL_MULTIPLIER : boolean := false
87    );
88    port(
89        clk :                   in std_logic;
90        reset :                 in std_logic;
91
92        data_a :                in t_byte;
93        data_b :                in t_byte;
94        start :                 in std_logic;
95
96        prod_out :              out t_word;
97        quot_out :              out t_byte;
98        rem_out :               out t_byte;
99        div_ov_out :            out std_logic;
100        mul_ov_out :            out std_logic;
101
102        mul_ready :             out std_logic;
103        div_ready :             out std_logic
104    );
105end entity light52_muldiv;
106
107architecture sequential of light52_muldiv is
108
109signal bit_ctr :            integer range 0 to 8;
110
111signal b_shift_reg :        t_word;
112
113signal den_ge_256 :         std_logic;
114signal num_ge_den :         std_logic;
115signal sub_num :            std_logic;
116
117signal denominator :        t_byte;
118signal rem_reg :            t_byte;
119signal quot_reg :           t_byte;
120signal prod_reg :           t_word;
121signal ready :              std_logic;
122
123signal load_regs :          std_logic;
124
125begin
126
127-- Control logic ---------------------------------------------------------------
128
129control_counter: process(clk)
130begin
131    if clk'event and clk='1' then
132        if reset='1' then
133            bit_ctr <= 8;
134        else
135            if load_regs='1' then
136                bit_ctr <= 0;
137            elsif bit_ctr /= 8 then
138                bit_ctr <= bit_ctr + 1;
139            end if;
140        end if;
141    end if;
142end process control_counter;
143
144-- Internal signal ready is asserted after 8 cycles.
145-- The sequential multiplier will use this signal too, IF it takes 8 cycles.
146
147ready <= '1' when bit_ctr >= 8 else '0';
148
149
150---- Divider logic -------------------------------------------------------------
151
152-- What we do is a simple base-2 'shift-and-subtract' algorithm that takes
153-- 8 cycles to complete. We can get away with this because we deal with unsigned
154-- numbers only.
155
156divider_registers: process(clk)
157begin
158    if clk'event and clk='1' then
159        -- denominator shift register
160        if load_regs='1' then
161            b_shift_reg <= "0" & data_b & "0000000";
162            -- Division overflow can be determined upon loading B reg data.
163            -- OV will be raised only on div-by-zero.
164            if data_b=X"00" then
165                div_ov_out <= '1';
166            else
167                div_ov_out <= '0';
168            end if;
169        else
170            b_shift_reg <= "0" & b_shift_reg(b_shift_reg'high downto 1);
171        end if;
172
173        -- numerator register
174        if load_regs='1' then
175            rem_reg <= data_a;
176        elsif bit_ctr/=8 and sub_num='1' then
177            rem_reg <= rem_reg - denominator;
178        end if;
179
180        --- quotient register
181        if load_regs='1' then
182            quot_reg <= (others => '0');
183        elsif bit_ctr/=8 then
184            quot_reg <= quot_reg(quot_reg'high-1 downto 0) & sub_num;
185        end if;
186
187        load_regs <= start;
188    end if;
189end process divider_registers;
190
191denominator <= b_shift_reg(7 downto 0);
192
193-- The 16-bit comparison between b_shift_reg (denominator) and the zero-extended
194-- rem_reg (numerator) can be simplified by splitting it in 2:
195-- If the shifted denominator high byte is not zero, it is >=256...
196den_ge_256 <= '1' when b_shift_reg(15 downto 8) /= X"00" else '0';
197-- ...otherwise we need to compare the low bytes.
198num_ge_den <= '1' when rem_reg >= denominator else '0';
199sub_num <= '1' when den_ge_256='0' and num_ge_den='1' else '0';
200
201
202quot_out <= quot_reg;
203prod_out <= prod_reg;
204rem_out <= rem_reg;
205
206div_ready <= ready;
207
208---- Multiplier logic ----------------------------------------------------------
209
210---- Combinational multiplier -----------------------------
211multiplier_combinational: if not SEQUENTIAL_MULTIPLIER generate
212
213registered_combinational_multiplier:process(clk)
214begin
215    if clk'event and clk='1' then
216        prod_reg <= data_a * data_b; -- t_byte is unsigned
217    end if;
218end process registered_combinational_multiplier;
219
220-- The multiplier output is valid in the cycle after the operands are loaded,
221-- so by the time MUL is executed it's already done.
222mul_ready <= '1';
223
224mul_ov_out <= '1' when prod_reg(15 downto 8)/=X"00" else '0';
225prod_out <= prod_reg;
226
227end generate multiplier_combinational;
228
229---- Sequential multiplier --------------------------------
230multiplier_sequential: if SEQUENTIAL_MULTIPLIER generate
231
232assert false
233report "Sequential multiplier implementation not done yet."&
234       " Use combinational implementation."
235severity failure;
236
237end generate multiplier_sequential;
238
239end sequential;
240
241
242with Types; use Types;
243with Files_Map;
244
245package p is
246    type int_ptr is access integer;
247    type rec is record
248        value : integer;
249        link  : rec_ptr;
250    end record;
251    type int_vec is array (integer range <>) of integer;
252    type int_vec_ptr is access int_vec;
253    constant def_arr : t_int_array := (0 to 2 => 10);
254end package;
255
256package body p is
257    procedure test is
258        variable v : int_ptr;
259        variable i : integer;
260    begin
261        v := null;
262        deallocate(v);
263        v := new integer;
264        v := new integer'(5);
265        v.all := 5;
266        r.all.value := 1;
267        a := new int_vec(1 to 3);
268        a.all(5) := 2;
269        a(1 to 2) := (1, 2);
270        s := new string'("");
271    end procedure;
272
273    procedure test2(x : inout rec_ptr) is
274    begin
275        x.value := x.value + 1;
276    end procedure;
277
278    procedure test3 is
279        type a;
280        type a is access integer;
281        variable v : a;
282    begin
283    end procedure;
284
285    type int_ptr_array is array (integer range <>) of int_ptr;
286
287    procedure tets4 is
288        type bvp is access bit_vector;
289        variable y : int_ptr(1 to 3) := int_ptr'(null);
290    begin
291    end procedure;
292
293    procedure Restore_Origin (Mark : Instance_Index_Type) is
294    begin
295        for I in reverse Mark + 1 .. Prev_Instance_Table.Last loop
296            declare
297                El : Instance_Entry_Type renames Prev_Instance_Table.Table (I);
298            begin
299                Origin_Table.Table (El.N) := El.Old_Origin;
300            end;
301        end loop;
302        Prev_Instance_Table.Set_Last (Mark);
303    end Restore_Origin;
304
305    --  Instantiate a list.  Simply create a new list and instantiate nodes of
306    --  that list.
307    function Instantiate_Iir_List (L : Iir_List; Is_Ref : Boolean)
308                                    return Iir_List
309    is
310        Res : Iir_List;
311        El : Iir;
312    begin
313        case L is
314            when Null_Iir_List
315            | Iir_List_All =>
316                return L;
317            when others =>
318                It := List_Iterate (L);
319                while Is_Valid (It) loop
320                    El := Get_Element (It);
321                    Append_Element (Res, Instantiate_Iir (El, Is_Ref));
322                end loop;
323                for I in Flist_First .. Flist_Last (L) loop
324                    Set_Nth_Element (Res, I, Instantiate_Iir (El, Is_Ref));
325                end loop;
326                return Res;
327        end case;
328    end Instantiate_Iir_List;
329end package body;
330
331-- Library bar
332context foo.test_context;
333
334entity concat is
335end entity;
336
337entity foo is
338    port (
339        x : in my_int );
340end entity;
341
342architecture t of concat is
343    type int_array is array (integer range <>) of integer;
344begin
345    process
346        variable s : string(1 to 5);
347        variable t : int_array(1 to 2);
348        variable c : bit_vector(1 to 4);
349    begin
350        x := ( 1, 2, 3 );
351        z := x & y;
352        w := 1 & x;
353        s := 'h' & string'("ello");
354        assert "10" = (b(1) & "0");
355        wait;
356    end process;
357
358    function CounterVal(Seconds : integer := 0) return integer is
359        variable TotalSeconds : interger;
360    begin
361        TotalSeconds := Seconds + Minutes * 60;
362        return TotalSeconds * ClockFrequencyHz -1;
363    end function;
364
365    component or_entity is
366    port(
367        input_1: in std_logic;
368        output: out std_logic
369        );
370    end component;
371
372    type enum_type is (a, b, c, ..., z);
373    type int_array is array(3 downto 0) of integer;
374
375    subtype addr_int is integer range 0 to 65535;
376    subtype sub_enum_type is enum_type range a to m;
377end architecture;
378
379architecture a2 of e is
380    function ">"(a, b: my_int) return boolean;
381begin
382    process is
383        variable x, y : my_int;
384    begin
385        assert x > y;
386        assert x < y;                   -- Error
387    end process;
388
389    billowitch_tc586: block is
390        type real_cons_vector  is array (15 downto 0) of real;
391        type real_cons_vector_file is file of real_cons_vector;
392        constant C19 : real_cons_vector := (others => 3.0);
393    begin
394    end block;
395end architecture;
396