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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [work/] [tb/] [jtag_sim.vhd] - Rev 5

Compare with Previous | Blame | View Log

------------------------------------------------------------------------------
--! @file
--! @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
--! @author    Sergey Khabarov - sergeykhbr@gmail.com
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
library std;
use std.textio.all;
library commonlib;
use commonlib.types_common.all;
use commonlib.types_util.all;
 
entity jtag_sim is 
  generic (
    clock_rate : integer := 10;
    irlen : integer := 4
  ); 
  port (
    rst : in std_logic;
    clk : in std_logic;
    i_test_ena : in std_logic;
    i_test_burst : in std_logic_vector(7 downto 0);
    i_test_addr : in std_logic_vector(31 downto 0);
    i_test_we : in std_logic;
    i_test_wdata : in std_logic_vector(31 downto 0);
    i_tdi  : in std_logic;
    o_tck : out std_logic;
    o_ntrst : out std_logic;
    o_tms : out std_logic;
    o_tdo : out std_logic
  );
end;
 
architecture jtag_sim_rtl of jtag_sim is
 
  type state_type is (test_rst, run_idle, start_ir, select_dr, capture_dr, shift_dr, exit1_dr,
                      pause_dr, exit2_dr, update_dr, select_ir, capture_ir, shift_ir,
                      exit1_ir, pause_ir, exit2_ir, update_ir);
 
  constant ADDR_WIDTH : integer := 32;
  constant DATA_WIDTH : integer := 32;
  constant REG1_LEN : integer := ADDR_WIDTH + 3; -- 3 = 1 bit we field + 2 bits transaction size
  constant REG2_LEN : integer := DATA_WIDTH + 1; -- 1 bulk bit
  constant SHIFT_LEN : integer := irlen + REG1_LEN; -- maximal length
 
  type registers is record
      jtagstate : state_type;
      jtagstatez : state_type;
      burst_cnt : integer;
      shift_reg1 : std_logic_vector(REG1_LEN-1 downto 0);
      shift_reg2 : std_logic_vector(REG2_LEN-1 downto 0);
      shift_reg : std_logic_vector(irlen + REG1_LEN-1 downto 0);
      shift_length : integer;
      clk_rate_cnt : integer;
      is_data : std_logic;
      instr : integer range 1 to 2;
      op_cnt : integer;
      rdata : std_logic_vector(DATA_WIDTH-1 downto 0);
      edge : std_logic;
      ntrst : std_logic;
      tms : std_logic;
  end record;
 
  signal r, rin : registers;
 
begin
 
  comblogic : process(rst, r, i_tdi, i_test_ena, i_test_addr, i_test_we, i_test_wdata)
    variable v : registers;
    variable w_posedge : std_logic;
    variable w_negedge : std_logic;
  begin
     v := r;
     w_posedge := '0';
     w_negedge := '0';
     if r.clk_rate_cnt = (clock_rate - 1) then
         v.clk_rate_cnt := 0;
         v.edge := not r.edge;
         w_posedge := not r.edge;
         w_negedge := r.edge;
     else
         v.clk_rate_cnt := r.clk_rate_cnt + 1;
     end if;
 
     if i_test_ena = '1' and r.jtagstate = run_idle then
        v.burst_cnt := conv_integer(i_test_burst);
        v.shift_reg1(34) := i_test_we;
        v.shift_reg1(33 downto 32) := "10"; -- size: 0=1 byte; 1=hword; 2=word; 3=dword
        v.shift_reg1(31 downto 0) := i_test_addr;
        if i_test_burst = X"00" then
            v.shift_reg2(32) := '0'; -- bulk=0
        else
            v.shift_reg2(32) := '1'; -- bulk=1
        end if;
        v.shift_reg2(31 downto 0) := i_test_wdata;
        v.is_data := '1';
     elsif w_posedge = '1' then
        v.is_data := '0';
     end if;
 
     if w_posedge = '1' then
        v.jtagstatez := r.jtagstate;
 
        case r.jtagstate is
        when test_rst =>
            v.ntrst := '0';
            v.op_cnt := r.op_cnt + 1;
            if r.op_cnt = 3 then
                v.jtagstate := run_idle;
                v.op_cnt := 0;
                v.ntrst := '1';
            end if;
        when run_idle =>
            if r.is_data = '1' then
                v.tms := '1';
                v.instr := 1;
                v.op_cnt := 0;
                v.jtagstate := start_ir;
            end if;
        when start_ir => -- the same as select_dr
            v.tms := '1';
            v.jtagstate := select_ir;
 
        when select_ir =>
            v.tms := '0';
            v.jtagstate := capture_ir;
        when capture_ir =>
            v.tms := '0'; 
            v.op_cnt := 0;
            v.jtagstate := shift_ir;
            if r.instr = 1 then
                v.shift_reg := r.shift_reg1 & conv_std_logic_vector(2, irlen);
                v.shift_length := 35-1;
            else
                v.shift_reg := "00" & r.shift_reg2 & conv_std_logic_vector(3, irlen);
                v.shift_length := 33-1;
            end if;
            v.op_cnt := 0; 
        when shift_ir =>
            v.tms := '0';
            v.op_cnt := r.op_cnt + 1;
            if r.op_cnt = irlen-1 then
                v.tms := '1';
                v.jtagstate := exit1_ir;
            end if;
        when exit1_ir =>
            v.tms := '1';
            v.jtagstate := update_ir;
        when update_ir =>
            v.tms := '1'; 
            v.jtagstate := select_dr;
 
        when select_dr =>
            v.tms := '0';
            v.jtagstate := capture_dr;
        when capture_dr => 
            v.tms := '0'; 
            v.op_cnt := 0; 
            v.jtagstate := shift_dr;
            v.rdata := (others => '0');
        when shift_dr =>
            v.tms := '0';
            v.rdata := i_tdi & r.rdata(DATA_WIDTH-1 downto 1);
            v.op_cnt := r.op_cnt + 1;
            if r.op_cnt = r.shift_length then
                v.tms := '1';
                v.jtagstate := exit1_dr;
            end if;
        when exit1_dr =>
            v.tms := '1';
            v.rdata := i_tdi & r.rdata(DATA_WIDTH-1 downto 1);
            v.jtagstate := update_dr;
        when update_dr =>
            -- TODO: and size == size_bulk
            if r.instr = 2 then
                if r.burst_cnt = 0 then
                    v.tms := '0'; 
                    v.jtagstate := run_idle;
                else
                    v.tms := '1'; 
                    v.jtagstate := start_ir;
                    v.burst_cnt := r.burst_cnt - 1;
                    if r.burst_cnt = 1 then
                        v.shift_reg2(32) := '0'; -- bulk=0
                    end if;
                end if;
            else
                v.tms := '1'; 
                v.instr := 2;
                v.jtagstate := start_ir;
            end if;
        when others =>
        end case;
 
 
        if r.jtagstatez = shift_ir or r.jtagstatez = shift_dr then
            v.shift_reg := '0' & r.shift_reg(SHIFT_LEN-1 downto 1);
        end if;
     end if;
 
     -- Reset
     if rst = '1' then
        v.jtagstate := test_rst;
        v.jtagstatez := test_rst;
        v.clk_rate_cnt := 0;
        v.op_cnt := 0;
        v.is_data := '0';
        v.shift_reg1 := (others => '0');
        v.shift_reg2 := (others => '0');
        v.shift_reg := (others => '0');
        v.burst_cnt := 0;
        v.edge := '0';
        v.ntrst := '0';
        v.tms := '0';
     end if;
 
     rin <= v;
   end process;
 
   o_tdo <= r.shift_reg(0);
   o_tck <= r.edge;
   o_tms <= r.tms;
   o_ntrst <= r.ntrst;
 
 
  procCheck : process (clk)
  begin
    if rising_edge(clk) then
        r <= rin;
    end if;
  end process;
 
end;
 

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.