OpenCores
URL https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [SELF_TEST/] [RV01_selftest.vhd] - Rev 2

Compare with Previous | Blame | View Log

-----------------------------------------------------------------
--                                                             --
-----------------------------------------------------------------
--                                                             --
-- Copyright (C) 2017 Stefano Tonello                          --
--                                                             --
-- This source file may be used and distributed without        --
-- restriction provided that this copyright statement is not   --
-- removed from the file and that any derivative work contains --
-- the original copyright notice and the associated disclaimer.--
--                                                             --
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      --
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         --
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    --
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   --
-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        --
-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  --
-- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  --
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  --
-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         --
-- POSSIBILITY OF SUCH DAMAGE.                                 --
--                                                             --
-----------------------------------------------------------------
 
---------------------------------------------------------------
-- RV01 self-test module
---------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use STD.textio.all;
 
library WORK;
use work.RV01_CONSTS_PKG.all;
use work.RV01_TYPES_PKG.all;
use work.RV01_FUNCS_PKG.all;
use work.RV01_CFG_PKG.all;
use work.RV01_CSR_PKG.all;
use work.RV01_PLIC_PKG.all;
 
entity RV01_SELFTEST is
  port(
    CLK_i : in std_logic;
    RST_i : in std_logic;
 
    DONE_o : out std_logic;
    PASS_o : out std_logic
  );
end RV01_SELFTEST;
 
architecture ARC of RV01_SELFTEST is
 
  constant CFG_FLAGS : std_logic_vector(8-1 downto 0) := ( 
    '0',
    PLIC_PRESENT,
    DM_PRESENT,
    FPU_PRESENT,   
    JALR_PREDICTION_ENABLED,
    BRANCH_PREDICTION_ENABLED,
    DELAYED_EXECUTION_ENABLED,
    PARALLEL_EXECUTION_ENABLED
  );
 
  constant CCS_HALTED : natural := 19;
 
  -- Number of Dhrystone runs to performs (max. 500)
  constant CNTR_MAX : natural := 30;
 
  -- Address to stop at after every run
  constant HALT_ADR1 : ADR_T := to_unsigned(17652,ALEN);
 
  -- Final address to stop at
  constant HALT_ADRF : ADR_T := to_unsigned(3360,ALEN);
 
  -- Number of data word to be read from RV01 memory
  -- (these are the check data)
  constant CNTD_R_INIT : natural := 12;
 
  -- Number of data word to be written to RV01 memory
  -- (this is the Dhrystone executable)
  constant CNTD_W_INIT : natural := 8150;
 
  -- Run-To-End flag, if this flag is asserted, the 
  -- test program runs until completion (500 Dhrystone
  -- loop iterations), otherwise the test stops after
  -- CNTR_MAX iterations.
  constant RUN_TO_END : std_logic := '0';
 
  -- ext. FSM state type
  type XS_T is (
    XS_IDLE,
    XS_INIT1,
    XS_INIT2,
    XS_WRITE,
    XS_WRTCP1,
    XS_WRTCP2,
    XS_WRTCP6,
    XS_WRTCP7,
    XS_WRTCP8,
    XS_WAIT5,
    XS_WAIT6,
    XS_WAIT7,
    XS_WAIT8,
    XS_RUN3,
    XS_RUN4,
    XS_READ,
    XS_STOP
  );
 
  -- write FSM state type
  type WS_T is (
    WS_IDLE,
    WS_WRITI,
    WS_WRITD,
    WS_WAIT1,
    WS_WAIT2,
    WS_WAIT3
  );
 
  -- read FSM state type
  type RS_T is (
    RS_IDLE,
    RS_READ,
    RS_WAIT1,
    RS_WAIT2
  );
 
  component RV01_TOP_NOHOST is
    generic(
      -- synthesis translate_off
      ST_FILE : string := "NONE";
      WB_FILE : string := "NONE";
      -- synthesis translate_on
      IMEM_SIZE : natural := 1024*32; -- 128Kb
      DMEM_SIZE : natural := 1024*16; -- 64Kb
      IOMEM_SIZE : natural := 1024; -- 4Kb
      IMEM_SIZE_PO2 : std_logic := '1';
      DMEM_SIZE_PO2 : std_logic := '1';
      IMEM_LOWM : std_logic := '1';
      BHT_SIZE : natural := 256;
      EI_SRC_CNT : natural := 8;
      EI_TRIG_TYPE : PLIC_TRIG_TYPE := LEVEL;
      EI_REQ_MAXCNT : natural := 16;
      CFG_FLAGS : std_logic_vector(16-1 downto 0) := "00000000"&"01100111";
      SIMULATION_ONLY : std_logic := '0'
    );
    port(
      CLK_i : in std_logic; -- clock
      RST_i : in std_logic; -- reset
      -- External Interrupt Request
      EI_REQ_i : std_logic_vector(EI_SRC_CNT-1 downto 0); 
      -- Data port interface
      DP_WE_i : in std_logic; -- DP write-enable
      DP_ADR_i : in std_logic_vector(ALEN-1 downto 0);
      DP_DAT_i : in std_logic_vector(SDLEN-1 downto 0); -- DP data-in
      -- Control port interface
      CP_RE_i : in std_logic;
      CP_WE_i : in std_logic;
      CP_ADR_i : in std_logic_vector(17-1 downto 0);
      CP_DAT_i : in std_logic_vector(SDLEN-1 downto 0); 
 
      -- Data port interface
      DP_DAT_o : out std_logic_vector(SDLEN-1 downto 0); -- DP data-out
      -- Control port interface
      CP_DAT_o : out std_logic_vector(SDLEN-1 downto 0)
    );
  end component ;
 
  component RV01_STI_ROM is
    port(
      CLK_i : in std_logic;
      A_i : in unsigned(13-1 downto 0);
      Q_o : out std_logic_vector(SDLEN*2-1 downto 0)
    );
  end component;
 
  component RV01_STO_ROM is
    port(
      CLK_i : in std_logic;
      A_i : in unsigned(4-1 downto 0);
      Q_o : out std_logic_vector(SDLEN*2+4-1 downto 0)
    );
  end component;
 
  signal EI_REQ : std_logic_vector(0 downto 0) := (others => '0');
  signal DP_WE : std_logic;
  signal DP_ADR : std_logic_vector(ALEN-1 downto 0) := (others => '0');
  signal DP_DATI : std_logic_vector(SDLEN-1 downto 0) := (others => '0');
  signal DP_DATO : std_logic_vector(SDLEN-1 downto 0);
  signal DP_DAT_CHK,DP_DAT_CHK_q : std_logic_vector(SDLEN-1 downto 0);
  signal XS,XS_q : XS_T;
  signal WS,WS_q : WS_T;
  signal RS,RS_q : RS_T;
  signal WRITE_OP,WRITE_END,WRITE_END_q : std_logic;
  signal WRITIF,WRITIF_q : std_logic;
  signal WRITDF,WRITDF_q : std_logic;
  signal CNTI_RST_i,CNTD_RST_i : std_logic;
  signal CNTI_q : natural range 0 to IMEM_SIZE-1;
  signal CNTI_INIT : natural range 0 to ASPC_SIZE/2-1;
  signal CNTD_q : natural range 0 to (IMEM_SIZE+DMEM_SIZE)-1;
  signal CNTD_INIT : natural range 0 to (IMEM_SIZE+DMEM_SIZE)-1;
  signal READ_OP,READ_END : std_logic;
  signal READF,READF_q,READF_q2 : std_logic;
  signal CHKC_OP,CHKD_OP : std_logic;
  signal CHKF,CHKF_q : std_logic;
  signal PASS,PASS_q : std_logic;
  signal DONE,DONE_q : std_logic;
  signal RADR,WADR : std_logic_vector(ALEN-1 downto 0);
  signal CP_WE : std_logic;
  signal CP_RE : std_logic;
  signal CP_ADR: std_logic_vector(17-1 downto 0);
  signal CP_DATI : std_logic_vector(SDLEN-1 downto 0);
  signal CP_DATO : std_logic_vector(SDLEN-1 downto 0);
  signal CNTR_END,CNTR_INC : std_logic;
  signal CNTR_q : natural range 0 to 200-1;
  signal ERROR : std_logic := '0';
  signal ERR_CNT_q : natural := 0;
  signal MSK_CHK,MSK_CHK_q : std_logic_vector(4-1 downto 0);
  signal RTE : std_logic := RUN_TO_END;
 
  signal STI_ROM_ADR_q : unsigned(13-1 downto 0);
  signal STI_ROM_Q : std_logic_vector(SDLEN*2-1 downto 0);
  signal STO_ROM_ADR_q,STO_ROM_ADR_q2 : unsigned(4-1 downto 0);
  signal STO_ROM_Q : std_logic_vector(SDLEN*2+4-1 downto 0);
  signal DAT4_CHK : std_logic_vector(SDLEN-1 downto 0);
 
begin
 
  ---------------------------------------------------
  -- Self-test module operations
  ---------------------------------------------------
 
  -- This self-test module performs the following
  -- operations:
  -- 1) Write core instruction memory to all-zero
  -- 2) Write test program (instruction + data) from
  -- ROM to core memory.
  -- 3) Configure core halt module to stop at
  -- HALT_ADR1 address and then starts test program
  -- execution.
  -- 4) When program execution stops, read memory
  -- locations holding Dhrystone loop single-iteration
  -- results and compare their content to ROM check
  -- data, counting errors (if present).
  -- 5) Resume test program execution.
 
  -- Steps 4 and 5 are repeated CNTR_MAX times, then
  -- if RTE (Run-To-End) flag is set, test program
  -- execution restarts and run until completion
  -- without further stops, otherwise test program
  -- execution remains stopped indefinitely.
 
  ---------------------------------------------------
  -- Test control FSM
  ---------------------------------------------------
 
  -- MRV01HC register
  -- bit  | description
  -- 0    | haltstate (R)
  -- 1    | start (W)
  -- 2    | resume (W)
  -- 3    | halt unconditionally (W)
  -- 4    | halt on break (R/W)
  -- 5    | halt on address (R/W)
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        DONE_q <= '0';
        XS_q <= XS_IDLE;
      else
        DONE_q <= DONE;
        XS_q <= XS;
      end if;
    end if;
  end process;
 
  process(XS_q,WRITE_END_q,CP_DATO,READ_END,CNTR_END,RTE)
  begin
 
    CNTI_RST_i <= '0';
    CNTD_RST_i <= '0';
    WRITE_OP <= '0';
    READ_OP <= '0';
    DONE <= '0';
    CP_RE <= '0';
    CP_WE <= '0';
    CP_ADR <= '1' & X"0000";
    CP_DATI <= X"00000000";
    CNTR_INC <= '0';
 
    case XS_q is
 
	 -- Do nothing while reset is on
      when XS_IDLE =>
        XS <= XS_INIT1;
 
	 -- Reset instruction/data counters
      when XS_INIT1 =>
        CNTI_RST_i <= '1';
        CNTD_RST_i <= '1';
        XS <= XS_INIT2;
 
	 -- Start writing input data & test program to core memory
      when XS_INIT2 =>
        -- assert write operation start flag
        WRITE_OP <= '1';
        XS <= XS_WRITE;      
 
	 -- Write core memory
      when XS_WRITE =>
        -- check write operation end flag...
        if(WRITE_END_q = '1') then
          -- write operation completed
          XS <= XS_WRTCP1;
        else
          -- write operation still in progress
          XS <= XS_WRITE;
        end if;
 
      -- Write control port
      when XS_WRTCP1 =>
        -- set halt address to HALT_ADR1
        CP_WE <= '1';
        CP_ADR <= "100" & to_std_logic_vector(MRV01HA_ADR) & "00";
        CP_DATI <= to_std_logic_vector(HALT_ADR1);
        XS <= XS_WRTCP2;
 
      -- Write control port
      when XS_WRTCP2 =>
        -- start execution and enable halt-on-address
        CP_WE <= '1';    
        CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
        -- start = 1, haltoadr = 1
        CP_DATI <= X"00000022";
        XS <= XS_WAIT5;
 
	 -- Check loop iteration results
      when XS_READ =>
        -- check read operation end flag...
        if(READ_END = '1') then
          -- check if run count has reached end value
          if(CNTR_END = '1') then
            -- stop test
            XS <= XS_STOP;
          else
            -- increment run count
            CNTR_INC <= '1';
            -- start next test run
            XS <= XS_WRTCP6;
          end if;
        else
          XS <= XS_READ;
        end if;
 
      -- Write control port
      when XS_WRTCP6 =>
        -- start execution and enable halt-on-address
        CP_WE <= '1';    
        CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
        -- start = 1, resume = 1, haltoadr = 1
        CP_DATI <= X"00000026";
        XS <= XS_WAIT5;
 
      -- Give haltstate time to be updated.
      when XS_WAIT5 =>
        CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
        XS <= XS_WAIT6;
 
      -- Give haltstate time to be updated.
      when XS_WAIT6 =>
        CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
        XS <= XS_RUN3;
 
      -- Run test program
      when XS_RUN3 =>
        -- wait for execution to halt, polling
        -- MRV01HC register
        if(CP_DATO(0) = '1') then
          -- check if there're data to be read from
          -- core memory...
          if(CNTD_R_INIT > 0) then
            -- assert read operation start flag
            READ_OP <= '1';
            XS <= XS_READ;
          -- check if run count has reached end value
          elsif(CNTR_END = '1') then
            -- check if Run-To-End flag is asserted...
            if(RTE = '1') then
              -- re-start test
              XS <= XS_WRTCP7;
            else
              -- stop test
              XS <= XS_STOP;
            end if;
          else
            -- increment run count
            CNTR_INC <= '1';
            -- start next test run
            XS <= XS_WRTCP6;
          end if;
        else
          -- keep register MTV01HC selected for read
          CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
          XS <= XS_RUN3;
        end if;
 
      -- write control port
      when XS_WRTCP7 =>
        -- set halt address
        CP_WE <= '1';
        CP_ADR <= "100" & to_std_logic_vector(MRV01HA_ADR) & "00";
        CP_DATI <= to_std_logic_vector(HALT_ADRF);
        XS <= XS_WRTCP8;
 
      -- write control port
      when XS_WRTCP8 =>
        -- start execution and enable halt-on-address
        CP_WE <= '1';    
        CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
        -- start = 1, resume = 1, haltoadr = 1
        CP_DATI <= X"00000026";
        XS <= XS_WAIT7;
 
      -- Give haltstate time to be updated.
      when XS_WAIT7 =>
        -- keep register MTV01HC selected for read
        CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
        XS <= XS_WAIT8;
 
      -- Give haltstate time to be updated.
      when XS_WAIT8 =>
        -- keep register MTV01HC selected for read
        CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
        XS <= XS_RUN4;
 
      -- Run test program to end
      when XS_RUN4 =>
        -- wait for execution to halt, polling
        -- MRV01HC register
        if(CP_DATO(0) = '1') then
          -- stop test
          XS <= XS_STOP;
        else
          -- keep register MTV01HC selected for read
          CP_ADR <= "100" & to_std_logic_vector(MRV01HC_ADR) & "00";
          XS <= XS_RUN4;
        end if;
 
      when XS_STOP =>
        -- assert done flag
        DONE <= '1';
        XS <= XS_STOP;
 
      when others =>
        XS <= XS_IDLE;
 
    end case;
  end process;
 
  ---------------------------------------------------
  -- Write FSM
  ---------------------------------------------------
 
  -- This FSM controls writing of test program (read
  -- from STI_ROM memory) into RV01 core internal memory.
 
  -- The FRM writes core memory in two steps: during
  -- first step (FSM in state WS_WRITI) instruction
  -- memory is written to all-zero, while during second
  -- step (FSM in state WS_WRITD) the test program
  -- (instructions + data) is loaded into memory (thus
  -- overwriting some of the memory locations set to
  -- zero in the first step).
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        WRITIF_q <= '0';
        WRITDF_q <= '0';
        WRITE_END_q <= '0';
        WS_q <= WS_IDLE;
      else
        WRITIF_q <= WRITIF;
        WRITDF_q <= WRITDF;
        WRITE_END_q <= WRITE_END;
        WS_q <= WS;
      end if;
    end if;
  end process;
 
  process(WS_q,WRITE_OP,CNTI_q,CNTD_q)
  begin
    WRITIF <= '0';
    WRITDF <= '0';
    WRITE_END <= '0';
    case WS_q is
 
      when WS_IDLE =>
        if(WRITE_OP = '1') then
          WRITIF <= '1';
          WS <= WS_WRITI;
        else
          WS <= WS_IDLE;
        end if;
 
      when WS_WRITI =>
        if(CNTI_q = 0) then
          WRITIF <= '1';
          WS <= WS_WAIT3;
        else
          WRITIF <= '1';
          WS <= WS_WRITI;
        end if;
 
      when WS_WAIT3 =>
        WRITDF <= '1';
        WS <= WS_WRITD;
 
      when WS_WRITD =>
        if(CNTD_q = 0) then
          WS <= WS_WAIT1;
        else
          WRITDF <= '1';
          WS <= WS_WRITD;
        end if;
 
      when WS_WAIT1 =>
        WS <= WS_WAIT2;
 
      when WS_WAIT2 =>
        WRITE_END <= '1';
        WS <= WS_IDLE;
 
      when others =>
        WS <= WS_IDLE;
    end case;
  end process;
 
  -- Data port write-enable flag
 
  DP_WE <= WRITIF_q or WRITDF_q;
 
  ---------------------------------------------------
  -- Read input data from RAM
  ---------------------------------------------------
 
  -- Whole instructions memory is written to all-0
  -- pattern, then instructions and data are written
  -- over, reading them from STI ROM memory.
 
  -- STI ROM address generator
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        STI_ROM_ADR_q <= (others => '0');
      elsif(WRITDF = '1') then
        STI_ROM_ADR_q <= STI_ROM_ADR_q + 1;
      end if;
    end if;
  end process;
 
  -- Self-Test Input (STI) ROM
 
  U_STIROM : RV01_STI_ROM
    port map(
      CLK_i => CLK_i,
      A_i => STI_ROM_ADR_q,
      Q_o => STI_ROM_Q
    );
 
  -- Write address mux, when writing instruction
  -- memory to all-zero, address is generated 
  -- through a counter, while when writing
  -- test program, bott address and data are
  -- supplied by STI ROM.
 
  process(WRITIF,CNTI_q,STI_ROM_Q)
  begin
    if(WRITIF = '1') then
      -- address generated through counter
      WADR <= to_std_logic_vector(to_unsigned((IMEM_SIZE-1-CNTI_q)*4,ALEN));
      -- all-zero data
      DP_DATI <= (others => '0');
    else
      -- data and address supplied by STI ROM output
      WADR <= STI_ROM_Q(SDLEN*2-1 downto SDLEN);
      DP_DATI <= STI_ROM_Q(SDLEN-1 downto 0);
    end if;
  end process;
 
  ---------------------------------------------------
  -- Read (check data) FSM
  ---------------------------------------------------
 
  -- This FSM control read operations from core
  -- memory.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        READF_q <= '0';
        RS_q <= RS_IDLE;
      else
        READF_q <= READF;
        RS_q <= RS;
      end if;
    end if;
  end process;
 
  process(RS_q,READ_OP,CNTD_q)
  begin
    READF <= '0';
    READ_END <= '0';
    case RS_q is
 
      when RS_IDLE =>
        if(READ_OP = '1') then
          READF <= '1';
          RS <= RS_READ;
        else
          RS <= RS_IDLE;
        end if;
 
      when RS_READ =>
        if(CNTD_q = 0) then
          RS <= RS_WAIT1;
        else
          READF <= '1';
          RS <= RS_READ;
        end if;
 
      when RS_WAIT1 =>
        RS <= RS_WAIT2;
 
      when RS_WAIT2 =>
        READ_END <= '1';
        RS <= RS_IDLE;
 
      when others =>
        RS <= RS_IDLE;
 
    end case;
  end process;
 
  -- delay write flag by 1 cycle.
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        READF_q2 <= '0';
      else
        READF_q2 <= READF_q;
      end if;
    end if;
  end process;
 
  ---------------------------------------------------
  -- Read output/check data from ROM
  ---------------------------------------------------
 
  -- STO ROM address generator
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1' or READ_OP = '1') then
        STO_ROM_ADR_q <= (others => '0');
      elsif(READF = '1') then
        STO_ROM_ADR_q <= STO_ROM_ADR_q + 1;
      end if;
      STO_ROM_ADR_q2 <= STO_ROM_ADR_q;
    end if;
  end process;
 
  -- Self-Test Output (STO) ROM
 
  U_STOROM : RV01_STO_ROM
    port map(
      CLK_i => CLK_i,
      A_i => STO_ROM_ADR_q,
      Q_o => STO_ROM_Q
    );
 
  -- STO ROM output consists of 3 bit fields:
  -- [3:0] byte check mask.
  -- [35:4] check data.
  -- [67:36] read address.
 
  -- Byte check mask
  MSK_CHK <= STO_ROM_Q(4-1 downto 0);
 
  -- Check data don't change across loop iterations,
  -- except for 4th word, which is dependent from the
  -- current run count. 
 
  DAT4_CHK <= to_std_logic_vector(to_signed(STO_ROM_Q(SDLEN+4-1 downto 4)) + CNTR_q);
 
  -- Check data (4th word is set to DAT4_CHK value)
  DP_DAT_CHK <= 
    DAT4_CHK when (STO_ROM_ADR_q2 = 4) else STO_ROM_Q(SDLEN+4-1 downto 4);
 
  -- Memory read address
  RADR <= STO_ROM_Q(SDLEN*2+4-1 downto SDLEN+4);
 
  -- Data from core memory is available with 1-cycle delay,
  -- save check data and byte mask for comparison.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      DP_DAT_CHK_q <= DP_DAT_CHK;
      MSK_CHK_q <= MSK_CHK; 
    end if;
  end process;
 
  ---------------------------------------------------
  -- Compare output and check data
  ---------------------------------------------------
 
  -- Compare data read from core memory locations
  -- storing Dhrystone core loop results to check
  -- data stored into ROM, counting errors.
 
  -- Note: comparison accounts for the byte check mask
  -- described above.
 
  process(DP_DATO,DP_DAT_CHK_q,MSK_CHK_q)
    variable B : std_logic_vector(8-1 downto 0);
    variable B_CHK : std_logic_vector(8-1 downto 0);
    variable ERRV : std_logic_vector(4-1 downto 0);
  begin
    for k in 0 to 4-1 loop
      -- get k-th byte from actual and expected results
      B := DP_DATO((k+1)*8-1 downto k*8);
      B_CHK := DP_DAT_CHK_q((k+1)*8-1 downto k*8);
      -- compare them
      if(B /= B_CHK) then
        ERRV(k) := MSK_CHK_q(k);
      else
        ERRV(k) := '0';
      end if;
    end loop;
    -- get overall error flag
    if(ERRV = "0000") then
      ERROR <= '0';
    else 
      ERROR <= '1';
     end if;
  end process;
 
  -- Error count register
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        ERR_CNT_q <= 0;
      elsif(READF_q2 = '1' and ERROR = '1') then
        ERR_CNT_q <= ERR_CNT_q + 1;
      end if;
    end if;
  end process;
 
  -- Test pass flag register (test is a pass
  -- if error count is zero when test completes)
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        PASS_q <= '0';
      elsif(DONE = '1' and ERR_CNT_q = 0) then
        PASS_q <= '1';
      end if;
    end if;
  end process;
 
  PASS_o <= PASS_q;
  DONE_o <= DONE_q;
 
  ---------------------------------------------------
  -- Read/Write word (down-) counter
  ---------------------------------------------------
 
  -- This counter counts the data/instructions words
  -- to be read from memory, or written to memory.
 
  -- Data word start count
  CNTD_INIT <= 
    CNTD_W_INIT when (WRITDF_q = '0' and WRITDF = '1') else
    CNTD_R_INIT;
 
  -- Instruction word start count
  CNTI_INIT <= IMEM_SIZE-1;
 
  -- Instruction word down-counter
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(CNTI_RST_i = '1') then
        CNTI_q <= CNTI_INIT;
      elsif(CNTI_q > 0) then
        CNTI_q <= CNTI_q - 1;
      end if;
    end if;
  end process;
 
  -- Data word down-counter
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(CNTD_RST_i = '1') then
        CNTD_q <= 0;
      elsif(
        (WRITDF_q = '0' and WRITDF = '1') or 
        (READF_q = '0' and READ_OP = '1')
      ) then
        CNTD_q <= CNTD_INIT;
      elsif(CNTD_q > 0) then
        CNTD_q <= CNTD_q - 1;
      end if;
    end if;
  end process;
 
  ---------------------------------------------------
  -- Run counter
  ---------------------------------------------------
 
  -- This counter counts Dhrystone core loop iterations,
  -- when count reaches CNTR_MAX-1 value, CNTR_END flag
  -- is set to '1'.
 
  process(CLK_i)
  begin
    if(CLK_i = '1' and CLK_i'event) then
      if(RST_i = '1') then
        CNTR_q <= 0;
      elsif(CNTR_INC = '1' and CNTR_q < CNTR_MAX - 1) then
        CNTR_q <= CNTR_q + 1;
      end if;
    end if;
  end process;
 
  CNTR_END <= '1' when (CNTR_q = CNTR_MAX - 1) else '0';
 
  ---------------------------------------------------
  -- RV01 core instance
  ---------------------------------------------------
 
  DP_ADR <= WADR when (WRITIF_q = '1' or WRITDF_q = '1') else RADR;
 
  U_RVTOP : RV01_TOP_NOHOST
    generic map(
      -- synthesis translate_off
      ST_FILE => "NONE",
      WB_FILE => "NONE",
      -- synthesis translate_on
      IMEM_SIZE => IMEM_SIZE,
      DMEM_SIZE => DMEM_SIZE,
      IOMEM_SIZE => IOMEM_SIZE,
      IMEM_SIZE_PO2 => IMEM_SIZE_PO2,
      DMEM_SIZE_PO2 => DMEM_SIZE_PO2,
      IMEM_LOWM => IMEM_LOWM,
      BHT_SIZE => BHT_SIZE,
      EI_SRC_CNT => EI_SRC_CNT,
      EI_TRIG_TYPE => EI_TRIG_TYPE,
      EI_REQ_MAXCNT => EI_REQ_MAXCNT,
      CFG_FLAGS => "00000000"&CFG_FLAGS,
      SIMULATION_ONLY => '0'
    )
    port map(
      CLK_i => CLK_i,
      RST_i => RST_i,
      EI_REQ_i => EI_REQ,
      DP_WE_i => DP_WE,
      DP_ADR_i => DP_ADR,
      DP_DAT_i => DP_DATI,
      CP_RE_i => CP_RE,
      CP_WE_i => CP_WE,
      CP_ADR_i => CP_ADR,
      CP_DAT_i => CP_DATI,
 
      DP_DAT_o => DP_DATO,
      CP_DAT_o => CP_DATO
    );
 
end ARC;

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.