--
Implantable Stimulator and Transponder (IST, A3036) Firmware, Oscillator Unit library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; -- Version 01, 31-DEC-19: Expand ring to a maximum of thirteen buffers. Those not used will be eliminated by the -- compiler. The incoming calib value sets the output frequyency. We support calib values 10-25, which in our -- A3036A provide a CK period 80 to 127 ns, with the period non-decreasing with increasing calib value. -- Versin 02, 26-AUG-20: Revert to a five-gate ring oscillator with variable divisor, hoping to obtain better resolution -- in FCK period. We have found that the A3037A core logic power supply voltage suffers from 30 mVpp, an inevitable result -- of the hysteresis-mode operation of its 1.2-V buck converter, and this variation causes the FCK period to vary. But if -- we place the maximum FCK period in a 5-ns window 105-110 ns, reception is >95%. -- Version 03, 31-AUG-20: Change the end count from a signal to a variable. entity ring_oscillator is port ( ENABLE : in std_logic; calib : in integer range 0 to 31; CK : out std_logic); end; architecture behavior of ring_oscillator is -- Functions and Procedures function to_std_logic (v: boolean) return std_ulogic is begin if v then return('1'); else return('0'); end if; end function; -- Attributes to guide the compiler. attribute syn_keep : boolean; attribute nomerge : string; -- Ring Oscillator and Transmit Clock component BUFBA is port (A : in std_logic; Z : out std_logic); end component; signal RIN, R1, R2, R3, R4 : std_logic; attribute syn_keep of RIN, R1, R2, R3, R4 : signal is true; attribute nomerge of RIN, R1, R2, R3, R4 : signal is ""; signal end_count : integer; begin ring1 : BUFBA port map (RIN,R1); ring2 : BUFBA port map (R1,R2); ring3 : BUFBA port map (R2,R3); ring4 : BUFBA port map (R3,R4); divider : process (RIN, calib) is constant ck_length : integer := 4; variable count : integer range 0 to 31 := 0; variable end_count : integer range 0 to 31; begin RIN <= to_std_logic((ENABLE = '1') and (R4 = '0')); end_count := calib; if rising_edge(RIN) then if (count = end_count - 1) then count := 0; else count := count + 1; end if; if (count >= 0) and (count <= ck_length) then CK <= '1'; else CK <= '0'; end if; end if; end process; end behavior;