library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; -------------------------------------------------------------------------------- entity pwm_min is generic ( IRF_ADR_W : integer := 5; PWM_W : integer := 10; BASE : integer := 0; PWMMIN_OFF : integer := 6; P_BASE : integer := 16; P_SIZE : integer := 4; PWM_OFF : integer := 1); port ( -- Primary Slave interface ACK_O : out std_logic; CLK_I : in std_logic; RST_I : in std_logic; STB_I : in std_logic; -- Shared dual-port memory IRF_ACK_I : in std_logic; IRF_ADR_O : out std_logic_vector (IRF_ADR_W-1 downto 0); IRF_DAT_I : in std_logic_vector (15 downto 0); IRF_DAT_O : out std_logic_vector (15 downto 0); IRF_STB_O : out std_logic; IRF_WE_O : out std_logic); end pwm_min; -------------------------------------------------------------------------------- architecture behavioral of pwm_min is type state_t is (ready, phase1, phase2, phase3, done); subtype irf_adr_t is std_logic_vector (IRF_ADR_W-1 downto 0); constant PWMMIN : irf_adr_t := conv_std_logic_vector(BASE+PWMMIN_OFF, IRF_ADR_W); constant PWM1 : irf_adr_t := conv_std_logic_vector(P_BASE+PWM_OFF+0*P_SIZE, IRF_ADR_W); constant PWM2 : irf_adr_t := conv_std_logic_vector(P_BASE+PWM_OFF+1*P_SIZE, IRF_ADR_W); constant PWM3 : irf_adr_t := conv_std_logic_vector(P_BASE+PWM_OFF+2*P_SIZE, IRF_ADR_W); signal state : state_t := ready; signal pwm_adr : std_logic_vector (IRF_ADR_W-1 downto 0); --signal pwm_compare : std_logic_vector (PWM_W-1 downto 0); signal pwm_compare : std_logic_vector (PWM_W-1 downto 0); signal pwm_less : std_logic; signal write_min : std_logic; signal ack : std_logic := '0'; signal irf_stb : std_logic := '0'; signal irf_we : std_logic; -------------------------------------------------------------------------------- begin ACK_O <= ack and STB_I; IRF_ADR_O <= PWMMIN when write_min = '1' else pwm_adr; IRF_DAT_O <= IRF_DAT_I; IRF_STB_O <= irf_stb and (not write_min or irf_we); IRF_WE_O <= irf_we; pwm_less <= '1' when IRF_DAT_I(pwm_compare'RANGE) < pwm_compare else '0'; irf_we <= '1' when (pwm_less = '1' or state = phase1) and write_min = '1' else '0'; process (CLK_I) is begin if rising_edge(CLK_I) then if irf_we = '1' then pwm_compare <= IRF_DAT_I(pwm_compare'RANGE); end if; end if; end process; FSM : process (CLK_I) is begin if rising_edge(CLK_I) then if RST_I = '1' then state <= ready; ack <= '0'; irf_stb <= '0'; else case state is when ready => if STB_I = '1' then state <= phase1; pwm_adr <= PWM1; irf_stb <= '1'; write_min <= '0'; end if; when phase1 => write_min <= '1'; if write_min = '1' then state <= phase2; pwm_adr <= PWM2; write_min <= '0'; end if; when phase2 => write_min <= '1'; if write_min = '1' then state <= phase3; pwm_adr <= PWM3; write_min <= '0'; end if; when phase3 => write_min <= '1'; if write_min = '1' then state <= done; ack <= '1'; irf_stb <= '0'; write_min <= '0'; end if; when done => if STB_I = '0' then state <= ready; ack <= '0'; end if; end case; end if; end if; end process; end behavioral;