library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; use work.IOB_Config.ALL; entity DS1302ClkCal is generic ( addr: DevID := CLKCALBASE ); port ( -- clocks clk: in std_logic; bitclk: in std_logic; -- CPU bus interface reset : in boolean; IOTact: in boolean; IOTdev: in DevID; IOTcmd: in DevCmd; cpu_write_n : in std_logic; clk_write_n : in std_logic; IOTread : in boolean; dx : inout std_logic_vector(0 to 11); cpu_c0_n : out std_logic; cpu_c1_n : out std_logic; cpu_skip_n : out std_logic; -- I/O RST_n : out std_logic; SCLK : out std_logic; SIO : inout std_logic ); end DS1302ClkCal; architecture RTL of DS1302ClkCal is type States is (Idle, Leader1, Leader2, SendCmd, RcvData, SendData, Trailer); signal data_reg, cmd_reg: std_logic_vector(0 to 7); signal bitctr: unsigned(3 downto 0); signal state : States; signal rw: std_logic; signal wrcmd_1, wrcmd_2: std_logic; signal wrdata_1, wrdata_2: std_logic; begin -- async bus interface process (IOTact, IOTdev, IOTcmd, cpu_write_n, IOTread, state, data_reg) begin if IOTact and (IOTDev = addr) then if (cpu_write_n = '0') and (IOTcmd = CCRD) then cpu_c0_n <= '0'; cpu_c1_n <= '0'; else cpu_c0_n <= 'Z'; cpu_c1_n <= 'Z'; end if; if (cpu_write_n = '0') and (IOTcmd = CCSK) and (state = Idle) then cpu_skip_n <= '0'; else cpu_skip_n <= 'Z'; end if; if IOTread then dx <= "0000" & data_reg; else dx <= (others => 'Z'); end if; else cpu_c0_n <= 'Z'; cpu_c1_n <= 'Z'; cpu_skip_n <= 'Z'; dx <= (others => 'Z'); end if; end process; -- sync bus interface process (reset, IOTact, IOTdev, IOTcmd, clk_write_n, wrcmd_2, wrdata_2) begin if reset then wrcmd_1 <= '0'; wrdata_1 <= '0'; elsif rising_edge(clk_write_n) then if IOTact and (IOTDev = addr) then case IOTcmd is when CCCM => wrcmd_1 <= not wrcmd_2; when CCWR => wrdata_1 <= not wrdata_2; when others => null; end case; end if; end if; end process; -- state machine process (state, bitctr, cmd_reg, data_reg) begin case state is when Idle => SCLK <= 'Z'; RST_n <= '0'; SIO <= 'Z'; when Leader1 => SCLK <= '0'; RST_n <= '0'; SIO <= '0'; when Leader2 => SCLK <= '0'; RST_n <= '1'; SIO <= '0'; when SendCmd => RST_n <= '1'; SCLK <= bitctr(0); SIO <= cmd_reg(7); when RcvData => RST_n <= '1'; SCLK <= bitctr(0); SIO <= 'Z'; when SendData => RST_n <= '1'; SCLK <= bitctr(0); SIO <= data_reg(7); when Trailer => SCLK <= '0'; RST_n <= '1'; SIO <= '0'; end case; end process; process (reset, clk, bitclk, state, dx, wrcmd_1, wrdata_1) begin if reset then wrcmd_2 <= '0'; wrdata_2 <= '0'; data_reg <= (others => '0'); elsif rising_edge(clk) then if wrcmd_2 /= wrcmd_1 then cmd_reg <= dx(4 to 11); rw <= dx(11); wrcmd_2 <= wrcmd_1; state <= Leader1; bitctr <= "0000"; elsif wrdata_2 /= wrdata_1 then data_reg <= dx(4 to 11); wrdata_2 <= wrdata_1; elsif bitclk = '1' then case state is when Idle => null; when Leader1 => state <= Leader2; when Leader2 => state <= SendCmd; when SendCmd => bitctr <= bitctr + 1; if bitctr = "1111" then if rw = '0' then state <= SendData; else state <= RcvData; end if; else if bitctr(0) = '1' then cmd_reg(1 to 7) <= cmd_reg(0 to 6); end if; end if; when RcvData => bitctr <= bitctr + 1; if bitctr = "1111" then state <= Trailer; else if bitctr(0) = '0' then data_reg <= SIO & data_reg(0 to 6); end if; end if; when SendData => bitctr <= bitctr + 1; if bitctr = "1111" then state <= Trailer; else if bitctr(0) = '1' then data_reg <= '0' & data_reg(0 to 6); end if; end if; when Trailer => state <= Idle; end case; end if; end if; end process; end RTL;