]> rtime.felk.cvut.cz Git - fpga/pwm.git/commitdiff
Added irc_base.
authorVladimir Burian <buriavl2@fel.cvut.cz>
Sat, 26 Mar 2011 16:30:22 +0000 (17:30 +0100)
committerVladimir Burian <buriavl2@fel.cvut.cz>
Sat, 26 Mar 2011 16:30:22 +0000 (17:30 +0100)
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.

irc_base.vhd [new file with mode: 0644]
mcc.vhd
tb/Makefile
tb/tb_mcc.sav
tb/tb_mcc.vhd

diff --git a/irc_base.vhd b/irc_base.vhd
new file mode 100644 (file)
index 0000000..ec1fab3
--- /dev/null
@@ -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 47ebe0aaf2b1849a108190209cb5da2f3759e3c5..6d309ba16042888530fb8296e7c86c9551d3a542 100644 (file)
--- 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 (
index ee49ed9d65a29853e13b82d6573f9acdd87b3239..bcd8fbd4404bc81f15d13c04fc394c05596e8e26 100644 (file)
@@ -12,6 +12,7 @@ VHDL_ENTITIES = counter.o \
                 sequencer.o \
                 pwm_dump.o \
                 irc_dump.o \
+                irc_base.o \
                 mcc.o
 
 
index 5bcefb9be7133b37b44d24f4a0567677020b01ce..3e48968c182f08e10961bd08883db209ee1b436f 100644 (file)
@@ -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]
index 3b49380ad4dbe6de981168e581127ee1a2f37814..d08d85fab2a5ffd2c19b4df51cb9b9161c77d367 100644 (file)
@@ -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';