From: Vladimir Burian Date: Sat, 26 Mar 2011 16:30:22 +0000 (+0100) Subject: Added irc_base. X-Git-Url: https://rtime.felk.cvut.cz/gitweb/fpga/pwm.git/commitdiff_plain/b76b2092a47d96eb9b20cef32f7ce06ee2ab893b Added irc_base. This entity keeps angle value in appropriate interval according to IRC_PER_REVOLUTION and modifies IRC_BASE value. When IRC value and IRC_BASE differs by more than two revolutions, BAD_BASE signal is set high during one CLK_I period. --- diff --git a/irc_base.vhd b/irc_base.vhd new file mode 100644 index 0000000..ec1fab3 --- /dev/null +++ b/irc_base.vhd @@ -0,0 +1,136 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +-------------------------------------------------------------------------------- + +entity irc_base is + generic ( + IRF_ADR_W : integer := 5; + BASE : integer := 0; + IRC_OFF : integer := 1; + ABASE_OFF : integer := 2; + APER_OFF : integer := 3; + A_OFF : integer := 4); + port ( + -- Primary slave interface + ACK_O : out std_logic; + CLK_I : in std_logic; + RST_I : in std_logic; + STB_I : in std_logic; + -- Master interface to the interface 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; + -- Error flag + BAD_BASE : out std_logic); +end entity irc_base; + +-------------------------------------------------------------------------------- + +architecture behavioral of irc_base is + + type state_t is (ready, nop, load_irc, load_base, load_per, do_correction, save, done); + subtype irf_adr_t is std_logic_vector (IRF_ADR_W-1 downto 0); + + constant IRC_ADR : irf_adr_t := conv_std_logic_vector(BASE+IRC_OFF, IRF_ADR_W); + constant BASE_ADR : irf_adr_t := conv_std_logic_vector(BASE+ABASE_OFF, IRF_ADR_W); + constant PER_ADR : irf_adr_t := conv_std_logic_vector(BASE+APER_OFF, IRF_ADR_W); + constant ANG_ADR : irf_adr_t := conv_std_logic_vector(BASE+A_OFF, IRF_ADR_W); + + + signal state : state_t; + signal irc : std_logic_vector (15 downto 0); + signal irc_base : std_logic_vector (15 downto 0); + signal irc_per : std_logic_vector (15 downto 0); + + signal angle : std_logic_vector (15 downto 0); + signal new_base : std_logic_vector (15 downto 0); + signal lower : std_logic; + signal higher : std_logic; + +-------------------------------------------------------------------------------- + +begin + + BAD_BASE <= '1' when state = save and (lower = '1' or higher = '1') else '0'; + + lower <= angle (angle'HIGH); + higher <= '1' when angle > irc_per and lower = '0' else '0'; + + angle <= irc - irc_base; + + new_base <= irc_base - irc_per when lower = '1' else + irc_base + irc_per when higher = '1' else + irc_base; + + + FSM : process (CLK_I) is + begin + if rising_edge(CLK_I) then + if RST_I = '1' or STB_I = '0' then + state <= ready; + ACK_O <= '0'; + IRF_STB_O <= '0'; + IRF_WE_O <= '0'; + + else + case state is + when ready => + if STB_I = '1' then + state <= nop; + IRF_ADR_O <= IRC_ADR; + IRF_STB_O <= '1'; + end if; + + when nop => + state <= load_irc; + IRF_ADR_O <= BASE_ADR; + + when load_irc => + state <= load_base; + irc <= IRF_DAT_I; + IRF_ADR_O <= PER_ADR; + + when load_base => + state <= load_per; + irc_base <= IRF_DAT_I; + + when load_per => + state <= do_correction; + irc_per <= IRF_DAT_I; + IRF_STB_O <= '0'; + + when do_correction => + state <= save; + irc_base <= new_base; + IRF_ADR_O <= BASE_ADR; + IRF_DAT_O <= new_base; + IRF_STB_O <= '1'; + IRF_WE_O <= '1'; + + when save => + state <= done; + IRF_ADR_O <= ANG_ADR; + IRF_DAT_O <= angle; + ACK_O <= '1'; + + when done => + IRF_STB_O <= '0'; + IRF_WE_O <= '0'; + if STB_I = '0' then + state <= ready; + ACK_O <= '0'; + end if; + end case; + + end if; + end if; + end process; + +end architecture behavioral; + diff --git a/mcc.vhd b/mcc.vhd index 47ebe0a..6d309ba 100644 --- a/mcc.vhd +++ b/mcc.vhd @@ -76,6 +76,11 @@ architecture behavioral of mcc is signal IRC_IRF_DAT_O : std_logic_vector (15 downto 0); signal IRC_IRF_STB_O : std_logic; signal IRC_IRF_WE_O : std_logic; + + signal BASE_IRF_ADR_O : std_logic_vector (IRF_ADR_W-1 downto 0); + signal BASE_IRF_DAT_O : std_logic_vector (15 downto 0); + signal BASE_IRF_STB_O : std_logic; + signal BASE_IRF_WE_O : std_logic; type state_t is (ready, read_mask, do_mcc, done); @@ -94,24 +99,28 @@ begin IRF_ADR_O <= MASTER_IRF_ADR_O when MCC_MUX_EN = '0' else IRC_IRF_ADR_O when MCC_MUX_CODE = 0 else + BASE_IRF_ADR_O when MCC_MUX_CODE = 1 else VECTOR_IRF_ADR_O when MCC_MUX_CODE = 2 else PWM_IRF_ADR_O when MCC_MUX_CODE = 5 else (others => '-'); IRF_DAT_O <= MASTER_IRF_DAT_O when MCC_MUX_EN = '0' else IRC_IRF_DAT_O when MCC_MUX_CODE = 0 else + BASE_IRF_DAT_O when MCC_MUX_CODE = 1 else VECTOR_IRF_DAT_O when MCC_MUX_CODE = 2 else PWM_IRF_DAT_O when MCC_MUX_CODE = 5 else (others => '-'); IRF_STB_O <= MASTER_IRF_STB_O when MCC_MUX_EN = '0' else IRC_IRF_STB_O when MCC_MUX_CODE = 0 else + BASE_IRF_STB_O when MCC_MUX_CODE = 1 else VECTOR_IRF_STB_O when MCC_MUX_CODE = 2 else PWM_IRF_STB_O when MCC_MUX_CODE = 5 else '0'; IRF_WE_O <= MASTER_IRF_WE_O when MCC_MUX_EN = '0' else IRC_IRF_WE_O when MCC_MUX_CODE = 0 else + BASE_IRF_WE_O when MCC_MUX_CODE = 1 else VECTOR_IRF_WE_O when MCC_MUX_CODE = 2 else '0'; @@ -157,6 +166,27 @@ begin IRF_DAT_O => IRC_IRF_DAT_O, IRF_STB_O => IRC_IRF_STB_O, IRF_WE_O => IRC_IRF_WE_O); + + irc_base_1 : entity work.irc_base + generic map ( + IRF_ADR_W => IRF_ADR_W, + BASE => 16#00#, + IRC_OFF => 16#01#, + ABASE_OFF => 16#02#, + APER_OFF => 16#03#, + A_OFF => 16#04#) + port map ( + ACK_O => MCC_ACK (1), + CLK_I => CLK_I, + RST_I => RST_I, + STB_I => MCC_STB (1), + IRF_ACK_I => IRF_ACK_I, + IRF_ADR_O => BASE_IRF_ADR_O, + IRF_DAT_I => IRF_DAT_I, + IRF_DAT_O => BASE_IRF_DAT_O, + IRF_STB_O => BASE_IRF_STB_O, + IRF_WE_O => BASE_IRF_WE_O, + BAD_BASE => open); vector_gen_1 : entity work.vector_gen generic map ( diff --git a/tb/Makefile b/tb/Makefile index ee49ed9..bcd8fbd 100644 --- a/tb/Makefile +++ b/tb/Makefile @@ -12,6 +12,7 @@ VHDL_ENTITIES = counter.o \ sequencer.o \ pwm_dump.o \ irc_dump.o \ + irc_base.o \ mcc.o diff --git a/tb/tb_mcc.sav b/tb/tb_mcc.sav index 5bcefb9..3e48968 100644 --- a/tb/tb_mcc.sav +++ b/tb/tb_mcc.sav @@ -9,12 +9,14 @@ clk_i rst_i stb_i ack_o -@23 +@22 irc_dat_i[15:0] @28 dbg_mem00[15:0] @22 dbg_mem01[15:0] +dbg_mem02[15:0] +dbg_mem03[15:0] dbg_mem04[15:0] dbg_mem11[15:0] dbg_mem15[15:0] diff --git a/tb/tb_mcc.vhd b/tb/tb_mcc.vhd index 3b49380..d08d85f 100644 --- a/tb/tb_mcc.vhd +++ b/tb/tb_mcc.vhd @@ -43,9 +43,11 @@ architecture testbench of tb_mcc is subtype word_t is std_logic_vector (15 downto 0); - signal dbg_mem00 : word_t := "0000000000100101"; -- MCC enable flags (RO) + signal dbg_mem00 : word_t := "0000000000100111"; -- MCC enable flags (RO) signal dbg_mem01 : word_t := (others => '0'); -- IRC - signal dbg_mem04 : word_t := (others => '0'); -- Angle (RO) + signal dbg_mem02 : word_t := "0000000000000000"; -- IRC base + signal dbg_mem03 : word_t := "0000000000000111"; -- IRC per revolution (7) + signal dbg_mem04 : word_t := (others => '0'); -- Angle signal dbg_mem11 : word_t := (others => '0'); -- Phase 1 signal dbg_mem15 : word_t := (others => '0'); -- Phase 2 signal dbg_mem19 : word_t := (others => '0'); -- Phase 3 @@ -132,6 +134,8 @@ begin case conv_integer(IRF_ADR_O) is when 16#00# => IRF_DAT_I <= dbg_mem00; when 16#01# => IRF_DAT_I <= dbg_mem01; + when 16#02# => IRF_DAT_I <= dbg_mem02; + when 16#03# => IRF_DAT_I <= dbg_mem03; when 16#04# => IRF_DAT_I <= dbg_mem04; when 16#11# => IRF_DAT_I <= dbg_mem11; when 16#15# => IRF_DAT_I <= dbg_mem15; @@ -141,6 +145,9 @@ begin else case conv_integer(IRF_ADR_O) is when 16#01# => dbg_mem01 <= IRF_DAT_O; + when 16#02# => dbg_mem02 <= IRF_DAT_O; + when 16#03# => dbg_mem03 <= IRF_DAT_O; + when 16#04# => dbg_mem04 <= IRF_DAT_O; when 16#11# => dbg_mem11 <= IRF_DAT_O; when 16#15# => dbg_mem15 <= IRF_DAT_O; when 16#19# => dbg_mem19 <= IRF_DAT_O; @@ -155,15 +162,13 @@ begin UUT_FEED : process is begin STB_I <= '0'; - IRC_DAT_I <= "0000000010101010"; wait for offset; wait for 4*period; for i in 0 to 1 loop - dbg_mem04 <= conv_std_logic_vector(i, 16); - - IRC_DAT_I <= conv_std_logic_vector(i, 16); + IRC_DAT_I <= conv_std_logic_vector(8*i, 16); + --dbg_mem04 <= conv_std_logic_vector(i, 16); STB_I <= '1'; wait until rising_edge(CLK_I) and ACK_O = '1';