⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isp8_flow_cntl.vhd

📁 Lattice 超精简8位软核CPU--Mico8
💻 VHD
字号:
------------------------------------------------------------------------------
-- 
--  Name:   isp8_flow_cntl.vhd
-- 
--  Description:  Flow control logic
-- 
--  $Revision: 1.3 $
--  
------------------------------------------------------------------------------
-- Permission:
--
--   Lattice Semiconductor grants permission to use this code for use
--   in synthesis for any Lattice programmable logic product.  Other
--   use of this code, including the selling or duplication of any
--   portion is strictly prohibited.
--
-- Disclaimer:
--
--   This VHDL or Verilog source code is intended as a design reference
--   which illustrates how these types of functions can be implemented.
--   It is the user's responsibility to verify their design for
--   consistency and functionality through the use of formal
--   verification methods.  Lattice Semiconductor provides no warranty
--   regarding the use or functionality of this code.
------------------------------------------------------------------------------
--
--    Lattice Semiconductor Corporation
--    5555 NE Moore Court
--    Hillsboro, OR 97124
--    U.S.A
--
--    TEL: 1-800-Lattice (USA and Canada)
--    408-826-6000 (other locations)
--
--    web: http://www.latticesemi.com/
--    email: techsupport@latticesemi.com
-- 
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity isp8_flow_cntl is
   generic(PROM_AW      :     natural;
           FAMILY_NAME  :     string;
           PGM_STACK_AW :     natural;
           PGM_STACK_AD :     natural);
   port(clk             : in  std_logic;
        rst_n           : in  std_logic;
        setc            : in  std_logic;
        clrc            : in  std_logic;
        setz            : in  std_logic;
        clrz            : in  std_logic;
        seti            : in  std_logic;
        clri            : in  std_logic;
        addr_jmp        : in  std_logic_vector((PROM_AW - 1) downto 0);
        update_c        : in  std_logic;
        update_z        : in  std_logic;
        cout_alu        : in  std_logic;
        dout_alu        : in  std_logic_vector(7 downto 0);
        bz              : in  std_logic;
        bnz             : in  std_logic;
        bc              : in  std_logic;
        bnc             : in  std_logic;
        b               : in  std_logic;
        callz           : in  std_logic;
        callnz          : in  std_logic;
        callc           : in  std_logic;
        callnc          : in  std_logic;
        call            : in  std_logic;
        ret             : in  std_logic;
        iret            : in  std_logic;
        intr            : in  std_logic;
        lsp             : in  std_logic;
        lspi            : in  std_logic;
        ssp             : in  std_logic;
        sspi            : in  std_logic;
        import          : in  std_logic;
        importi         : in  std_logic;
        export          : in  std_logic;
        exporti         : in  std_logic;
        ready           : in  std_logic;
        addr_cyc        : out std_logic;
        ext_addr_cyc    : out std_logic;
        data_cyc        : out std_logic;
        prom_addr       : out std_logic_vector((PROM_AW - 1) downto 0);
        carry_flag      : out std_logic;
        intr_ack        : out std_logic);
end isp8_flow_cntl;


architecture behave of isp8_flow_cntl is

   component pmi_distributed_spram
      generic (
         pmi_addr_depth       : integer;
         pmi_addr_width       : integer;
         pmi_data_width       : integer;
         pmi_regmode          : string;
         pmi_init_file        : string;
         pmi_init_file_format : string;
         pmi_family           : string;
         module_type          : string := "pmi_distributed_spram"
         );
      port (
         Address : in  std_logic_vector(pmi_addr_width-1 downto 0);
         Data    : in  std_logic_vector(pmi_data_width-1 downto 0);
         Clock   : in  std_logic;
         ClockEn : in  std_logic;
         WE      : in  std_logic;
         Reset   : in  std_logic;
         Q       : out std_logic_vector(pmi_data_width-1 downto 0));
   end component;

   signal rst                       : std_logic;
   signal lo_val                    : std_logic;
   signal hi_val                    : std_logic;
   signal carry_flag_int            : std_logic;
   signal zero_flag                 : std_logic;
   signal ie_flag                   : std_logic;
   signal pc, pc_int                : std_logic_vector((PROM_AW - 1) downto 0);
   signal addr_cyc_int              : std_logic;
   signal ext_addr_cyc_int          : std_logic;
   signal data_cyc_int              : std_logic;
   signal ret_reg                   : std_logic;
   signal intr_req_actv_reg         : std_logic;
   signal dout_alu_reg              : std_logic_vector(7 downto 0);
   signal push_enb                  : std_logic;
   signal intr_req_actv             : std_logic;
   signal intr_reg0                 : std_logic;
   signal addr_jmp_reg              : std_logic_vector((PROM_AW - 1) downto 0);
   signal prom_addr_int             : std_logic_vector((PROM_AW - 1) downto 0);
   signal br_enb, br_enb_reg        : std_logic;
   signal intr_ack_int              : std_logic;
   signal dout_stack                : std_logic_vector((PROM_AW - 1) downto 0);
   signal dout_stack_w_cz           : std_logic_vector((PROM_AW + 1) downto 0);
   signal din_stack_w_cz            : std_logic_vector((PROM_AW + 1) downto 0);
   signal pushed_zero, pushed_carry : std_logic;
   signal sp_we                     : std_logic;
   signal br_enb0                   : std_logic;
   signal stack_ptr                 : std_logic_vector(PGM_STACK_AW-1 downto 0);

   signal condbr : std_logic;
   signal ext_cycle_type : std_logic;
   
--attribute syn_black_box : boolean;
--attribute syn_black_box of pmi_distributed_spram: component is true;

begin

   rst    <= not rst_n;
   lo_val <= '0';
   hi_val <= '1';
   condbr <= bz or bnz or bc or bnc or call or callz or callnz or callc or callnc;

   ext_cycle_type           <= (lspi or lsp or sspi or ssp or
                                export or exporti or import or
                                importi);
   process(clk, rst_n)
   begin
      if (rst_n = '0') then
         addr_cyc_int     <= '0';
         ext_addr_cyc_int <= '0';
         data_cyc_int     <= '0';
      elsif rising_edge(clk) then
         addr_cyc_int     <= (NOT(addr_cyc_int) and (not(ext_addr_cyc_int)));
         ext_addr_cyc_int <= (addr_cyc_int and ext_cycle_type) or
                             (ext_addr_cyc_int and not ready);
         data_cyc_int     <= (addr_cyc_int and not ext_cycle_type) or
                             (ext_addr_cyc_int and ready);
      end if;
   end process;

   addr_cyc <= addr_cyc_int;
   ext_addr_cyc <= ext_addr_cyc_int;
   data_cyc <= data_cyc_int;

   process(clk, rst_n)
   begin
      if (rst_n = '0') then
         ret_reg <= '0';
         intr_req_actv_reg <= '0';
         dout_alu_reg <= "00000000";
      elsif rising_edge(clk) then
         ret_reg <= (ret OR iret);
         intr_req_actv_reg <= intr_req_actv;
         dout_alu_reg <= dout_alu;
      end if;
   end process;

   process(clk, rst_n)
   begin
      if (rst_n = '0') then
         intr_reg0 <= '0';
      elsif rising_edge(clk) then
         if (addr_cyc_int = '1') then
            intr_reg0 <= ie_flag and intr and not condbr;
         else
            intr_reg0 <= intr_reg0;
         end if;
      end if;
   end process;

   process(clk, rst_n)
   begin
      if (rst_n = '0') then
         addr_jmp_reg <= (others => '0');
         br_enb_reg   <= '0';
      elsif rising_edge(clk) then
         if (addr_cyc_int = '1') then
            addr_jmp_reg <= addr_jmp;
            br_enb_reg   <= br_enb;
         end if;
      end if;
   end process;

   intr_req_actv <= (intr_reg0 AND NOT(intr_ack_int));

-- Push enable to store in stack
   push_enb <= ((callz AND zero_flag) OR (callc AND carry_flag_int) OR
                (callnz AND NOT(zero_flag)) OR (callnc AND NOT(carry_flag_int)) OR call);

-- Branch enable to branch out the programm counter
   br_enb0 <= ((bz AND zero_flag) OR (bc AND carry_flag_int) OR
               (bnz AND NOT zero_flag) OR (bnc AND NOT carry_flag_int)) ;

   br_enb <= ((bz AND zero_flag) OR (bc AND carry_flag_int) OR
              (bnz AND NOT(zero_flag)) OR (bnc AND NOT(carry_flag_int)) OR b OR push_enb);

-- program coumter
-- Incremented every address cycle (2 clocks) and 
-- loaded with stack with return instruction.
-- loaded interrupt vector with interrupt.
   pc_int <= (pc + addr_jmp_reg) when ((br_enb_reg = '1') AND (data_cyc_int = '1')) else pc + '1';

   process(intr_req_actv, ret_reg, dout_stack, pc_int, push_enb, br_enb0, data_cyc_int)
   begin
      if (data_cyc_int = '1') and (intr_req_actv = '1') and (push_enb = '0') and (br_enb0 = '0') then
         -- taking an interrupt
         prom_addr_int <= (others => '0');
      else
         if (ret_reg = '1') then
            -- returning from interrupt, pull return address from the stack
            prom_addr_int <= dout_stack;
         else
            -- normal straight line/jump instruction
            prom_addr_int <= pc_int;
         end if;
      end if;
   end process;

   prom_addr <= prom_addr_int;

   process(clk, rst_n)
   begin
      if (rst_n = '0') then
         pc <= (others => '0');
      elsif rising_edge(clk) then
         if (data_cyc_int = '1') then
            pc <= prom_addr_int;
         end if;
      end if;
   end process;

-- Carry flag
   process(clk,rst_n)
   begin
      if (rst_n = '0') then
         carry_flag_int <= '0';
      elsif rising_edge(clk) then
         if ((clrc = '1') OR (setc = '1') OR (update_c = '1') OR (iret = '1')) then
            carry_flag_int <= (NOT(clrc) AND ((update_c AND cout_alu) OR setc OR (iret AND pushed_carry)));
         else
            carry_flag_int <= carry_flag_int;
         end if;
      end if;
   end process;

   carry_flag <= carry_flag_int;

-- Zero flag
   process(clk,rst_n)
   begin
      if (rst_n = '0') then
         zero_flag <= '0';
      elsif rising_edge(clk) then
         if ((clrz = '1') OR (setz = '1') OR (update_z = '1') OR (iret = '1')) then
            zero_flag <= ((update_z AND data_cyc_int AND
                           NOT(dout_alu_reg(0) OR
                               dout_alu_reg(1) OR
                               dout_alu_reg(2) OR
                               dout_alu_reg(3) OR
                               dout_alu_reg(4) OR
                               dout_alu_reg(5) OR
                               dout_alu_reg(6) OR
                               dout_alu_reg(7)))
                          OR (iret AND pushed_zero)
                          OR setz);
         else
            zero_flag <= zero_flag;
         end if;
      end if;
   end process;

-- Interrupt Enable flag
   process(clk,rst_n)
   begin
      if (rst_n = '0') then
         ie_flag <= '0';
      elsif rising_edge(clk) then
         if ((clri = '1') OR (seti = '1')) then
            ie_flag <= NOT(clri);
         else
            ie_flag <= ie_flag;
         end if;
      end if;
   end process;

-- Generate interrupt acknowledge
-- Asserted as long as in interrupt service routine
   process(clk,rst_n)
   begin
      if (rst_n = '0') then
         intr_ack_int <= '0';
      elsif rising_edge(clk) then
         if ((data_cyc_int = '1') and (intr_req_actv = '1') and (push_enb = '0') and (br_enb0 = '0')) then
            intr_ack_int <= '1';
         elsif (iret = '1' and data_cyc_int = '1') then
            intr_ack_int <= '0';
         else
            intr_ack_int <= intr_ack_int;
         end if;
      end if;
   end process;

   intr_ack <= intr_ack_int;

   sp_we <= (addr_cyc_int AND push_enb) OR
            (data_cyc_int AND intr_req_actv and
             ((not push_enb) and (not br_enb0)));

   u1_isp8_stkmem : pmi_distributed_spram
      generic map (
         pmi_addr_depth       => PGM_STACK_AD,
         pmi_addr_width       => PGM_STACK_AW,
         pmi_data_width       => (PROM_AW+2),
         pmi_regmode          => "noreg",
         pmi_init_file        => "none",
         pmi_init_file_format => "binary",
         pmi_family           => FAMILY_NAME)
      port map (
         Address              => stack_ptr,
         Data                 => din_stack_w_cz,
         Clock                => clk,
         ClockEn              => hi_val,
         WE                   => sp_we,
         Reset                => lo_val,
         Q                    => dout_stack_w_cz);      


   din_stack_w_cz <= carry_flag_int & zero_flag & pc_int;
   dout_stack     <= dout_stack_w_cz(PROM_AW - 1 downto 0);
   pushed_carry   <= dout_stack_w_cz(PROM_AW + 1);
   pushed_zero    <= dout_stack_w_cz(PROM_AW);

-- Stack pointer
   process(clk, rst_n)
   begin
      if (rst_n = '0') then
         stack_ptr <= (others => '0');
      elsif rising_edge(clk) then
         if ((data_cyc_int = '1') AND ((push_enb = '1') OR (intr_req_actv = '1'))) then
            stack_ptr <= stack_ptr + '1';
         elsif ((addr_cyc_int = '1') AND ((ret = '1') OR (iret = '1'))) then
            stack_ptr <= stack_ptr - '1';
         end if;
      end if;
   end process;

end behave;

--------------------------------- E O F --------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -