-------------------------------------------------------------------------------- -- CERN BE-CO-HT -- General Cores Library -- https://www.ohwr.org/projects/general-cores -------------------------------------------------------------------------------- -- -- unit name: gencores_pkg -- -- description: Package incorporating simple VHDL modules and functions, -- which are used in OHWR projects. -- -------------------------------------------------------------------------------- -- Copyright CERN 2009-2018 -------------------------------------------------------------------------------- -- Copyright and related rights are licensed under the Solderpad Hardware -- License, Version 2.0 (the "License"); you may not use this file except -- in compliance with the License. You may obtain a copy of the License at -- http://solderpad.org/licenses/SHL-2.0. -- Unless required by applicable law or agreed to in writing, software, -- hardware and materials distributed under this License is distributed on an -- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -- or implied. See the License for the specific language governing permissions -- and limitations under the License. -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.genram_pkg.all; package gencores_pkg is --============================================================================ -- Component instantiations --============================================================================ ------------------------------------------------------------------------------ -- Pulse extender ------------------------------------------------------------------------------ component gc_extend_pulse generic ( g_width : natural); port ( clk_i : in std_logic; rst_n_i : in std_logic; pulse_i : in std_logic; extended_o : out std_logic); end component; component gc_dyn_extend_pulse is generic ( g_len_width : natural := 10); port ( clk_i : in std_logic; rst_n_i : in std_logic; pulse_i : in std_logic; len_i : in std_logic_vector(g_len_width-1 downto 0); extended_o : out std_logic := '0'); end component; ------------------------------------------------------------------------------ -- CRC generator ------------------------------------------------------------------------------ component gc_crc_gen generic ( g_polynomial : std_logic_vector := x"04C11DB7"; g_init_value : std_logic_vector := x"ffffffff"; g_residue : std_logic_vector := x"38fb2284"; g_data_width : integer range 2 to 256 := 16; g_half_width : integer range 2 to 256 := 8; g_sync_reset : integer range 0 to 1 := 1; g_dual_width : integer range 0 to 1 := 0; g_registered_match_output : boolean := true; g_registered_crc_output : boolean := true); port ( clk_i : in std_logic; rst_i : in std_logic; en_i : in std_logic; half_i : in std_logic; restart_i : in std_logic := '0'; data_i : in std_logic_vector(g_data_width - 1 downto 0); match_o : out std_logic; crc_o : out std_logic_vector(g_polynomial'length - 1 downto 0)); end component; ------------------------------------------------------------------------------ -- Moving average ------------------------------------------------------------------------------ component gc_moving_average generic ( g_data_width : natural; g_avg_log2 : natural range 1 to 8); port ( rst_n_i : in std_logic; clk_i : in std_logic; din_i : in std_logic_vector(g_data_width-1 downto 0); dout_o : out std_logic_vector(g_data_width+g_avg_log2-1 downto 0); dout_stb_o : out std_logic); end component; ------------------------------------------------------------------------------ -- Delay line ------------------------------------------------------------------------------ component gc_delay_line generic ( g_delay : integer; g_width : integer); port ( clk_i : in std_logic; rst_n_i : in std_logic; d_i : in std_logic_vector(g_width -1 downto 0); q_o : out std_logic_vector(g_width -1 downto 0); ready_o : out std_logic); end component; ------------------------------------------------------------------------------ -- PI controller ------------------------------------------------------------------------------ component gc_dual_pi_controller generic ( g_error_bits : integer; g_dacval_bits : integer; g_output_bias : integer; g_integrator_fracbits : integer; g_integrator_overbits : integer; g_coef_bits : integer); port ( clk_sys_i : in std_logic; rst_n_sysclk_i : in std_logic; phase_err_i : in std_logic_vector(g_error_bits-1 downto 0); phase_err_stb_p_i : in std_logic; freq_err_i : in std_logic_vector(g_error_bits-1 downto 0); freq_err_stb_p_i : in std_logic; mode_sel_i : in std_logic; dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0); dac_val_stb_p_o : out std_logic; pll_pcr_enable_i : in std_logic; pll_pcr_force_f_i : in std_logic; pll_fbgr_f_kp_i : in std_logic_vector(g_coef_bits-1 downto 0); pll_fbgr_f_ki_i : in std_logic_vector(g_coef_bits-1 downto 0); pll_pbgr_p_kp_i : in std_logic_vector(g_coef_bits-1 downto 0); pll_pbgr_p_ki_i : in std_logic_vector(g_coef_bits-1 downto 0)); end component; ------------------------------------------------------------------------------ -- Serial 16-bit DAC interface (SPI/QSPI/MICROWIRE compatible) ------------------------------------------------------------------------------ component gc_serial_dac generic ( g_num_data_bits : integer; g_num_extra_bits : integer; g_num_cs_select : integer; g_sclk_polarity : integer); port ( clk_i : in std_logic; rst_n_i : in std_logic; value_i : in std_logic_vector(g_num_data_bits-1 downto 0); cs_sel_i : in std_logic_vector(g_num_cs_select-1 downto 0); load_i : in std_logic; sclk_divsel_i : in std_logic_vector(2 downto 0); dac_cs_n_o : out std_logic_vector(g_num_cs_select-1 downto 0); dac_sclk_o : out std_logic; dac_sdata_o : out std_logic; busy_o : out std_logic); end component; ------------------------------------------------------------------------------ -- Comparator ------------------------------------------------------------------------------ component gc_comparator is generic ( g_IN_WIDTH : natural := 32); port ( clk_i : in std_logic; rst_n_i : in std_logic := '1'; pol_inv_i : in std_logic := '0'; enable_i : in std_logic := '1'; inp_i : in std_logic_vector(g_IN_WIDTH-1 downto 0); inn_i : in std_logic_vector(g_IN_WIDTH-1 downto 0); hys_i : in std_logic_vector(g_IN_WIDTH-1 downto 0) := (others => '0'); out_o : out std_logic; out_p_o : out std_logic); end component gc_comparator; ------------------------------------------------------------------------------ -- Synchronisation FF chain ------------------------------------------------------------------------------ component gc_sync_ffs generic ( g_sync_edge : string := "positive"); port ( clk_i : in std_logic; rst_n_i : in std_logic; data_i : in std_logic; synced_o : out std_logic; npulse_o : out std_logic; ppulse_o : out std_logic); end component; ------------------------------------------------------------------------------ -- Pulse synchroniser ------------------------------------------------------------------------------ component gc_pulse_synchronizer port ( clk_in_i : in std_logic; clk_out_i : in std_logic; rst_n_i : in std_logic; d_ready_o : out std_logic; d_p_i : in std_logic; q_p_o : out std_logic); end component; ------------------------------------------------------------------------------ -- Pulse synchroniser (with reset from both clock domains) ------------------------------------------------------------------------------ component gc_pulse_synchronizer2 is port ( clk_in_i : in std_logic; rst_in_n_i : in std_logic; clk_out_i : in std_logic; rst_out_n_i : in std_logic; d_ready_o : out std_logic; d_ack_p_o : out std_logic; d_p_i : in std_logic; q_p_o : out std_logic); end component; ------------------------------------------------------------------------------ -- Word synchroniser ------------------------------------------------------------------------------ component gc_sync_word_wr is generic ( g_AUTO_WR : boolean := FALSE; g_WIDTH : positive := 8); port ( clk_in_i : in std_logic; rst_in_n_i : in std_logic; clk_out_i : in std_logic; rst_out_n_i : in std_logic; data_i : in std_logic_vector (g_WIDTH - 1 downto 0); wr_i : in std_logic := '0'; busy_o : out std_logic; ack_o : out std_logic; data_o : out std_logic_vector (g_WIDTH - 1 downto 0); wr_o : out std_logic); end component gc_sync_word_wr; ------------------------------------------------------------------------------ -- Frequency meters ------------------------------------------------------------------------------ component gc_frequency_meter generic ( g_WITH_INTERNAL_TIMEBASE : boolean := TRUE; g_CLK_SYS_FREQ : integer; g_SYNC_OUT : boolean := FALSE; g_COUNTER_BITS : integer); port ( clk_sys_i : in std_logic; clk_in_i : in std_logic; rst_n_i : in std_logic; pps_p1_i : in std_logic; freq_o : out std_logic_vector(g_COUNTER_BITS-1 downto 0); freq_valid_o : out std_logic); end component; component gc_multichannel_frequency_meter is generic ( g_with_internal_timebase : boolean; g_clk_sys_freq : integer; g_counter_bits : integer; g_channels : integer); port ( clk_sys_i : in std_logic; clk_in_i : in std_logic_vector(g_channels -1 downto 0); rst_n_i : in std_logic; pps_p1_i : in std_logic; channel_sel_i : in std_logic_vector(3 downto 0); freq_o : out std_logic_vector(g_counter_bits-1 downto 0); freq_valid_o : out std_logic); end component gc_multichannel_frequency_meter; ------------------------------------------------------------------------------ -- Time-division multiplexer with round robin arbitration ------------------------------------------------------------------------------ component gc_arbitrated_mux generic ( g_num_inputs : integer; g_width : integer); port ( clk_i : in std_logic; rst_n_i : in std_logic; d_i : in std_logic_vector(g_num_inputs * g_width-1 downto 0); d_valid_i : in std_logic_vector(g_num_inputs-1 downto 0); d_req_o : out std_logic_vector(g_num_inputs-1 downto 0); q_o : out std_logic_vector(g_width-1 downto 0); q_valid_o : out std_logic; q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0)); end component; ------------------------------------------------------------------------------ -- Power-On reset generator ------------------------------------------------------------------------------ component gc_reset is generic( g_clocks : natural := 1; g_logdelay : natural := 10; g_syncdepth : natural := 3); port( free_clk_i : in std_logic; locked_i : in std_logic := '1'; -- All the PLL locked signals ANDed together clks_i : in std_logic_vector(g_clocks-1 downto 0); rstn_o : out std_logic_vector(g_clocks-1 downto 0)); end component; ------------------------------------------------------------------------------ -- Multiple clock domain reset generator and synchronizer with -- Asynchronous Assert and Syncrhonous Deassert (AASD) ------------------------------------------------------------------------------ component gc_reset_multi_aasd is generic ( g_CLOCKS : natural; g_RST_LEN : natural); port ( arst_i : in std_logic := '1'; clks_i : in std_logic_vector(g_CLOCKS-1 downto 0); rst_n_o : out std_logic_vector(g_CLOCKS-1 downto 0)); end component gc_reset_multi_aasd; ------------------------------------------------------------------------------ -- Power-On reset generator of synchronous single reset from multiple -- asynchronous input reset signals ------------------------------------------------------------------------------ component gc_single_reset_gen is generic( g_out_reg_depth : natural :=2; g_rst_in_num : natural :=2); port ( clk_i : in std_logic; rst_signals_n_a_i : in std_logic_vector(g_rst_in_num-1 downto 0); rst_n_o : out std_logic ); end component; ------------------------------------------------------------------------------ -- Round robin arbiter ------------------------------------------------------------------------------ component gc_rr_arbiter generic ( g_size : integer); port ( clk_i : in std_logic; rst_n_i : in std_logic; req_i : in std_logic_vector(g_size-1 downto 0); grant_o : out std_logic_vector(g_size-1 downto 0); grant_comb_o : out std_logic_vector(g_size-1 downto 0)); end component; ------------------------------------------------------------------------------ -- Pack or unpack words ------------------------------------------------------------------------------ component gc_word_packer generic ( g_input_width : integer; g_output_width : integer); port ( clk_i : in std_logic; rst_n_i : in std_logic; d_i : in std_logic_vector(g_input_width-1 downto 0); d_valid_i : in std_logic; d_req_o : out std_logic; flush_i : in std_logic := '0'; q_o : out std_logic_vector(g_output_width-1 downto 0); q_valid_o : out std_logic; q_req_i : in std_logic); end component; ------------------------------------------------------------------------------ -- Adder ------------------------------------------------------------------------------ component gc_big_adder is generic( g_data_bits : natural := 64; g_parts : natural := 4); port( clk_i : in std_logic; stall_i : in std_logic := '0'; a_i : in std_logic_vector(g_data_bits-1 downto 0); b_i : in std_logic_vector(g_data_bits-1 downto 0); c_i : in std_logic := '0'; c1_o : out std_logic; x2_o : out std_logic_vector(g_data_bits-1 downto 0); c2_o : out std_logic); end component; ------------------------------------------------------------------------------ -- I2C slave ------------------------------------------------------------------------------ constant c_i2cs_idle : std_logic_vector(1 downto 0) := "00"; constant c_i2cs_addr_good : std_logic_vector(1 downto 0) := "01"; constant c_i2cs_rd_done : std_logic_vector(1 downto 0) := "10"; constant c_i2cs_wr_done : std_logic_vector(1 downto 0) := "11"; component gc_i2c_slave is generic ( -- Length of glitch filter -- 0 - SCL and SDA lines are passed only through synchronizer -- 1 - one clk_i glitches filtered -- 2 - two clk_i glitches filtered g_gf_len : natural := 0; -- Automatically ACK reception upon address match. g_auto_addr_ack : boolean := FALSE ); port ( -- Clock, reset ports clk_i : in std_logic; rst_n_i : in std_logic; -- I2C lines scl_i : in std_logic; scl_o : out std_logic; scl_en_o : out std_logic; sda_i : in std_logic; sda_o : out std_logic; sda_en_o : out std_logic; -- Slave address i2c_addr_i : in std_logic_vector(6 downto 0); -- ACK input, should be set after done_p_o = '1' -- (note that the bit is reversed wrt I2C ACK bit) -- '1' - ACK -- '0' - NACK ack_i : in std_logic; -- Byte to send, should be loaded while done_p_o = '1' tx_byte_i : in std_logic_vector(7 downto 0); -- Received byte, valid after done_p_o = '1' rx_byte_o : out std_logic_vector(7 downto 0); -- Pulse outputs signaling various I2C actions -- Start and stop conditions i2c_sta_p_o : out std_logic; i2c_sto_p_o : out std_logic; -- Received address corresponds addr_i addr_good_p_o : out std_logic; -- Read and write done r_done_p_o : out std_logic; w_done_p_o : out std_logic; -- I2C bus operation, set after address detection -- '0' - write -- '1' - read op_o : out std_logic ); end component gc_i2c_slave; ------------------------------------------------------------------------------ -- Glitch filter ------------------------------------------------------------------------------ component gc_glitch_filt is generic ( -- Length of glitch filter: -- g_len = 1 => data width should be > 1 clk_i cycle -- g_len = 2 => data width should be > 2 clk_i cycle -- etc. g_len : natural := 4 ); port ( clk_i : in std_logic; rst_n_i : in std_logic; -- Data input dat_i : in std_logic; -- Data output -- latency: g_len+1 clk_i cycles dat_o : out std_logic ); end component gc_glitch_filt; ------------------------------------------------------------------------------ -- Dynamic glitch filter ------------------------------------------------------------------------------ component gc_dyn_glitch_filt is generic ( -- Number of bit of the glitch filter length input g_len_width : natural := 8 ); port ( clk_i : in std_logic; rst_n_i : in std_logic; -- Glitch filter length len_i : in std_logic_vector(g_len_width-1 downto 0); -- Data input dat_i : in std_logic; -- Data output -- latency: g_len+1 clk_i cycles dat_o : out std_logic ); end component gc_dyn_glitch_filt; ------------------------------------------------------------------------------ -- FSM Watchdog Timer ------------------------------------------------------------------------------ component gc_fsm_watchdog is generic ( -- Maximum value of watchdog timer in clk_i cycles g_wdt_max : positive := 65535 ); port ( -- Clock and active-low reset line clk_i : in std_logic; rst_n_i : in std_logic; -- Active-high watchdog timer reset line, synchronous to clk_i wdt_rst_i : in std_logic; -- Active-high reset output, synchronous to clk_i fsm_rst_o : out std_logic ); end component gc_fsm_watchdog; ------------------------------------------------------------------------------ -- Bicolor LED controller ------------------------------------------------------------------------------ constant c_led_red : std_logic_vector(1 downto 0) := "10"; constant c_led_green : std_logic_vector(1 downto 0) := "01"; constant c_led_red_green : std_logic_vector(1 downto 0) := "11"; constant c_led_off : std_logic_vector(1 downto 0) := "00"; component gc_bicolor_led_ctrl generic( g_nb_column : natural := 4; g_nb_line : natural := 2; g_clk_freq : natural := 125000000; -- in Hz g_refresh_rate : natural := 250 -- in Hz ); port ( rst_n_i : in std_logic; clk_i : in std_logic; led_intensity_i : in std_logic_vector(6 downto 0); led_state_i : in std_logic_vector((g_nb_line * g_nb_column * 2) - 1 downto 0); column_o : out std_logic_vector(g_nb_column - 1 downto 0); line_o : out std_logic_vector(g_nb_line - 1 downto 0); line_oen_o : out std_logic_vector(g_nb_line - 1 downto 0) ); end component; component gc_sync_register is generic ( g_width : integer); port ( clk_i : in std_logic; rst_n_a_i : in std_logic; d_i : in std_logic_vector(g_width-1 downto 0); q_o : out std_logic_vector(g_width-1 downto 0)); end component gc_sync_register; component gc_async_signals_input_stage is generic ( g_signal_num : integer; g_extended_pulse_width : integer; g_dglitch_filter_len : integer); port ( clk_i : in std_logic; rst_n_i : in std_logic; signals_a_i : in std_logic_vector(g_signal_num-1 downto 0); config_active_i : in std_logic_vector(g_signal_num-1 downto 0); signals_o : out std_logic_vector(g_signal_num-1 downto 0); signals_p1_o : out std_logic_vector(g_signal_num-1 downto 0); signals_pN_o : out std_logic_vector(g_signal_num-1 downto 0)); end component; ------------------------------------------------------------------------------ -- Priority encoder ------------------------------------------------------------------------------ component gc_prio_encoder is generic ( g_width : integer); port ( d_i : in std_logic_vector(g_width-1 downto 0); therm_o : out std_logic_vector(g_width-1 downto 0)); end component; ------------------------------------------------------------------------------ -- Delay generator ------------------------------------------------------------------------------ component gc_delay_gen is generic( g_delay_cycles : in natural; g_data_width : in natural); port(clk_i : in std_logic; rst_n_i : in std_logic; d_i : in std_logic_vector(g_data_width - 1 downto 0); q_o : out std_logic_vector(g_data_width - 1 downto 0)); end component; ------------------------------------------------------------------------------ -- One-wire interface to DS1820 and DS1822 ------------------------------------------------------------------------------ -- Deprecated! Kept only for backward compatibility. -- Please use gc_ds1282x_readout instead component gc_ds182x_interface is generic ( freq : integer := 40; g_USE_INTERNAL_PPS : boolean := false); port ( clk_i : in std_logic; rst_n_i : in std_logic; pps_p_i : in std_logic; onewire_b : inout std_logic; id_o : out std_logic_vector(63 downto 0); temper_o : out std_logic_vector(15 downto 0); id_read_o : out std_logic; id_ok_o : out std_logic); end component gc_ds182x_interface; component gc_ds182x_readout is generic ( g_CLOCK_FREQ_KHZ : integer := 40000; g_USE_INTERNAL_PPS : boolean := false); port ( clk_i : in std_logic; rst_n_i : in std_logic; pps_p_i : in std_logic; onewire_b : inout std_logic; id_o : out std_logic_vector(63 downto 0); temper_o : out std_logic_vector(15 downto 0); id_read_o : out std_logic; id_ok_o : out std_logic); end component gc_ds182x_readout; component gc_dec_8b10b is port ( clk_i : in std_logic; rst_n_i : in std_logic; in_10b_i : in std_logic_vector(9 downto 0); ctrl_o : out std_logic; code_err_o : out std_logic; rdisp_err_o : out std_logic; out_8b_o : out std_logic_vector(7 downto 0)); end component gc_dec_8b10b; ------------------------------------------------------------------------------ -- SFP I2C Adapter ------------------------------------------------------------------------------ component gc_sfp_i2c_adapter is port ( clk_i : in std_logic; rst_n_i : in std_logic; scl_i : in std_logic; sda_i : in std_logic; sda_en_o : out std_logic; sfp_det_valid_i : in std_logic; sfp_data_i : in std_logic_vector (127 downto 0)); end component gc_sfp_i2c_adapter; ------------------------------------------------------------------------------ -- Asynchronous counter inc/dec pulses ------------------------------------------------------------------------------ component gc_async_counter_diff is generic ( g_bits : integer := 8; g_output_clock : string := "inc"); port ( rst_n_i : in std_logic; clk_inc_i : in std_logic; clk_dec_i : in std_logic; inc_i : in std_logic; dec_i : in std_logic; counter_o : out std_logic_vector(g_bits downto 0)); end component gc_async_counter_diff; --============================================================================ -- Procedures and functions --============================================================================ procedure f_rr_arbitrate ( signal req : in std_logic_vector; signal pre_grant : in std_logic_vector; signal grant : out std_logic_vector); function f_onehot_decode(x : std_logic_vector; size : integer) return std_logic_vector; function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector; function f_gray_encode(x : std_logic_vector) return std_logic_vector; function f_gray_decode(x : std_logic_vector; step : natural) return std_logic_vector; function log2_ceil(N : natural) return positive; function f_bool2int (b : boolean) return natural; function f_int2bool (n : natural) return boolean; -- Convert a boolean to std_logic ('1' for True, '0' for False). function f_to_std_logic(b : boolean) return std_logic; -- Reduce-OR an std_logic_vector to std_logic function f_reduce_or (x : std_logic_vector) return std_logic; -- Character/String to std_logic_vector function f_to_std_logic_vector (c : character) return std_logic_vector; function f_to_std_logic_vector (s : string) return std_logic_vector; -- Functions for short-hand if assignments function f_pick (cond : boolean; if_1 : std_logic; if_0 : std_logic) return std_logic; function f_pick (cond : boolean; if_1 : std_logic_vector; if_0 : std_logic_vector) return std_logic_vector; function f_pick (cond : std_logic; if_1 : std_logic; if_0 : std_logic) return std_logic; function f_pick (cond : std_logic; if_1 : std_logic_vector; if_0 : std_logic_vector) return std_logic_vector; -- Functions to convert characters and strings to upper/lower case function to_upper(c : character) return character; function to_lower(c : character) return character; function to_upper(s : string) return string; function to_lower(s : string) return string; end package; package body gencores_pkg is ------------------------------------------------------------------------------ -- Simple round-robin arbiter: -- req = requests (1 = pending request), -- pre_grant = previous grant vector (1 cycle delay) -- grant = new grant vector ------------------------------------------------------------------------------ procedure f_rr_arbitrate ( signal req : in std_logic_vector; signal pre_grant : in std_logic_vector; signal grant : out std_logic_vector)is variable reqs : std_logic_vector(req'length - 1 downto 0); variable gnts : std_logic_vector(req'length - 1 downto 0); variable gnt : std_logic_vector(req'length - 1 downto 0); variable gntM : std_logic_vector(req'length - 1 downto 0); variable zeros : std_logic_vector(req'length - 1 downto 0); begin zeros := (others => '0'); -- bit twiddling magic : gnt := req and std_logic_vector(unsigned(not req) + 1); reqs := req and not (std_logic_vector(unsigned(pre_grant) - 1) or pre_grant); gnts := reqs and std_logic_vector(unsigned(not reqs)+1); if(reqs = zeros) then gntM := gnt; else gntM := gnts; end if; if((req and pre_grant) = zeros) then grant <= gntM; else grant <= pre_grant; end if; end f_rr_arbitrate; function f_onehot_decode(x : std_logic_vector; size : integer) return std_logic_vector is begin for j in 0 to x'left loop if x(j) /= '0' then return std_logic_vector(to_unsigned(j, size)); end if; end loop; -- i return std_logic_vector(to_unsigned(0, size)); end f_onehot_decode; ------------------------------------------------------------------------------ -- Carry ripple ------------------------------------------------------------------------------ function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector is constant len : natural := a'length; variable aw, bw, rw : std_logic_vector(len+1 downto 0); variable x : std_logic_vector(len downto 0); begin aw := "0" & a & c; bw := "0" & b & c; rw := std_logic_vector(unsigned(aw) + unsigned(bw)); x := rw(len+1 downto 1); return x; end f_big_ripple; ------------------------------------------------------------------------------ -- Gray encoder ------------------------------------------------------------------------------ function f_gray_encode(x : std_logic_vector) return std_logic_vector is variable o : std_logic_vector(x'length downto 0); begin o := (x & '0') xor ('0' & x); return o(x'length downto 1); end f_gray_encode; ------------------------------------------------------------------------------ -- Gray decoder -- call with step=1 ------------------------------------------------------------------------------ function f_gray_decode(x : std_logic_vector; step : natural) return std_logic_vector is constant len : natural := x'length; alias y : std_logic_vector(len-1 downto 0) is x; variable z : std_logic_vector(len-1 downto 0) := (others => '0'); begin if step >= len then return y; else z(len-step-1 downto 0) := y(len-1 downto step); return f_gray_decode(y xor z, step+step); end if; end f_gray_decode; ------------------------------------------------------------------------------ -- Returns log of 2 of a natural number ------------------------------------------------------------------------------ function log2_ceil(N : natural) return positive is begin if N <= 2 then return 1; elsif N mod 2 = 0 then return 1 + log2_ceil(N/2); else return 1 + log2_ceil((N+1)/2); end if; end; ------------------------------------------------------------------------------ -- Converts a boolean to natural integer (false -> 0, true -> 1) ------------------------------------------------------------------------------ function f_bool2int (b : boolean) return natural is begin if b then return 1; else return 0; end if; end; ------------------------------------------------------------------------------ -- Converts a natural integer to boolean (0 -> false, any positive -> true) ------------------------------------------------------------------------------ function f_int2bool (n : natural) return boolean is begin if n = 0 then return false; else return true; end if; end; function f_to_std_logic(b : boolean) return std_logic is begin if b then return '1'; else return '0'; end if; end f_to_std_logic; ------------------------------------------------------------------------------ -- Perform reduction-OR on an std_logic_vector, return std_logic ------------------------------------------------------------------------------ function f_reduce_or (x : std_logic_vector) return std_logic is variable rv : std_logic; begin rv := '0'; for n in x'range loop rv := rv or x(n); end loop; return rv; end f_reduce_or; ------------------------------------------------------------------------------ -- Convert a character to an 8-bit std_logic_vector ------------------------------------------------------------------------------ function f_to_std_logic_vector (c : character) return std_logic_vector is variable rv : std_logic_vector(7 downto 0); begin rv := std_logic_vector(to_unsigned(character'pos(c), 8)); return rv; end function f_to_std_logic_vector; ------------------------------------------------------------------------------ -- Convert a string of characters to a std_logic_vector of bytes. -- NOTE: right-most character is stored at rv(7 downto 0). ------------------------------------------------------------------------------ function f_to_std_logic_vector (s : string) return std_logic_vector is variable rv : std_logic_vector(s'length*8-1 downto 0); variable k : natural; begin for i in s'range loop -- calculate offset within rv k := 8*(4-i); -- do the character conversion and write to proper offset rv(k+7 downto k) := f_to_std_logic_vector(s(i)); end loop; return rv; end function f_to_std_logic_vector; ------------------------------------------------------------------------------ -- Functions for short-hand if assignments ------------------------------------------------------------------------------ function f_pick (cond : std_logic; if_1 : std_logic; if_0 : std_logic) return std_logic is begin if cond = '1' then return if_1; else return if_0; end if; end function f_pick; function f_pick (cond : std_logic; if_1 : std_logic_vector; if_0 : std_logic_vector) return std_logic_vector is begin if cond = '1' then return if_1; else return if_0; end if; end function f_pick; function f_pick (cond : boolean; if_1 : std_logic; if_0 : std_logic) return std_logic is begin return f_pick (f_to_std_logic(cond), if_1, if_0); end function f_pick; function f_pick (cond : boolean; if_1 : std_logic_vector; if_0 : std_logic_vector) return std_logic_vector is begin return f_pick (f_to_std_logic(cond), if_1, if_0); end function f_pick; ------------------------------------------------------------------------------ -- Functions to convert characters and strings to upper/lower case ------------------------------------------------------------------------------ function to_upper(c : character) return character is variable i : integer; begin i := character'pos(c); if (i > 96 and i < 123) then i := i - 32; end if; return character'val(i); end function to_upper; function to_lower(c : character) return character is variable i : integer; begin i := character'pos(c); if (i > 64 and i < 91) then i := i + 32; end if; return character'val(i); end function to_lower; function to_upper(s : string) return string is variable uppercase : string (s'range); begin for i in s'range loop uppercase(i) := to_upper(s(i)); end loop; return uppercase; end to_upper; function to_lower(s : string) return string is variable lowercase : string (s'range); begin for i in s'range loop lowercase(i) := to_lower(s(i)); end loop; return lowercase; end to_lower; end gencores_pkg;