aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/issue1655/absenc_master_endat.vhdl
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2021-02-20 10:04:00 +0100
committerTristan Gingold <tgingold@free.fr>2021-02-20 10:04:00 +0100
commite6f397e0ee0c8e3e8f0ca5ac864f02a4cd305818 (patch)
tree7931a3b8fc13653784e9aea0c8edca0c014ed259 /testsuite/gna/issue1655/absenc_master_endat.vhdl
parenta18c2b2b4491607c4bdaf723c82979e4fb2ad36f (diff)
downloadghdl-e6f397e0ee0c8e3e8f0ca5ac864f02a4cd305818.tar.gz
ghdl-e6f397e0ee0c8e3e8f0ca5ac864f02a4cd305818.tar.bz2
ghdl-e6f397e0ee0c8e3e8f0ca5ac864f02a4cd305818.zip
testsuite/gna: add a test for #1655
Diffstat (limited to 'testsuite/gna/issue1655/absenc_master_endat.vhdl')
-rw-r--r--testsuite/gna/issue1655/absenc_master_endat.vhdl314
1 files changed, 314 insertions, 0 deletions
diff --git a/testsuite/gna/issue1655/absenc_master_endat.vhdl b/testsuite/gna/issue1655/absenc_master_endat.vhdl
new file mode 100644
index 000000000..2d0daf141
--- /dev/null
+++ b/testsuite/gna/issue1655/absenc_master_endat.vhdl
@@ -0,0 +1,314 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use ieee.math_real.all;
+
+library work;
+
+
+entity master_endat is
+
+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 entity;
+
+
+architecture absenc_master_endat_rtl of master_endat is
+
+
+--
+-- default timeout value. standard says: 10 to 30 us
+
+constant TM_VAL: integer := work.absenc_pkg.us_to_count
+ (work.absenc_pkg.MASTER_DEFAULT_TM_US, CLK_FREQ, tm_top'length);
+
+
+--
+-- main state machine
+
+type endat_state_t is
+(
+ ENDAT_INIT,
+
+ ENDAT_T0,
+ ENDAT_T1,
+ ENDAT_MODE,
+ ENDAT_T3,
+ ENDAT_T4,
+
+ ENDAT_T5,
+
+ ENDAT_START,
+ ENDAT_F1,
+ ENDAT_DATA,
+
+ ENDAT_CRC5_FIRST,
+ ENDAT_CRC5_CONT,
+
+ ENDAT_DONE
+);
+
+constant ENDAT_TMOUT: endat_state_t := ENDAT_DONE;
+constant ENDAT_ERR: endat_state_t := ENDAT_DONE;
+
+signal curr_state: endat_state_t;
+signal next_state: endat_state_t;
+
+
+--
+-- right shifted parallel in, serial out register
+-- loaded values are in reverse order
+
+constant piso_ini: std_logic_vector := "111000";
+signal piso_val: std_logic_vector(piso_ini'length - 1 downto 0);
+signal piso_load: std_logic;
+
+
+begin
+
+
+--
+-- state automaton
+
+process
+begin
+ wait until rising_edge(clk);
+
+ if (rst = '1') then
+ curr_state <= ENDAT_TMOUT;
+ elsif ((tm_match or ma_clk_fedge) = '1') then
+ curr_state <= next_state;
+ end if;
+
+end process;
+
+
+process(curr_state, count_match, tm_match, miso)
+begin
+
+ next_state <= curr_state;
+
+ case curr_state is
+
+ when ENDAT_INIT =>
+ next_state <= ENDAT_T0;
+
+ when ENDAT_T0 =>
+ next_state <= ENDAT_T1;
+
+ when ENDAT_T1 =>
+ next_state <= ENDAT_MODE;
+
+ when ENDAT_MODE =>
+ if (count_match = '1') then
+ next_state <= ENDAT_T3;
+ end if;
+
+ when ENDAT_T3 =>
+ next_state <= ENDAT_T4;
+
+ when ENDAT_T4 =>
+ next_state <= ENDAT_T5;
+
+ when ENDAT_T5 =>
+ next_state <= ENDAT_START;
+
+ when ENDAT_START =>
+ if (miso = '1') then
+ next_state <= ENDAT_F1;
+ elsif (tm_match = '1') then
+ next_state <= ENDAT_TMOUT;
+ end if;
+
+ when ENDAT_F1 =>
+ next_state <= ENDAT_DATA;
+
+ when ENDAT_DATA =>
+ if (count_match = '1') then
+ next_state <= ENDAT_CRC5_FIRST;
+ end if;
+
+ when ENDAT_CRC5_FIRST =>
+ next_state <= ENDAT_CRC5_CONT;
+
+ when ENDAT_CRC5_CONT =>
+ if (count_match = '1') then
+ next_state <= ENDAT_DONE;
+ end if;
+
+ when ENDAT_DONE =>
+ -- wait for at least one timeout
+ next_state <= ENDAT_INIT;
+
+ when others =>
+ next_state <= ENDAT_ERR;
+
+ end case;
+
+end process;
+
+
+process
+begin
+
+ wait until rising_edge(clk);
+
+ ma_clk_rst_en <= '0';
+ count_top <= (count_top'range => '0');
+ count_rst <= '0';
+ sipo_latch <= '0';
+ gate <= '0';
+ mosi <= '0';
+ piso_load <= '0';
+
+ case curr_state is
+
+ when ENDAT_INIT =>
+ gate <= '1';
+
+ when ENDAT_T0 =>
+ gate <= '1';
+
+ when ENDAT_T1 =>
+ piso_load <= '1';
+ gate <= '1';
+ count_top <= to_unsigned(6, count_top'length);
+ count_rst <= '1';
+
+ when ENDAT_MODE =>
+ mosi <= piso_val(0);
+ gate <= '1';
+
+ when ENDAT_T3 =>
+ mosi <= '0';
+ gate <= '1';
+
+ when ENDAT_T4 =>
+ mosi <= '0';
+ gate <= '1';
+
+ when ENDAT_T5 =>
+
+ when ENDAT_START =>
+
+ when ENDAT_F1 =>
+ count_top <= len(count_top'range);
+ count_rst <= '1';
+
+ when ENDAT_DATA =>
+ -- sent LSb first
+
+ when ENDAT_CRC5_FIRST =>
+ count_top <= to_unsigned(integer(5 - 1), count_top'length);
+ count_rst <= '1';
+ sipo_latch <= '1';
+
+ when ENDAT_CRC5_CONT =>
+
+ when ENDAT_DONE =>
+ ma_clk_rst_en <= '1';
+
+ when others =>
+
+ end case;
+
+end process;
+
+
+--
+-- right shifted piso register
+-- set at falling edge, sample by slave at redge
+
+process
+begin
+ wait until rising_edge(clk);
+
+ if (piso_load = '1') then
+ piso_val <= piso_ini;
+ elsif (ma_clk_fedge = '1') then
+ piso_val <= '0' & piso_val(piso_val'length - 1 downto 1);
+ end if;
+
+end process;
+
+
+--
+-- clock reset or idle value
+
+ma_clk_rst_val <= '1';
+
+
+--
+-- timeout
+
+tm_top <= to_unsigned(TM_VAL, tm_top'length);
+
+
+--
+-- gray to binary disabled
+
+gray_to_bin_en <= '0';
+
+
+--
+-- lsb to msb enabled
+
+lsb_to_msb_en <= '1';
+
+
+--
+-- use falling edge
+
+ma_clk_edge <= ma_clk_fedge;
+
+
+end architecture;