Skip to content
Snippets Groups Projects
Commit 612e8fbd authored by Tomasz Wlostowski's avatar Tomasz Wlostowski
Browse files

added common modules

parents
No related merge requests found
*.*\#
\#*
.\#*
*.*~
\ No newline at end of file
----------------------------------------------------------------------
---- ----
---- Ultimate CRC. ----
---- ----
---- This file is part of the ultimate CRC projectt ----
---- http://www.opencores.org/cores/ultimate_crc/ ----
---- ----
---- Description ----
---- CRC generator/checker, parallel implementation. ----
---- ----
---- ----
---- To Do: ----
---- - ----
---- ----
---- Author(s): ----
---- - Geir Drange, gedra@opencores.org ----
---- ----
----------------------------------------------------------------------
---- ----
---- Copyright (C) 2005 Authors and OPENCORES.ORG ----
---- ----
---- 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 General ----
---- Public License as published by the Free Software Foundation; ----
---- either version 2.0 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 General Public License for more details.----
---- ----
---- You should have received a copy of the GNU General ----
---- Public License along with this source; if not, download it ----
---- from http://www.gnu.org/licenses/gpl.txt ----
---- ----
----------------------------------------------------------------------
--
-- CVS Revision History
--
-- $Log: ucrc_par.vhd,v $
-- Revision 1.1 2005/05/09 15:58:38 gedra
-- Parallel implementation
--
-- Modified by T.W. for use in GenCores library
--
library ieee;
use ieee.std_logic_1164.all;
use work.gencores_pkg.all;
entity gc_crc_gen is
generic (
-- polynomial of our CRC generator
g_polynomial : std_logic_vector := x"04C11DB7";
-- initial (after-reset) value of CRC
g_init_value : std_logic_vector := x"ffffffff";
-- residual value of CRC when matched
g_residue : std_logic_vector := x"38fb2284";
-- width of full data input word
g_data_width : integer range 2 to 256 := 16;
-- width of smaller-than-full data input word
g_half_width : integer range 2 to 256 := 8;
-- use synchronous reset when 1
g_sync_reset : integer range 0 to 1 := 0;
-- dual-width mode (g_data_width - wide input word when 1 and g_half_width input
-- word when 0)
g_dual_width : integer range 0 to 1 := 0); -- use sync./async reset
port (
clk_i : in std_logic; -- clock
rst_i : in std_logic; -- reset, active high
en_i : in std_logic; -- enable input, active high
half_i : in std_logic; -- 1: input word has g_half_width bits
-- 0: input word has g_data_width bits
data_i : in std_logic_vector(g_data_width - 1 downto 0); -- data input
match_o : out std_logic; -- CRC match flag: 1 - CRC matches
crc_o : out std_logic_vector(g_polynomial'length - 1 downto 0)); -- CRC
-- output value
end gc_crc_gen;
architecture rtl of gc_crc_gen is
function f_reverse_vector (a : in std_logic_vector)
return std_logic_vector is
variable v_result : std_logic_vector(a'reverse_range);
begin
for i in a'range loop
v_result(i) := a(i);
end loop;
return v_result;
end;
constant msb : integer := g_polynomial'length - 1;
constant init_msb : integer := g_init_value'length - 1;
constant p : std_logic_vector(msb downto 0) := g_polynomial;
constant dw : integer := g_data_width;
constant pw : integer := g_polynomial'length;
type fb_array is array (dw downto 1) of std_logic_vector(msb downto 0);
type dmsb_array is array (dw downto 1) of std_logic_vector(msb downto 1);
signal crca : fb_array;
signal da, ma : dmsb_array;
signal crc, zero : std_logic_vector(msb downto 0);
signal arst, srst : std_logic;
signal a, b : std_logic_vector(g_polynomial'length - 1 downto 0);
signal data_i2 : std_logic_vector(15 downto 0);
signal en_d0 : std_logic;
signal half_d0 : std_logic;
signal crc_tmp : std_logic_vector(31 downto 0);
signal crc_int : std_logic_vector(31 downto 0);
begin
a <= g_init_value;
b <= g_polynomial;
-- Parameter checking: Invalid generics will abort simulation/synthesis
PCHK1 : if msb /= init_msb generate
process
begin
report "g_polynomial and g_init_value vectors must be equal length!"
severity failure;
wait;
end process;
end generate PCHK1;
PCHK2 : if (msb < 3) or (msb > 31) generate
process
begin
report "g_polynomial must be of order 4 to 32!"
severity failure;
wait;
end process;
end generate PCHK2;
PCHK3 : if p(0) /= '1' generate -- LSB must be 1
process
begin
report "g_polynomial must have lsb set to 1!"
severity failure;
wait;
end process;
end generate PCHK3;
data_i2(15 downto 0) <= (data_i(7 downto 0) & data_i(15 downto 8));
-- data_i2(15 downto 0) <= f_reverse_vector(data_i(15 downto 0));
-- Generate vector of each data bit
CA : for i in 1 to dw generate -- data bits
DAT : for j in 1 to msb generate
da(i)(j) <= data_i2(i - 1);
end generate DAT;
end generate CA;
-- Generate vector of each CRC MSB
MS0 : for i in 1 to msb generate
ma(1)(i) <= crc(msb);
end generate MS0;
MSP : for i in 2 to dw generate
MSU : for j in 1 to msb generate
ma(i)(j) <= crca(i - 1)(msb);
end generate MSU;
end generate MSP;
-- Generate feedback matrix
crca(1)(0) <= da(1)(1) xor crc(msb);
crca(1)(msb downto 1) <= crc(msb - 1 downto 0) xor ((da(1) xor ma(1)) and p(msb downto 1));
FB : for i in 2 to dw generate
crca(i)(0) <= da(i)(1) xor crca(i - 1)(msb);
crca(i)(msb downto 1) <= crca(i - 1)(msb - 1 downto 0) xor
((da(i) xor ma(i)) and p(msb downto 1));
end generate FB;
-- Reset signal
SR : if g_sync_reset = 1 generate
srst <= rst_i;
arst <= '0';
end generate SR;
AR : if g_sync_reset = 0 generate
srst <= '0';
arst <= rst_i;
end generate AR;
-- CRC process
crc_tmp <= f_reverse_vector(not crc);
crc_int <= crc_tmp(7 downto 0) & crc_tmp(15 downto 8) & crc_tmp(23 downto 16) & crc_tmp(31 downto 24);
zero <= (others => '0');
crc_o <= crc_int;
CRCP : process (clk_i, arst)
begin
if arst = '1' then -- async. reset
crc <= g_init_value;
half_d0 <= '0';
elsif rising_edge(clk_i) then
if srst = '1' then -- sync. reset
crc <= g_init_value;
elsif en_i = '1' then
if(half_i = '1' and g_dual_width = 1) then
crc <= crca(g_half_width);
else
crc <= crca(g_data_width);
end if;
end if;
end if;
end process;
match_gen : process (clk_i, arst)
begin
if arst = '1' then -- async. reset
match_o <= '0';
en_d0 <= '0';
elsif rising_edge(clk_i) then
if srst = '1' then -- sync. reset
match_o <= '0';
en_d0 <= '0';
else
en_d0 <= en_i;
if(en_d0 = '1') then
if crc_int = g_residue then
match_o <= '1';
else
match_o <= '0';
end if;
end if;
end if;
end if;
end process;
end rtl;
-------------------------------------------------------------------------------
-- Title : Simple delay line generator
-- Project : White Rabbit
-------------------------------------------------------------------------------
-- File : gc_delay_gen.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-02-25
-- Last update: 2011-04-29
-- Platform : FPGA-generic
-- Standard : VHDL '87
------------------------------------------------------------------------------
-- Description: Simple N-bit delay line with programmable delay.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 - 2010 CERN
--
-- 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.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-02-25 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.gencores_pkg.all;
entity 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 gc_delay_gen;
architecture behavioral of gc_delay_gen is
type t_dly_array is array (0 to g_delay_cycles) of std_logic_vector(g_data_width -1 downto 0);
signal dly : t_dly_array;
begin -- behavioral
p_delay_proc : process (clk_i, rst_n_i)
begin -- process delay_proc
if rst_n_i = '0' then -- asynchronous reset (active low)
genrst : for i in 1 to g_delay_cycles loop
dly(i) <= (others => '0');
end loop;
elsif rising_edge(clk_i) then -- rising clock edge
dly(0) <= d_i;
gendly : for i in 0 to g_delay_cycles-1 loop
dly(i+1) <= dly(i);
end loop;
end if;
end process p_delay_proc;
q_o <= dly(g_delay_cycles);
end behavioral;
-------------------------------------------------------------------------------
-- Title : Dual channel PI controller for use in WR PLLs
-- Project : White Rabbit
-------------------------------------------------------------------------------
-- File : gc_dual_pi_controller.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2011-04-29
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Dual, programmable PI controller:
-- - first channel processes the frequency error (gain defined by P_KP/P_KI)
-- - second channel processes the phase error (gain defined by F_KP/F_KI)
-- Mode is selected by the mode_sel_i port and FORCE_F field in PCR register.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 - 2010 CERN
--
-- 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.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-06-14 1.0 twlostow Created
-- 2010-07-16 1.1 twlostow added anti-windup
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity gc_dual_pi_controller is
generic(
g_error_bits : integer := 12;
g_dacval_bits : integer := 16;
g_output_bias : integer := 32767;
g_integrator_fracbits : integer := 16;
g_integrator_overbits : integer := 6;
g_coef_bits : integer := 16
);
port (
clk_sys_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-------------------------------------------------------------------------------
-- Phase & frequency error inputs
-------------------------------------------------------------------------------
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 select input: 1 = frequency mode, 0 = phase mode
mode_sel_i : in std_logic;
-------------------------------------------------------------------------------
-- DAC Output
-------------------------------------------------------------------------------
dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_val_stb_p_o : out std_logic;
-------------------------------------------------------------------------------
-- Wishbone regs
-------------------------------------------------------------------------------
-- PLL enable
pll_pcr_enable_i : in std_logic;
-- PI force freq mode. '1' causes the PI to stay in frequency lock mode all the
-- time.
pll_pcr_force_f_i : in std_logic;
-- Frequency Kp/Ki
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);
-- Phase Kp/Ki
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 gc_dual_pi_controller;
architecture behavioral of gc_dual_pi_controller is
type t_dmpll_state is (PI_CHECK_MODE, PI_WAIT_SAMPLE, PI_MUL_KI, PI_INTEGRATE, PI_MUL_KP, PI_CALC_SUM, PI_SATURATE, PI_ROUND_SUM, PI_DISABLED);
-- integrator size: 12 error bits + 16 coefficient bits + 6 overflow bits
constant c_INTEGRATOR_BITS : integer := g_error_bits + g_integrator_overbits + g_coef_bits;
constant c_ZEROS : unsigned (63 downto 0) := (others => '0');
constant c_ONES : unsigned (63 downto 0) := (others => '1');
-- DAC DC bias (extended by c_INTEGRATOR_FRACBITS). By default it's half of the
-- output voltage scale.
constant c_OUTPUT_BIAS : signed(g_dacval_bits + g_integrator_fracbits-1 downto 0) := to_signed(g_output_bias, g_dacval_bits) & to_signed(0, g_integrator_fracbits);
-- Multiplier size. A = error value, B = coefficient value
constant c_MUL_A_BITS : integer := g_error_bits;
constant c_MUL_B_BITS : integer := g_coef_bits;
-- the integrator
signal i_reg : signed(c_INTEGRATOR_BITS-1 downto 0);
-- multiplier IO
signal mul_A : signed(c_MUL_A_BITS - 1 downto 0);
signal mul_B : signed(c_MUL_B_BITS - 1 downto 0);
signal mul_OUT : signed(c_MUL_A_BITS + c_MUL_B_BITS - 1 downto 0);
signal mul_out_reg : signed(c_MUL_A_BITS + c_MUL_B_BITS - 1 downto 0);
signal pi_state : t_dmpll_state;
-- 1: we are in the frequency mode, 0: we are in phase mode.
signal freq_mode : std_logic;
signal freq_mode_ld : std_logic;
signal output_val : unsigned(c_INTEGRATOR_BITS-1 downto 0);
signal output_val_unrounded : unsigned(g_dacval_bits-1 downto 0);
signal output_val_round_up : std_logic;
signal dac_val_int : std_logic_vector(g_dacval_bits-1 downto 0);
signal output_val_sign : std_logic;
signal output_val_sat_hi : std_logic;
signal output_val_sat_lo : std_logic;
signal s_zero : unsigned(63 downto 0) := (others => '0');
signal anti_windup_hi, anti_windup_lo : std_logic;
begin -- behavioral
-- shared multiplier
multiplier : process (mul_A, mul_B)
begin -- process
mul_OUT <= mul_A * mul_B;
end process;
output_val_unrounded <= output_val(g_integrator_fracbits + g_dacval_bits - 1 downto g_integrator_fracbits);
output_val_round_up <= std_logic(output_val(g_integrator_fracbits - 1));
-- saturation detect logic
output_val_sign <= output_val(output_val'high);
output_val_sat_hi <= '1' when output_val_sign = '0' and (output_val(output_val'high-1 downto g_integrator_fracbits+g_dacval_bits) /= s_zero(output_val'high-1 downto g_integrator_fracbits+g_dacval_bits)) else '0';
output_val_sat_lo <= '1' when output_val_sign = '1' else '0';
main_fsm : process (clk_sys_i, rst_n_sysclk_i)
begin -- process
if rising_edge(clk_sys_i) then
if rst_n_sysclk_i = '0' then
i_reg <= (others => '0');
freq_mode <= '1'; -- start in frequency lock mode
pi_state <= PI_CHECK_MODE;
dac_val_stb_p_o <= '0';
dac_val_int <= std_logic_vector(to_unsigned(g_output_bias, dac_val_int'length));
freq_mode <= '1';
else
case pi_state is
when PI_DISABLED =>
dac_val_stb_p_o <= '0';
if(pll_pcr_enable_i = '1') then
pi_state <= PI_CHECK_MODE;
end if;
when PI_CHECK_MODE =>
if(pll_pcr_force_f_i = '0') then
freq_mode <= mode_sel_i;
else
freq_mode <= '1';
end if;
if(pll_pcr_enable_i = '1') then
dac_val_stb_p_o <= '0';
pi_state <= PI_WAIT_SAMPLE;
else
dac_val_stb_p_o <= '1';
dac_val_int <= std_logic_vector(to_unsigned(g_output_bias, dac_val_int'length));
pi_state <= PI_DISABLED;
freq_mode <= '1';
end if;
-------------------------------------------------------------------------------
-- State: DMPLL wait for input sample. When a frequency error (or phase error)
-- sample arrives from the detector, start the PI update.
-------------------------------------------------------------------------------
when PI_WAIT_SAMPLE =>
-- frequency lock mode, got a frequency sample
if(freq_mode = '1' and freq_err_stb_p_i = '1') then
pi_state <= PI_MUL_KI;
mul_A <= signed(freq_err_i);
mul_B <= signed(pll_fbgr_f_ki_i);
-- phase lock mode, got a phase sample
elsif (freq_mode = '0' and phase_err_stb_p_i = '1') then
pi_state <= PI_MUL_KI;
mul_A <= signed(phase_err_i);
mul_B <= signed(pll_pbgr_p_ki_i);
end if;
-------------------------------------------------------------------------------
-- State: DMPLL multiply by Ki: multiples the phase/freq error by an appropriate
-- Kp/Ki coefficient, set up the multipler for (error * Kp) operation.
-------------------------------------------------------------------------------
when PI_MUL_KI =>
if(freq_mode = '1') then
mul_B <= signed(pll_fbgr_f_kp_i);
else
mul_B <= signed(pll_pbgr_p_kp_i);
end if;
mul_out_reg <= mul_OUT; -- just keep the result
pi_state <= PI_INTEGRATE;
-------------------------------------------------------------------------------
-- State: HPLL integrate: add the (Error * Ki) to the integrator register
-------------------------------------------------------------------------------
when PI_INTEGRATE =>
if(anti_windup_lo = '0' and anti_windup_hi = '0') then
i_reg <= i_reg + mul_out_reg;
end if;
-- the output is saturated to MAX value, but the (Ki*error)
-- is negative, or the output is saturated to MIN value
-- and the (Ki*error) is positive
if (anti_windup_hi = '1' and mul_out_reg(mul_out_reg'high) = '1') or (anti_windup_lo = '1' and mul_out_reg(mul_out_reg'high) = '0') then --
i_reg <= i_reg + mul_out_reg;
end if;
pi_state <= PI_MUL_KP;
-------------------------------------------------------------------------------
-- State: HPLL multiply by Kp: does the same as PI_MUL_KI but for the proportional
-- branch.
-------------------------------------------------------------------------------
when PI_MUL_KP =>
mul_out_reg <= mul_OUT;
pi_state <= PI_CALC_SUM;
when PI_CALC_SUM =>
output_val <= unsigned(c_OUTPUT_BIAS + resize(mul_out_reg, output_val'length) + resize(i_reg, output_val'length));
pi_state <= PI_SATURATE;
when PI_SATURATE =>
if(output_val_sat_hi = '1') then
dac_val_int <= (others => '1');
dac_val_stb_p_o <= '1';
pi_state <= PI_CHECK_MODE;
anti_windup_hi <= '1';
anti_windup_lo <= '0';
elsif (output_val_sat_lo = '1') then
dac_val_int <= (others => '0');
dac_val_stb_p_o <= '1';
pi_state <= PI_CHECK_MODE;
anti_windup_hi <= '0';
anti_windup_lo <= '1';
else
anti_windup_lo <= '0';
anti_windup_hi <= '0';
pi_state <= PI_ROUND_SUM;
end if;
-------------------------------------------------------------------------------
-- State: HPLL round sum: calculates the final DAC value, with 0.5LSB rounding.
-- Also checks for the frequency lock.
-------------------------------------------------------------------------------
when PI_ROUND_SUM =>
dac_val_stb_p_o <= '1';
-- +-0.5 rounding of the output value
if(output_val_round_up = '1') then
dac_val_int <= std_logic_vector(output_val_unrounded + 1);
else
dac_val_int <= std_logic_vector(output_val_unrounded);
end if;
pi_state <= PI_CHECK_MODE;
when others => null;
end case;
end if;
end if;
end process;
dac_val_o <= dac_val_int;
end behavioral;
-------------------------------------------------------------------------------
-- Title : Pulse width extender
-- Project : General Cores library
-------------------------------------------------------------------------------
-- File : gc_extend_pulse.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2009-09-01
-- Last update: 2011-04-29
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Description:
-- Synchronous pulse extender. Generates a pulse of programmable width upon
-- detection of a rising edge in the input.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009-2011 CERN
--
-- 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.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2009-09-01 0.9 twlostow Created
-- 2011-04-18 1.0 twlostow Added comments & header
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.NUMERIC_STD.all;
library work;
use work.gencores_pkg.all;
entity gc_extend_pulse is
generic (
-- output pulse width in clk_i cycles
g_width : natural := 1000
);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- input pulse (synchronou to clk_i)
pulse_i : in std_logic;
-- extended output pulse
extended_o : out std_logic);
end gc_extend_pulse;
architecture rtl of gc_extend_pulse is
signal cntr : unsigned(31 downto 0);
begin -- rtl
extend : process (clk_i, rst_n_i)
begin -- process extend
if rst_n_i = '0' then -- asynchronous reset (active low)
extended_o <= '0';
cntr <= (others => '0');
elsif clk_i'event and clk_i = '1' then -- rising clock edge
if(pulse_i = '1') then
extended_o <= '1';
cntr <= to_unsigned(g_width, cntr'length);
elsif cntr /= to_unsigned(0, cntr'length) then
cntr <= cntr - 1;
else
extended_o <= '0';
end if;
end if;
end process extend;
end rtl;
-------------------------------------------------------------------------------
-- Title : Moving average filter
-- Project : General Cores library
-------------------------------------------------------------------------------
-- File : gc_moving_average.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2009-09-01
-- Last update: 2011-04-29
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Description:
-- Simple averaging filter.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009-2011 CERN
--
-- 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.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2009-09-01 0.9 twlostow Created
-- 2011-04-18 1.0 twlostow Added comments & header
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.NUMERIC_STD.all;
library work;
use work.gencores_pkg.all;
entity gc_moving_average is
generic (
-- input/output data width
g_data_width : natural := 24;
-- averaging window, expressed as 2 ** g_avg_log2
g_avg_log2 : natural range 1 to 8 := 4
);
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
din_i : in std_logic_vector(g_data_width-1 downto 0);
din_stb_i : in std_logic;
dout_o : out std_logic_vector(g_data_width-1 downto 0);
dout_stb_o : out std_logic
);
end gc_moving_average;
architecture rtl of gc_moving_average is
component generic_ssram_dp_rw_rw
generic (
g_width : integer;
g_addr_bits : integer;
g_size : integer);
port (
clk_i : in std_logic;
wr_en_a_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_bits-1 downto 0);
data_a_i : in std_logic_vector(g_width-1 downto 0);
q_a_o : out std_logic_vector(g_width-1 downto 0);
wr_en_b_i : in std_logic;
addr_b_i : in std_logic_vector(g_addr_bits-1 downto 0);
data_b_i : in std_logic_vector(g_width-1 downto 0);
q_b_o : out std_logic_vector(g_width-1 downto 0));
end component;
constant avg_steps : natural := 2**g_avg_log2;
signal read_cntr, write_cntr : unsigned(g_avg_log2-1 downto 0);
signal mem_dout : std_logic_vector(g_data_width-1 downto 0);
signal ready : std_logic;
signal acc : signed(g_data_width+g_avg_log2 downto 0);
signal stb_d0, stb_d1, stb_d2, stb_d3 : std_logic;
signal s_dummy : std_logic_vector(g_data_width-1 downto 0);
begin -- rtl
delay_buf : generic_ssram_dp_rw_rw
generic map (
g_width => g_data_width,
g_addr_bits => g_avg_log2,
g_size => 2**g_avg_log2
)
port map (
clk_i => clk_i,
wr_en_a_i => '0',
addr_a_i => std_logic_vector(read_cntr),
data_a_i => s_dummy,
q_a_o => mem_dout,
wr_en_b_i => din_stb_i,
addr_b_i => std_logic_vector(write_cntr),
data_b_i => din_i,
q_b_o => open);
--delay_buf : generic_ssram_dualport_singleclock
-- generic map (
-- g_width => g_data_width,
-- g_addr_bits => g_avg_log2,
-- g_size => 2**g_avg_log2)
-- port map (
-- data_i => din_i,
-- rd_addr_i => std_logic_vector(read_cntr),
-- clk_i => clk_i,
-- wr_addr_i => std_logic_vector(write_cntr),
-- wr_en_i => din_stb_i,
-- q_o => mem_dout);
avg : process (clk_i, rst_n_i)
begin -- process avg
if clk_i'event and clk_i = '1' then -- rising clock edge
if(rst_n_i = '0') then
read_cntr <= to_unsigned(1, read_cntr'length);
write_cntr <= to_unsigned(avg_steps, write_cntr'length);
ready <= '0';
stb_d0 <= '0';
stb_d1 <= '0';
stb_d2 <= '0';
stb_d3 <= '0';
acc <= (others => '0');
else
if(read_cntr = to_unsigned(avg_steps, read_cntr'length)) then
ready <= '1';
end if;
if(din_stb_i = '1') then
acc <= acc + signed(din_i);
write_cntr <= write_cntr + 1;
else
if stb_d3 = '1' then
read_cntr <= read_cntr + 1;
if(ready = '1') then
acc <= acc - signed(mem_dout);
dout_o <= std_logic_vector(acc (g_avg_log2 + g_data_width - 1 downto g_avg_log2));
end if;
end if;
end if;
dout_stb_o <= stb_d3 and ready;
stb_d0 <= din_stb_i;
stb_d1 <= stb_d0;
stb_d2 <= stb_d1;
stb_d3 <= stb_d2;
end if;
end if;
end process avg;
end rtl;
-------------------------------------------------------------------------------
-- Title : Serial DAC interface
-- Project : White Rabbit
-------------------------------------------------------------------------------
-- File : gc_serial_dac.vhd
-- Author : Pablo Alvarez Sanchez
-- Company : CERN BE-Co-HT
-- Created : 2010-02-25
-- Last update: 2011-04-29
-- Platform : FPGA-generic
-- Standard : VHDL '87
-------------------------------------------------------------------------------
-- Description: The DAC unit provides an interface to a 16 bit serial Digital
-- to Analogue converter (MAX5441, AD5662, SPI/QSPI/MICROWIRE compatible)
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 - 2010 CERN
--
-- 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.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2009-01-24 1.0 paas Created
-- 2010-02-25 1.1 twlostow Modified for rev 1.1 switch
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity gc_serial_dac is
generic (
-- number of DAC data word bits (LSBs)
g_num_data_bits : integer := 16;
-- number of padding MSBs, sent as zeros
g_num_extra_bits : integer := 8;
-- number of chip select inputs
g_num_cs_select : integer := 2;
-- serial clock polarity: 0 - data is outputted on rising-,
-- 1 - on falling edge of SCLK
g_sclk_polarity : integer := 1
);
port (
-- clock & reset
clk_i : in std_logic;
rst_n_i : in std_logic;
-- value to be written to the DAC
value_i : in std_logic_vector(g_num_data_bits-1 downto 0);
-- chip select vector. Setting bits to 1 enables writing to the corresponding
-- DAC
cs_sel_i : in std_logic_vector(g_num_cs_select-1 downto 0);
-- when 1, value_i is valid.
load_i : in std_logic;
-- SCLK divider: 000 = clk_i/8 ... 111 = clk_i/1024
sclk_divsel_i : in std_logic_vector(2 downto 0);
-- DAC I/F
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;
-- when 1, the SPI interface is busy sending data to the DAC.
busy_o : out std_logic
);
end gc_serial_dac;
architecture syn of gc_serial_dac is
signal divider : unsigned(11 downto 0);
signal dataSh : std_logic_vector(g_num_data_bits + g_num_extra_bits-1 downto 0);
signal bitCounter : std_logic_vector(g_num_data_bits + g_num_extra_bits+1 downto 0);
signal endSendingData : std_logic;
signal sendingData : std_logic;
signal iDacClk : std_logic;
signal iValidValue : std_logic;
signal divider_muxed : std_logic;
signal cs_sel_reg : std_logic_vector(g_num_cs_select-1 downto 0);
begin
select_divider : process (divider, sclk_divsel_i)
begin -- process
case sclk_divsel_i is
when "000" => divider_muxed <= divider(1); -- sclk = clk_i/8
when "001" => divider_muxed <= divider(2); -- sclk = clk_i/16
when "010" => divider_muxed <= divider(3); -- sclk = clk_i/32
when "011" => divider_muxed <= divider(4); -- sclk = clk_i/64
when "100" => divider_muxed <= divider(5); -- sclk = clk_i/128
when "101" => divider_muxed <= divider(6); -- sclk = clk_i/256
when "110" => divider_muxed <= divider(7); -- sclk = clk_i/512
when "111" => divider_muxed <= divider(8); -- sclk = clk_i/1024
when others => null;
end case;
end process;
iValidValue <= load_i;
process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
sendingData <= '0';
else
if iValidValue = '1' and sendingData = '0' then
sendingData <= '1';
elsif endSendingData = '1' then
sendingData <= '0';
end if;
end if;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
if iValidValue = '1' then
divider <= (others => '0');
elsif sendingData = '1' then
if(divider_muxed = '1') then
divider <= (others => '0');
else
divider <= divider + 1;
end if;
elsif endSendingData = '1' then
divider <= (others => '0');
end if;
end if;
end process;
process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
iDacClk <= '1'; -- 0
else
if iValidValue = '1' then
iDacClk <= '1'; -- 0
elsif divider_muxed = '1' then
iDacClk <= not(iDacClk);
elsif endSendingData = '1' then
iDacClk <= '1'; -- 0
end if;
end if;
end if;
end process;
process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
dataSh <= (others => '0');
else
if iValidValue = '1' and sendingData = '0' then
cs_sel_reg <= cs_sel_i;
dataSh(g_num_data_bits-1 downto 0) <= value_i;
dataSh(dataSh'left downto g_num_data_bits) <= (others => '0');
elsif sendingData = '1' and divider_muxed = '1' and iDacClk = '0' then
dataSh(0) <= dataSh(dataSh'left);
dataSh(dataSh'left downto 1) <= dataSh(dataSh'left - 1 downto 0);
end if;
end if;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
if iValidValue = '1' and sendingData = '0' then
bitCounter(0) <= '1';
bitCounter(bitCounter'left downto 1) <= (others => '0');
elsif sendingData = '1' and to_integer(divider) = 0 and iDacClk = '1' then
bitCounter(0) <= '0';
bitCounter(bitCounter'left downto 1) <= bitCounter(bitCounter'left - 1 downto 0);
end if;
end if;
end process;
endSendingData <= bitCounter(bitCounter'left);
busy_o <= SendingData;
dac_sdata_o <= dataSh(dataSh'left);
gen_cs_out : for i in 0 to g_num_cs_select-1 generate
dac_cs_n_o(i) <= not(sendingData) or (not cs_sel_reg(i));
end generate gen_cs_out;
p_drive_sclk : process(iDacClk)
begin
if(g_sclk_polarity = 0) then
dac_sclk_o <= iDacClk;
else
dac_sclk_o <= not iDacClk;
end if;
end process;
end syn;
-------------------------------------------------------------------------------
-- Title : Synchronizer chain
-- Project : White Rabbit
-------------------------------------------------------------------------------
-- File : gc_sync_ffs.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2011-04-29
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Synchronizer chain and edge detector.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 - 2010 CERN
--
-- 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.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-06-14 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity gc_sync_ffs is
generic(
g_sync_edge : string := "positive"
);
port(
clk_i : in std_logic; -- clock from the destination clock domain
rst_n_i : in std_logic; -- reset
data_i : in std_logic; -- async input
synced_o : out std_logic; -- synchronized output
npulse_o : out std_logic; -- negative edge detect output (single-clock
-- pulse)
ppulse_o : out std_logic -- positive edge detect output (single-clock
-- pulse)
);
end gc_sync_ffs;
architecture behavioral of gc_sync_ffs is
signal sync0, sync1, sync2 : std_logic;
begin
sync_posedge : if (g_sync_edge = "positive") generate
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
sync0 <= '0';
sync1 <= '0';
sync2 <= '0';
synced_o <= '0';
npulse_o <= '0';
ppulse_o <= '0';
elsif rising_edge(clk_i) then
sync0 <= data_i;
sync1 <= sync0;
sync2 <= sync1;
synced_o <= sync1;
npulse_o <= sync2 and not sync1;
ppulse_o <= not sync2 and sync1;
end if;
end process;
end generate sync_posedge;
sync_negedge : if(g_sync_edge = "negative") generate
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
sync0 <= '0';
sync1 <= '0';
sync2 <= '0';
synced_o <= '0';
npulse_o <= '0';
ppulse_o <= '0';
elsif falling_edge(clk_i) then
sync0 <= data_i;
sync1 <= sync0;
sync2 <= sync1;
synced_o <= sync1;
npulse_o <= sync2 and not sync1;
ppulse_o <= not sync2 and sync1;
end if;
end process;
end generate sync_negedge;
end behavioral;
-------------------------------------------------------------------------------
-- Title : General cores VHDL package
-- Project : General Cores library
-------------------------------------------------------------------------------
-- File : gencores_pkg.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2009-09-01
-- Last update: 2011-04-29
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Description:
-- Package incorporating simple VHDL modules, which are used
-- in the WR and other OHWR projects.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009-2011 CERN
--
-- 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.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2009-09-01 0.9 twlostow Created
-- 2011-04-18 1.0 twlostow Added comments & header
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package gencores_pkg is
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_crc_gen
generic (
g_polynomial : std_logic_vector;
g_init_value : std_logic_vector;
g_residue : std_logic_vector;
g_data_width : integer range 2 to 256;
g_half_width : integer range 2 to 256;
g_sync_reset : integer range 0 to 1;
g_dual_width : integer range 0 to 1);
port (
clk_i : in std_logic;
rst_i : in std_logic;
en_i : in std_logic;
half_i : in std_logic;
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;
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);
din_stb_i : in std_logic;
dout_o : out std_logic_vector(g_data_width-1 downto 0);
dout_stb_o : out std_logic);
end component;
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;
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;
component gc_sync_ffs
generic (
g_sync_edge : string);
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;
end package;
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment