aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/issue1655/absenc_pkg.vhdl
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/gna/issue1655/absenc_pkg.vhdl')
-rw-r--r--testsuite/gna/issue1655/absenc_pkg.vhdl776
1 files changed, 776 insertions, 0 deletions
diff --git a/testsuite/gna/issue1655/absenc_pkg.vhdl b/testsuite/gna/issue1655/absenc_pkg.vhdl
new file mode 100644
index 000000000..e5a439746
--- /dev/null
+++ b/testsuite/gna/issue1655/absenc_pkg.vhdl
@@ -0,0 +1,776 @@
+--
+-- package for absolute encoder slave and master
+-- supported formats: ENDAT, BISS, SSI
+--
+-- there is a bunch of code here. a typical user is
+-- interested in the following 2 components:
+-- absenc_pkg.slave
+-- absenc_pkg.master
+--
+-- refer to sim/common/main.vhd for usage.
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use ieee.math_real.all;
+
+
+package absenc_pkg is
+
+
+--
+-- encoder type identifiers
+
+constant ENC_TYPE_ENDAT: integer := 0;
+constant ENC_TYPE_BISS: integer := 1;
+constant ENC_TYPE_SSI: integer := 2;
+constant ENC_TYPE_COUNT: integer := 3;
+
+
+--
+-- encoder positions in mux
+
+function get_enc_mux_endat
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return integer;
+
+
+function get_enc_mux_biss
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return integer;
+
+
+function get_enc_mux_ssi
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return integer;
+
+
+--
+-- count enabled encoders
+
+function get_enc_mux_count
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return integer;
+
+
+--
+-- mux position to encoder type
+
+type enc_type_array_t is array(ENC_TYPE_COUNT - 1 downto 0) of integer;
+
+function gen_enc_mux_to_type
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return enc_type_array_t;
+
+
+--
+-- compute integer length
+
+function integer_length
+(
+ i: integer
+)
+return integer;
+
+
+--
+-- microsecond to counter clocked by freq
+
+function us_to_count
+(
+ us: integer;
+ freq: integer;
+ len: integer
+)
+return integer;
+
+
+--
+-- default timeout us
+-- conditions the lowset and highest ma_clk
+
+constant MAX_TM_US: integer := 100;
+constant MASTER_DEFAULT_TM_US: integer := 60;
+constant SLAVE_DEFAULT_TM_US: integer := 20;
+
+
+--
+-- default ssi related values
+-- no spy mode
+-- binary coding
+-- no special terminating pattern
+-- no delay
+
+constant SSI_DEFAULT_FLAGS: std_logic_vector := "00000";
+constant SSI_DEFAULT_DELAY_FDIV: unsigned(0 downto 0) := to_unsigned(0, 1);
+
+
+--
+-- encoder slave interface
+
+component slave
+generic
+(
+ -- local clock frequency
+ CLK_FREQ: integer;
+
+ -- enable a specific implementation, or all by default
+ -- disabling unneeded implementations optimizes resources
+ ENABLE_ENDAT: boolean := TRUE;
+ ENABLE_BISS: boolean := TRUE;
+ ENABLE_SSI: boolean := TRUE
+);
+port
+(
+ -- local clock and reset
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- clock from master
+ ma_clk: in std_logic;
+
+ -- master in, slave out
+ miso: out std_logic;
+ mosi: in std_logic;
+
+ -- gate to drive output (1 to drive it). used in PEPU
+ -- first versions, set to open if not used.
+ gate: out std_logic;
+
+ -- data sent to master. typically the position
+ -- important: use the smallest possible width, as
+ -- this is used to derive other resource sizes
+ data: in std_logic_vector;
+
+ -- data length. typically the encoder resolution
+ -- important: use the smallest possible width, as
+ -- this is used to derive other resource sizes
+ len: in unsigned;
+
+ -- the selected encoder type
+ enc_type: in integer;
+
+ -- ssi specific flags
+ -- set to work.absenc_pkg.SSI_DEFAULT_FLAGS if unused
+ -- ssi_flags<0>: unused
+ -- ssi_flags<1>: 0 or 1 for binary or gray data coding
+ -- ssi_flags<2>: '.S' terminating pattern
+ -- ssi_flags<3>: 'ES' terminating pattern
+ -- ssi_flags<4>: 'OS' terminating pattern
+ ssi_flags: in std_logic_vector
+);
+end component;
+
+
+component slave_endat
+generic
+(
+ CLK_FREQ: integer
+);
+port
+(
+ -- local clock
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- master clock edges
+ ma_clk_redge: in std_logic;
+ ma_clk_fedge: in std_logic;
+
+ -- the edge we are interested in
+ ma_clk_edge: out std_logic;
+
+ -- master in, slave out
+ miso: out std_logic;
+ mosi: in std_logic;
+
+ -- gate to drive output (1 to drive it)
+ gate: out std_logic;
+
+ -- actual data to send and length
+ data: in std_logic_vector;
+ len: in unsigned;
+
+ -- timeout counter
+ tm_match: in std_logic;
+ tm_top: out unsigned;
+
+ -- general purpose counter
+ count_top: out unsigned;
+ count_match: in std_logic;
+ count_rst: out std_logic;
+
+ -- piso register
+ piso_rval: in std_logic_vector;
+ piso_lval: in std_logic_vector;
+ piso_ini: out std_logic_vector;
+ piso_load: out std_logic
+);
+end component;
+
+
+component slave_biss
+generic
+(
+ CLK_FREQ: integer
+);
+port
+(
+ -- local clock
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- master clock edges
+ ma_clk_redge: in std_logic;
+ ma_clk_fedge: in std_logic;
+
+ -- the edge we are interested in
+ ma_clk_edge: out std_logic;
+
+ -- master in, slave out
+ miso: out std_logic;
+ mosi: in std_logic;
+
+ -- gate to drive output (1 to drive it)
+ gate: out std_logic;
+
+ -- actual data to send and length
+ data: in std_logic_vector;
+ len: in unsigned;
+
+ -- timeout counter
+ tm_match: in std_logic;
+ tm_top: out unsigned;
+
+ -- general purpose counter
+ count_top: out unsigned;
+ count_match: in std_logic;
+ count_rst: out std_logic;
+
+ -- piso register
+ piso_rval: in std_logic_vector;
+ piso_lval: in std_logic_vector;
+ piso_ini: out std_logic_vector;
+ piso_load: out std_logic
+);
+end component;
+
+
+component slave_ssi
+generic
+(
+ CLK_FREQ: integer
+);
+port
+(
+ -- local clock
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- master clock edges
+ ma_clk_redge: in std_logic;
+ ma_clk_fedge: in std_logic;
+
+ -- the edge we are interested in
+ ma_clk_edge: out std_logic;
+
+ -- master in, slave out
+ miso: out std_logic;
+ mosi: in std_logic;
+
+ -- gate to drive output (1 to drive it)
+ gate: out std_logic;
+
+ -- actual data to send and length
+ data: in std_logic_vector;
+ len: in unsigned;
+
+ -- timeout counter
+ tm_match: in std_logic;
+ tm_top: out unsigned;
+
+ -- general purpose counter
+ count_top: out unsigned;
+ count_match: in std_logic;
+ count_rst: out std_logic;
+
+ -- piso register
+ piso_rval: in std_logic_vector;
+ piso_lval: in std_logic_vector;
+ piso_ini: out std_logic_vector;
+ piso_load: out std_logic;
+
+ -- refer to absenc_pkg.slave for comments
+ ssi_flags: in std_logic_vector
+);
+end component;
+
+
+--
+-- encoder master interface
+
+component master
+generic
+(
+ -- local clock frequency
+ CLK_FREQ: integer;
+
+ -- enable a specific implementation, or all by default
+ -- disabling unneeded implementations optimizes resources
+ ENABLE_ENDAT: boolean := TRUE;
+ ENABLE_BISS: boolean := FALSE;
+ ENABLE_SSI: boolean := FALSE
+);
+port
+(
+ -- local clock and reset
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- ma_clk is the clock signal generated by the master
+ -- to the slave. its frequency is CLK_FREQ / ma_fdiv
+ ma_fdiv: in unsigned;
+ ma_clk: out std_logic;
+
+ -- master out, slave in
+ mosi: out std_logic;
+ miso: in std_logic;
+
+ -- gate to drive output (1 to drive it). used in PEPU
+ -- first versions, set to open if not used.
+ gate: out std_logic;
+
+ -- data received from slave. typically the position
+ -- important: use the smallest possible width, as
+ -- this is used to derive other resource sizes
+ data: out std_logic_vector;
+
+ -- data length. typically the encoder resolution
+ -- important: use the smallest possible width, as
+ -- this is used to derive other resource sizes
+ len: in unsigned;
+
+ -- the selected encoder type
+ enc_type: in integer;
+
+ -- ssi specific flags
+ -- set to work.absenc_pkg.SSI_DEFAULT_FLAGS if unused
+ -- ssi_flags<0>: ssi spy mode (ie. master without clock)
+ -- ssi_flags<1>: 0 or 1 for binary or gray data coding
+ -- ssi_flags<2>: '.S' terminating pattern
+ -- ssi_flags<3>: 'ES' terminating pattern
+ -- ssi_flags<4>: 'OS' terminating pattern
+ ssi_flags: in std_logic_vector;
+
+ -- ssi frame delay. divides CLK_FREQ
+ -- set to work.absenc_pkg.SSI_DEFAULT_DELAY_FDIV if unsued
+ ssi_delay_fdiv: in unsigned
+);
+end component;
+
+
+component master_endat
+generic
+(
+ CLK_FREQ: integer
+);
+port
+(
+ -- local clock
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- master clock edges
+ ma_clk_fedge: in std_logic;
+ ma_clk_redge: in std_logic;
+
+ -- the edge we are interested in
+ ma_clk_edge: out std_logic;
+
+ -- master clock reset
+ -- if ma_clk_rst_en, use ma_clk_rst_level
+ ma_clk_rst_en: out std_logic;
+ ma_clk_rst_val: out std_logic;
+
+ -- master out, slave in
+ mosi: out std_logic;
+ miso: in std_logic;
+
+ -- gate to drive output (1 to drive it)
+ gate: out std_logic;
+
+ -- desired data length
+ len: in unsigned;
+
+ -- timeout counter
+ tm_match: in std_logic;
+ tm_top: out unsigned;
+
+ -- general purpose counter
+ count_top: out unsigned;
+ count_match: in std_logic;
+ count_rst: out std_logic;
+
+ -- sipo register
+ sipo_val: in std_logic_vector;
+ sipo_latch: out std_logic;
+
+ -- enable data conversion stages
+ gray_to_bin_en: out std_logic;
+ lsb_to_msb_en: out std_logic
+);
+end component;
+
+
+component master_biss
+generic
+(
+ CLK_FREQ: integer
+);
+port
+(
+ -- local clock
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- master clock edges
+ ma_clk_fedge: in std_logic;
+ ma_clk_redge: in std_logic;
+
+ -- the edge we are interested in
+ ma_clk_edge: out std_logic;
+
+ -- master clock reset
+ -- if ma_clk_rst_en, use ma_clk_rst_level
+ ma_clk_rst_en: out std_logic;
+ ma_clk_rst_val: out std_logic;
+
+ -- master out, slave in
+ mosi: out std_logic;
+ miso: in std_logic;
+
+ -- gate to drive output (1 to drive it)
+ gate: out std_logic;
+
+ -- desired data length
+ len: in unsigned;
+
+ -- timeout counter
+ tm_match: in std_logic;
+ tm_top: out unsigned;
+
+ -- general purpose counter
+ count_top: out unsigned;
+ count_match: in std_logic;
+ count_rst: out std_logic;
+
+ -- sipo register
+ sipo_val: in std_logic_vector;
+ sipo_latch: out std_logic;
+
+ -- enable data conversion stages
+ gray_to_bin_en: out std_logic;
+ lsb_to_msb_en: out std_logic
+);
+end component;
+
+
+component master_ssi
+generic
+(
+ CLK_FREQ: integer
+);
+port
+(
+ -- local clock
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- master clock edges
+ ma_clk_fedge: in std_logic;
+ ma_clk_redge: in std_logic;
+
+ -- the edge we are interested in
+ ma_clk_edge: out std_logic;
+
+ -- master clock reset
+ -- if ma_clk_rst_en, use ma_clk_rst_level
+ ma_clk_rst_en: out std_logic;
+ ma_clk_rst_val: out std_logic;
+
+ -- master out, slave in
+ mosi: out std_logic;
+ miso: in std_logic;
+
+ -- gate to drive output (1 to drive it)
+ gate: out std_logic;
+
+ -- desired data length
+ len: in unsigned;
+
+ -- timeout counter
+ tm_match: in std_logic;
+ tm_top: out unsigned;
+
+ -- general purpose counter
+ count_top: out unsigned;
+ count_match: in std_logic;
+ count_rst: out std_logic;
+
+ -- sipo register
+ sipo_val: in std_logic_vector;
+ sipo_latch: out std_logic;
+
+ -- enable data conversion stages
+ gray_to_bin_en: out std_logic;
+ lsb_to_msb_en: out std_logic;
+
+ -- refer to absenc_pkg.master for comments
+ ssi_flags: in std_logic_vector;
+ ssi_delay_fdiv: in unsigned
+);
+end component;
+
+
+component reader_hssl is
+generic
+(
+ CLK_FREQ: integer
+);
+port
+(
+ -- local clock
+ clk: in std_logic;
+ rst: in std_logic;
+
+ -- sender clock
+ sclk: in std_logic;
+
+ -- sender out, reader in
+ sori: in std_logic;
+
+ -- actual data to send and length
+ data: out std_logic_vector;
+
+ -- configuration
+ len: in unsigned;
+ tm_gap: in unsigned
+);
+
+end component;
+
+
+--
+-- utilities
+
+component len_to_mask
+port
+(
+ len: in unsigned;
+ mask: out std_logic_vector
+);
+end component;
+
+
+component lsb_to_msb
+port
+(
+ en: in std_logic;
+ data_len: in unsigned;
+ lsb_data: in std_logic_vector;
+ msb_data: out std_logic_vector
+);
+end component;
+
+
+component bin_to_gray
+port
+(
+ en: in std_logic;
+ bin_data: in std_logic_vector;
+ gray_data: out std_logic_vector
+);
+end component;
+
+
+component gray_to_bin
+port
+(
+ en: in std_logic;
+ gray_data: in std_logic_vector;
+ bin_data: out std_logic_vector
+);
+end component;
+
+
+component extend_sign
+port
+(
+ data_len: in unsigned;
+ data_in: in std_logic_vector;
+ data_out: out std_logic_vector;
+ len_mask: in std_logic_vector
+);
+end component;
+
+
+end package absenc_pkg;
+
+
+package body absenc_pkg is
+
+--
+-- encoder positions in mux
+
+function get_enc_mux_endat
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return integer is
+begin
+ return 0;
+end get_enc_mux_endat;
+
+
+function get_enc_mux_biss
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return integer is
+ variable i: integer;
+begin
+ i := 0;
+ if enable_endat = TRUE then i := i + 1; end if;
+ return i;
+end get_enc_mux_biss;
+
+
+function get_enc_mux_ssi
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return integer is
+ variable i: integer;
+begin
+ i := 0;
+ if enable_endat = TRUE then i := i + 1; end if;
+ if enable_biss = TRUE then i := i + 1; end if;
+ return i;
+end get_enc_mux_ssi;
+
+
+--
+-- count enabled encoders
+
+function get_enc_mux_count
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return integer is
+ variable n: integer;
+begin
+ n := 0;
+ if enable_endat = TRUE then n := n + 1; end if;
+ if enable_biss = TRUE then n := n + 1; end if;
+ if enable_ssi = TRUE then n := n + 1; end if;
+ return n;
+end get_enc_mux_count;
+
+
+--
+-- mux position to encoder type
+
+function gen_enc_mux_to_type
+(
+ enable_endat: boolean;
+ enable_biss: boolean;
+ enable_ssi: boolean
+)
+return enc_type_array_t is
+ variable a: enc_type_array_t;
+ variable i: integer;
+begin
+
+ i := 0;
+
+ if enable_endat = TRUE then
+ a(i) := ENC_TYPE_ENDAT;
+ i := i + 1;
+ end if;
+
+ if enable_biss = TRUE then
+ a(i) := ENC_TYPE_BISS;
+ i := i + 1;
+ end if;
+
+ if enable_ssi = TRUE then
+ a(i) := ENC_TYPE_SSI;
+ i := i + 1;
+ end if;
+
+ return a;
+end gen_enc_mux_to_type;
+
+
+--
+-- compute integer length
+
+function integer_length
+(
+ i: integer
+)
+return integer is
+begin
+ return integer(ceil(log2(real(i))));
+end integer_length;
+
+
+--
+-- microsecond to counter clocked by freq
+
+function us_to_count
+(
+ us: integer;
+ freq: integer;
+ len: integer
+)
+return integer is
+ variable count: integer;
+begin
+ count := integer(ceil(real(us) * real(freq) / 1000000.0));
+ assert (integer_length(count) <= len) report "tm too high" severity failure;
+ return count;
+end us_to_count;
+
+
+end package body absenc_pkg;