-------------------------------------------------------------------------------- -- light52_muldiv.vhdl -- Simple multiplier/divider module. -------------------------------------------------------------------------------- -- The 8051 mul and div instructions are both unsigned and operands are 8 bit. -- -- This module implements the division as a sequential state machine which takes -- 8 cycles to complete. -- The multiplier can be implemented as sequential or as combinational, in which -- case it will use a DSP block in those architectures that support it. -- No attempt has been made to make this module generic or reusable. -- -- If you want a combinational multiplier but don't want to waste a DSP block -- in this module, you need to modify this file adding whatever synthesis -- pragmas your tool of choice needs. -- -- Note that unlike the division state machine, the combinational product logic -- is always operating: when SEQUENTIAL_MULTIPLIER=true, prod_out equals -- data_a * data_b with a latency of 1 clock cycle, and mul_ready is hardwired -- to '1'. -- -- FIXME explain division algorithm. -------------------------------------------------------------------------------- -- GENERICS: -- -- SEQUENTIAL_MULTIPLIER -- Sequential vs. combinational multiplier. -- When true, a sequential implementation will be used for the multiplier, -- which will usually save a lot of logic or a dedicated multiplier. -- When false, a combinational registered multiplier will be used. -- -------------------------------------------------------------------------------- -- INTERFACE SIGNALS: -- -- clk : Clock, active rising edge. -- reset : Synchronous reset. Clears only the control registers not -- visible to the programmer -- not the output registers. -- -- data_a : Numerator input, should be connected to the ACC register. -- data_b : Denominator input, should be connected to the B register. -- start : Assert for 1 cycle to start the division state machine -- (and the product if SEQUENTIAL_MULTIPLIER=true); -- -- prod_out : Product output, valid only when mul_ready='1'. -- quot_out : Quotient output, valid only when div_ready='1'. -- rem_out : Remainder output, valid only when div_ready='1'. -- div_ov_out : Division overflow flag, valid only when div_ready='1'. -- mul_ov_out : Product overflow flag, valid only when mul_ready='1'. -- -- mul_ready : Asserted permanently if SEQUENTIAL_MULTIPLIER=false. -- div_ready : Deasserted the cycle after start is asserted. -- Asserted when the division has completed. -- -------------------------------------------------------------------------------- -- Copyright (C) 2012 Jose A. Ruiz -- -- This source file may be used and distributed without -- restriction provided that this copyright statement is not -- removed from the file and that any derivative work contains -- the original copyright notice and the associated disclaimer. -- -- This source file is free software; you can redistribute it -- and/or modify it under the terms of the GNU Lesser General -- Public License as published by the Free Software Foundation; -- either version 2.1 of the License, or (at your option) any -- later version. -- -- This source is distributed in the hope that it will be -- useful, but WITHOUT ANY WARRANTY; without even the implied -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -- PURPOSE. See the GNU Lesser General Public License for more -- details. -- -- You should have received a copy of the GNU Lesser General -- Public License along with this source; if not, download it -- from http://www.opencores.org/lgpl.shtml -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.light52_pkg.all; use work.light52_ucode_pkg.all; entity light52_muldiv is generic ( SEQUENTIAL_MULTIPLIER : boolean := false ); port( clk : in std_logic; reset : in std_logic; data_a : in t_byte; data_b : in t_byte; start : in std_logic; prod_out : out t_word; quot_out : out t_byte; rem_out : out t_byte; div_ov_out : out std_logic; mul_ov_out : out std_logic; mul_ready : out std_logic; div_ready : out std_logic ); end entity light52_muldiv; architecture sequential of light52_muldiv is signal bit_ctr : integer range 0 to 8; signal b_shift_reg : t_word; signal den_ge_256 : std_logic; signal num_ge_den : std_logic; signal sub_num : std_logic; signal denominator : t_byte; signal rem_reg : t_byte; signal quot_reg : t_byte; signal prod_reg : t_word; signal ready : std_logic; signal load_regs : std_logic; begin -- Control logic --------------------------------------------------------------- control_counter: process(clk) alias sig is <>; begin if clk'event and clk='1' then if reset='1' then bit_ctr <= 8; else if load_regs='1' then bit_ctr <= 0; elsif bit_ctr /= 8 then bit_ctr <= bit_ctr + 1; end if; end if; end if; end process control_counter; -- Internal signal ready is asserted after 8 cycles. -- The sequential multiplier will use this signal too, IF it takes 8 cycles. ready <= '1' when bit_ctr >= 8 else '0'; ---- Divider logic ------------------------------------------------------------- -- What we do is a simple base-2 'shift-and-subtract' algorithm that takes -- 8 cycles to complete. We can get away with this because we deal with unsigned -- numbers only. divider_registers: process(clk) begin if clk'event and clk='1' then -- denominator shift register if load_regs='1' then b_shift_reg <= "0" & data_b & "0000000"; -- Division overflow can be determined upon loading B reg data. -- OV will be raised only on div-by-zero. if data_b=X"00" then div_ov_out <= '1'; else div_ov_out <= '0'; end if; else b_shift_reg <= "0" & b_shift_reg(b_shift_reg'high downto 1); end if; -- numerator register if load_regs='1' then rem_reg <= data_a; elsif bit_ctr/=8 and sub_num='1' then rem_reg <= rem_reg - denominator; end if; --- quotient register if load_regs='1' then quot_reg <= (others => '0'); elsif bit_ctr/=8 then quot_reg <= quot_reg(quot_reg'high-1 downto 0) & sub_num; end if; load_regs <= start; end if; end process divider_registers; denominator <= b_shift_reg(7 downto 0); -- The 16-bit comparison between b_shift_reg (denominator) and the zero-extended -- rem_reg (numerator) can be simplified by splitting it in 2: -- If the shifted denominator high byte is not zero, it is >=256... den_ge_256 <= '1' when b_shift_reg(15 downto 8) /= X"00" else '0'; -- ...otherwise we need to compare the low bytes. num_ge_den <= '1' when rem_reg >= denominator else '0'; sub_num <= '1' when den_ge_256='0' and num_ge_den='1' else '0'; quot_out <= quot_reg; prod_out <= prod_reg; rem_out <= rem_reg; div_ready <= ready; ---- Multiplier logic ---------------------------------------------------------- ---- Combinational multiplier ----------------------------- multiplier_combinational: if not SEQUENTIAL_MULTIPLIER generate registered_combinational_multiplier:process(clk) begin if clk'event and clk='1' then prod_reg <= data_a * data_b; -- t_byte is unsigned end if; end process registered_combinational_multiplier; -- The multiplier output is valid in the cycle after the operands are loaded, -- so by the time MUL is executed it's already done. mul_ready <= '1'; mul_ov_out <= '1' when prod_reg(15 downto 8)/=X"00" else '0'; prod_out <= prod_reg; end generate multiplier_combinational; ---- Sequential multiplier -------------------------------- multiplier_sequential: if SEQUENTIAL_MULTIPLIER generate assert false report "Sequential multiplier implementation not done yet."& " Use combinational implementation." severity failure; end generate multiplier_sequential; end sequential; with Types; use Types; with Files_Map; package fixed_pkg is new IEEE.fixed_generic_pkg generic map ( fixed_overflow_style => IEEE.fixed_float_types.fixed_saturate, fixed_guard_bits => 3, no_warning => false ); package p is type int_ptr is access integer; type rec is record data : std_logic_vector(31 downto 0); ack : std_logic; value : integer; link : rec_ptr; end record; type int_vec is array (integer range <>) of integer; type int_vec_ptr is access int_vec; procedure UNIFORM(variable SEED1, SEED2 : inout POSITIVE; variable X : out REAL); constant def_arr : t_int_array := (0 to 2 => 10); -- type range type newInt is range -4 to 3; type CAPACITY is range 0 to 1E5 units pF; nF = 1000 pF; end units; -- type protected type prot is protected function meth(a : int) return bit; end protected; -- type protected body type prot is protected body variable var : positive; constant const : boolean; function meth(a : int) return bit is begin end function; end protected body; function \?=\ (L, R : BOOLEAN) return BOOLEAN; end package; package body p is function \?=\ (L, R : BOOLEAN) return BOOLEAN is begin if not (format(format'left) = '%') then report "to_string: Illegal format string """ & format & '"' severity error; return ""; end if; return L = R; end function \?=\; procedure test is variable v : int_ptr; variable i : integer; begin v := null; deallocate(v); v := new integer; v := new integer'(5); v.all := 5; r.all.value := 1; a := new int_vec(1 to 3); a.all(5) := 2; a(1 to 2) := (1, 2); s := new string'(""); end procedure; procedure test2(x : inout rec_ptr) is begin x.value := x.value + 1; end procedure; procedure test3 is type a; type a is access integer; variable v : a; begin end procedure; type int_ptr_array is array (integer range <>) of int_ptr; procedure tets4 is type bvp is access bit_vector; variable y : int_ptr(1 to 3) := int_ptr'(null); begin end procedure; procedure Restore_Origin (Mark : Instance_Index_Type) is begin for I in reverse Mark + 1 .. Prev_Instance_Table.Last loop declare El : Instance_Entry_Type renames Prev_Instance_Table.Table (I); begin Origin_Table.Table (El.N) := El.Old_Origin; end; end loop; Prev_Instance_Table.Set_Last (Mark); end Restore_Origin; -- Instantiate a list. Simply create a new list and instantiate nodes of -- that list. function Instantiate_Iir_List (L : Iir_List; Is_Ref : Boolean) return Iir_List is Res : Iir_List; El : Iir; begin case to_integer(unsigned(CTRL_REF(x*4+3 downto x*4))) is when Null_Iir_List | Iir_List_All => return L; when others => It := List_Iterate (L); while Is_Valid (It) loop El := Get_Element (It); Append_Element (Res, Instantiate_Iir (El, Is_Ref)); end loop; for I in Flist_First .. Flist_Last (L) loop Set_Nth_Element (Res, I, Instantiate_Iir (El, Is_Ref)); end loop; return Res; end case; end Instantiate_Iir_List; end package body; -- Library bar context foo.test_context; context foo is context foo.test_context; end context foo; entity concat is end entity; entity foo is port ( x : in my_int ); end entity; architecture t of concat is type int_array is array (integer range <>) of integer; type small is range 1 to 3; component or_entity is port( input_1: in std_logic; output: out std_logic ); end component; begin process variable s : string(1 to 5); variable t : int_array(1 to 2); variable c : bit_vector(1 to 4); begin x := ( 1, 2, 3 ); z := x & y; w := 1 & x; s := 'h' & string'("ello"); assert "10" = (b(1) & "0"); wait; end process; function CounterVal(Seconds : integer := 0) return integer is variable TotalSeconds : interger; begin TotalSeconds := Seconds + Minutes * 60; return TotalSeconds * ClockFrequencyHz -1; end function; type enum_type is (a, b, c, ..., z); type int_array is array(3 downto 0) of integer; subtype addr_int is integer range 0 to 65535; subtype sub_enum_type is enum_type range a to m; inst1: entity work.counter1(rtl) generic map (BITS1 => 8) port map ( clk1 => Clock, DATA_OUT => pwm_data_o(3 downto 5), COMP_IN(1 downto 0) => compensate_i, WRITE_IN => (others => '0') ); inst2: component counter2 generic map (BITS1 => 8) port map (clk1 => Clock); inst3: configuration counter3 generic map (BITS1 => 8) port map (clk1 => Clock); THE_PWM_GEN : pwm_generator generic map( dsfds => ds ) port map( CLK => clk_i, DATA_IN => pwm_data_i, DATA_OUT => pwm_data_o(3 downto 5), COMP_IN(1 downto 0) => compensate_i, WRITE_IN => (others => '0') ); end architecture; architecture a2 of e is function ">"(a, b: my_int) return boolean; begin process is variable x, y : my_int; begin assert x > y; assert x < y; -- Error end process; billowitch_tc586: block is type real_cons_vector is array (15 downto 0) of real; type real_cons_vector_file is file of real_cons_vector; constant C19 : real_cons_vector := (others => 3.0); begin end block; end architecture; architecture arch of ent is begin LL: if test=10 generate begin end; elsif test=5 generate begin end; end generate; LL: if l1: SPEED = "fast" generate elsif test=5 generate end generate; end architecture arch; architecture thing_arch of designthing is component pwm_generator port( CLK : in std_logic; DATA_IN : in std_logic_vector(15 downto 0); ); end component pwm_generator; attribute NOM_FREQ : string; attribute NOM_FREQ of clk_source : label is "133.00"; signal clk_i : std_logic; begin gen_no_comp: if TEMP = 0 generate compensate_i <= (others => '0'); end generate; gen_no_comp: for i in 0 to TEMP generate compensate_i <= (others => '0') after 10 ns; compensate_i <= (others => '0') ; end generate; --------------------------------------------------------------------------- -- LED blinking when activity on inputs --------------------------------------------------------------------------- PROC_TIMER : process begin wait until rising_edge(clk_i); timer <= timer + 1; wait for 10 ns; leds <= (last_inp xor inp_status(3 downto 0)) or leds or last_leds; if timer = 0 then leds <= not inp_status(3 downto 0); last_leds <= x"0"; elsif gf then fdsa <= '1'; end if; xz: for x in 0 to 7 loop dsadf; end loop; case c is when XXX => c <= 1; d <= 21321; when YYYY => c <= 2; end case; end process; generate_with_begin: if TEMP = 0 generate signal : test : std_logic; begin compensate_i <= (others => '0'); if timer = 0 then leds <= not inp_status(3 downto 0); last_leds <= x"0"; elsif gf then fdsa <= '1'; end if; end generate generate_with_begin; PROC_TIMER : process variable x : std_logic; begin x := '0'; end process PROC_TIMER; end architecture thing_arc; --this is not correct (wrong name) 1+1 2ns 1_2_3 12_3 1.2 1.2_3 1_3.2_3 12_3e+1 12_3e-1 12_3e1_1 12_3.4e1_1 12_3e1_ 12_3e 2#1_2_3#E+8 2#1_2.3#E+8 2#1_f2.3# 3.14159_26536 -- A literal of type universal_real. 5280 -- A literal of type universal_integer. 10.7 ns -- A literal of a physical type. O"4777" -- A bit string literal. "54LS281" -- A string literal. "" -- A string literal representing a null array. B"1111_1111_1111" -- Equivalent to the string literal "111111111111". X"FFF" -- Equivalent to B"1111_1111_1111". O"777" -- Equivalent to B"111_111_111". X"777" -- Equivalent to B"0111_0111_0111". B"XXXX_01LH" -- Equivalent to the string literal "XXXX01LH" UO"27" -- Equivalent to B"010_111" UO"2C" -- Equivalent to B"011_CCC" SX"3W" -- Equivalent to B"0011_WWWW" D"35" -- Equivalent to B"100011" 12UB"X1" -- Equivalent to B"0000_0000_00X1" 12SB"X1" -- Equivalent to B"XXXX_XXXX_XXX1" 12UX"F-" -- Equivalent to B"0000_1111_----" 12SX"F-" -- Equivalent to B"1111_1111_----" 12D"13" -- Equivalent to B"0000_0000_1101" 12UX"000WWW" -- Equivalent to B"WWWW_WWWW_WWWW" 12SX"FFFC00" -- Equivalent to B"1100_0000_0000" 12SX"XXXX00" -- Equivalent to B"XXXX_0000_0000" 8D"511" -- Error 8UO"477" -- Error 8SX"0FF" -- Error 8SX"FXX" -- Error