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

Subversion Repositories xgate

[/] [xgate/] [trunk/] [rtl/] [verilog/] [xgate_jtag.v] - Rev 88

Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////////
//
//  XGATE Coprocessor - XGATE JTAG Module
//
//  Author: Robert Hayes
//          rehayes@opencores.org
//
//  Downloaded from: http://www.opencores.org/projects/xgate.....
//
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011, Robert Hayes
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Supplemental terms.
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY Robert Hayes ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL Robert Hayes 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.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
////////////////////////////////////////////////////////////////////////////////
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
 
// -----------------------------------------------------------------------------
// JTAG TAP Controller
// -----------------------------------------------------------------------------
module xgate_jtag #(parameter IR_BITS = 4)    // Number of Instruction Register Bits
  (
    output  jtag_tdo,      // JTAG Serial Output Data
    output  jtag_tdo_en,   // JTAG Serial Output Data tri-state enable
 
    input   jtag_tdi,      // JTAG Serial Input Data
    input   jtag_clk,      // JTAG Test clock
    input   jtag_reset_n,  // JTAG Async reset signal
    input   jtag_tms,      // JTAG Test Mode Select
 
    output  extest,        // JTAG Command for I/O control
    output  clamp,         // JTAG Command for I/O control
    output  highz,         // JTAG Command for I/O control
    output  force_pul_lo,  // JTAG Command for I/O control
    output  force_pul_hi,  // JTAG Command for I/O control
 
    output  sel_bsd,       // JTAG select the boundary scan register
    output  sel_udi_1,     // JTAG select the udi_1 (testmode control) register
 
    output  capture_clk,   // Shift and input capture clock
    output  update_clk,    // Load holding register
    output  capture_dr,    // Enable shift/capture register input loading,
    output  update_dr,     // Enable holding register input loading
    output  shift_dr,      // Select eather shift mode or parallel capture mode
    input   bsd_so,        // Serial data input from boundary scan chain
    input   user1_so       // Serial data input from user register
  );
 
 
  wire [3:0] jtag_state;
  wire [3:0] next_jtag_state;
 
  wire [IR_BITS-1:0] ir_reg;
 
 
 
  // Define clocks here, future enhansment would be to add scan clock mux
  // update_clk is output I/O clock and control register capture clock
  // capture_clock is input I/O clock and shifting clock
  assign update_clk  = !jtag_clk;
  assign capture_clk = jtag_clk;
 
  // ---------------------------------------------------------------------------
  xgate_jtag_sm
    jtag_sm(
      .jtag_state(jtag_state),
      .next_jtag_state(next_jtag_state),
      .update_ir(update_ir),
      .capture_ir(capture_ir),
      .shift_ir(shift_ir),
      .update_dr(update_dr),
      .capture_dr(capture_dr),
      .shift_dr(shift_dr),
      .capture_clk(capture_clk),
      .jtag_reset_n(jtag_reset_n),
      .jtag_tms(jtag_tms)
    );
 
  // ---------------------------------------------------------------------------
  xgate_jtag_ir #(.IR_BITS(IR_BITS))
    jtag_ir(
      .ir_reg(ir_reg),
      .ir_so(ir_so),
      .capture_clk(capture_clk),
      .update_clk(update_clk),
      .update_ir(update_ir),
      .capture_ir(capture_ir),
      .shift_ir(shift_ir),
      .jtag_tdi(jtag_tdi),
      .jtag_reset_n(jtag_reset_n)
    );
 
  // ---------------------------------------------------------------------------
  xgate_instr_decode #(.IR_BITS(IR_BITS))
    decoder(
      .bypass(bypass),
      .clamp(clamp),
      .highz(highz),
      .extest(extest),
      .force_pul_lo(force_pul_lo),
      .force_pul_hi(force_pul_hi),
      .sample(sample),
      .idcode(idcode),
      .usercode(usercode),
      .udi_1(udi_1),
 
      .sel_bypass(sel_bypass),
      .sel_bsd(sel_bsd),
      .sel_id(sel_id),
      .sel_udi_1(sel_udi_1),
 
      .ir_reg(ir_reg)
    );
 
  // ---------------------------------------------------------------------------
  xgate_bypass_reg
    tdi_bypass(
      .bypass_so(bypass_so),
 
      .jtag_tdi(jtag_tdi),
      .capture_clk(capture_clk),
      .jtag_reset_n(jtag_reset_n)
    );
 
  // ---------------------------------------------------------------------------
  xgate_id_reg
    chip_id(
      .id_so(id_so),
 
      .jtag_tdi(jtag_tdi),
      .capture_clk(capture_clk),
      .capture_dr(capture_dr),
      .shift_dr(shift_dr),
      .idcode(idcode),
      .usercode(usercode),
      .jtag_reset_n(jtag_reset_n)
    );
 
  // ---------------------------------------------------------------------------
  xgate_tdo_mux
    tdo_out(
      .sel_bypass(sel_bypass),
      .sel_bsd(sel_bsd),
      .sel_id(sel_id),
      .sel_udi_1(sel_udi_1),
 
      .bypass_so(bypass_so),
      .bsd_so(bsd_so),
      .user1_so(user1_so),
      .id_so(id_so),
      .ir_so(ir_so),
 
      .shift_dr(shift_dr),
      .shift_ir(shift_ir),
      .update_clk(update_clk),
      .jtag_reset_n(jtag_reset_n),
 
      .jtag_tdo(jtag_tdo),
      .jtag_tdo_en(jtag_tdo_en)
    );
 
endmodule  // xgate_jtag
 
 
// -----------------------------------------------------------------------------
// JTAG TAP State Machine
// -----------------------------------------------------------------------------
module xgate_jtag_sm
  (
    output reg [3:0] jtag_state,        // JTAG State
    output reg [3:0] next_jtag_state,   // Pseudo Register for JTAG next state logic
 
    output           update_ir,
    output           capture_ir,
    output           shift_ir,
 
    output           update_dr,
    output           capture_dr,
    output           shift_dr,
 
    input            capture_clk,   // JTAG Test clock
    input            jtag_reset_n,  // JTAG Async reset signal
    input            jtag_tms       // JTAG Test Mode Select
  );
 
parameter RESET         = 4'hF,
          RUN_TEST_IDLE = 4'hC,
          SEL_DR_SCAN   = 4'h7,
          CAPTURE_DR    = 4'h6,
          SHIFT_DR      = 4'h2,
          EXIT1_DR      = 4'h1,
          PAUSE_DR      = 4'h3,
          EXIT2_DR      = 4'h0,
          UPDATE_DR     = 4'h5,
          SEL_IR_SCAN   = 4'h4,
          CAPTURE_IR    = 4'hE,
          SHIFT_IR      = 4'hA,
          EXIT1_IR      = 4'h9,
          PAUSE_IR      = 4'hB,
          EXIT2_IR      = 4'h8,
          UPDATE_IR     = 4'hD;
 
  assign update_ir  = jtag_state == UPDATE_IR;
  assign capture_ir = jtag_state == CAPTURE_IR;
  assign shift_ir   = jtag_state == SHIFT_IR;
 
  assign update_dr  = jtag_state == UPDATE_DR;
  assign capture_dr = jtag_state == CAPTURE_DR;
  assign shift_dr   = jtag_state == SHIFT_DR;
 
 
  // Define the JTAG State Register
  always @(posedge capture_clk or negedge jtag_reset_n)
    if (!jtag_reset_n)
      jtag_state <= RESET;
    else
      jtag_state <= next_jtag_state;
 
  // Define the JTAG State Transitions
  always @*
    begin
      case(jtag_state)
        RESET:
          next_jtag_state = jtag_tms ? RESET : RUN_TEST_IDLE;
        RUN_TEST_IDLE:
          next_jtag_state = jtag_tms ? SEL_DR_SCAN : RUN_TEST_IDLE;
        SEL_DR_SCAN:
          next_jtag_state = jtag_tms ? SEL_IR_SCAN : CAPTURE_DR;
        CAPTURE_DR:
          next_jtag_state = jtag_tms ? EXIT1_DR : SHIFT_DR;
        SHIFT_DR:
          next_jtag_state = jtag_tms ? EXIT1_DR : SHIFT_DR;
        EXIT1_DR:
          next_jtag_state = jtag_tms ? UPDATE_DR : PAUSE_DR;
        PAUSE_DR:
          next_jtag_state = jtag_tms ? EXIT2_DR : PAUSE_DR;
        EXIT2_DR:
          next_jtag_state = jtag_tms ? UPDATE_DR : SHIFT_DR;
        UPDATE_DR:
          next_jtag_state = jtag_tms ? SEL_DR_SCAN : RUN_TEST_IDLE;
 
        SEL_IR_SCAN:
          next_jtag_state = jtag_tms ? RESET : CAPTURE_IR;
        CAPTURE_IR:
          next_jtag_state = jtag_tms ? EXIT1_IR : SHIFT_IR;
        SHIFT_IR:
          next_jtag_state = jtag_tms ? EXIT1_IR : SHIFT_IR;
        EXIT1_IR:
          next_jtag_state = jtag_tms ? UPDATE_IR : PAUSE_IR;
        PAUSE_IR:
          next_jtag_state = jtag_tms ? EXIT2_IR : PAUSE_IR;
        EXIT2_IR:
          next_jtag_state = jtag_tms ? UPDATE_IR : SHIFT_IR;
        UPDATE_IR:
          next_jtag_state = jtag_tms ? SEL_DR_SCAN : RUN_TEST_IDLE;
      endcase
    end
 
endmodule  // xgate_jtag_sm
 
 
// -----------------------------------------------------------------------------
// JTAG TAP Instruction Register
// -----------------------------------------------------------------------------
module xgate_jtag_ir #(parameter IR_BITS = 4)    // Number of Instruction Register Bits
  (
    output reg [IR_BITS-1:0] ir_reg,
    output                   ir_so,    // IR shift out
 
    input            update_ir,
    input            capture_ir,
    input            shift_ir,
 
    input            jtag_tdi,      // JTAG Serial Input Data
    input            capture_clk,   // JTAG Test clock
    input            update_clk,
    input            jtag_reset_n   // JTAG Async reset signal
  );
 
  reg [IR_BITS-1:0] ir_shift_reg;
 
  assign ir_so = ir_shift_reg[0];
 
  // JTAG Instruction Shift Register
  always @(posedge capture_clk or negedge jtag_reset_n)
    if (!jtag_reset_n)
      ir_shift_reg <= 0;
    else if (capture_ir)
      ir_shift_reg <= ir_reg;
    else if (shift_ir)
      ir_shift_reg <= {jtag_tdi, ir_shift_reg[(IR_BITS-1):1]};
 
  // JTAG Instruction Register
  always @(posedge update_clk or negedge jtag_reset_n)
    if (!jtag_reset_n)
      ir_reg <= {IR_BITS{1'b1}};  // Make the default instruction BYPASS
    else if (update_ir)
      ir_reg <= ir_shift_reg;
 
endmodule  // xgate_jtag_ir
 
 
// -----------------------------------------------------------------------------
// JTAG Bypass Register
// -----------------------------------------------------------------------------
module xgate_bypass_reg
  (
    output reg       bypass_so,
 
    input            jtag_tdi,      // JTAG Serial Input Data
    input            capture_clk,   // JTAG Test clock
    input            jtag_reset_n   // JTAG Async reset signal
  );
 
  // JTAG Bypass Register
  always @(posedge capture_clk or negedge jtag_reset_n)
    if (!jtag_reset_n)
      bypass_so <= 0;
    else
      bypass_so <= jtag_tdi;
 
endmodule  // xgate_bypass_reg
 
 
// -----------------------------------------------------------------------------
// JTAG ID Register
// -----------------------------------------------------------------------------
module xgate_id_reg #(parameter NUM_BITS = 32)
  (
    output id_so,
 
    input  jtag_tdi,      // JTAG Serial Input Data
    input  capture_clk,
    input  capture_dr,
    input  shift_dr,
    input  idcode,
    input  usercode,
    input  jtag_reset_n   // JTAG Async reset signal
  );
 
  parameter user_code_val  = 32'ha596_c3f0;
  parameter version        = 4'h1;
  parameter part_num       = 16'h1105;
  parameter manufacture_id = 11'h00f;
 
  reg  [NUM_BITS-1:0] id_shifter;
 
  wire [NUM_BITS-1:0] jtag_id = {version, part_num, manufacture_id, 1'b1};
  wire [NUM_BITS-1:0] sel_mux = ({NUM_BITS{idcode}} & jtag_id) | ({NUM_BITS{usercode}} & user_code_val);
  wire [NUM_BITS-1:0] din_mux = shift_dr ? {jtag_tdi, id_shifter[(NUM_BITS-1):1]} : jtag_id;
 
  wire capture_en = (idcode || usercode) && (capture_dr || shift_dr);
 
  // JTAG Id Register
  always @(posedge capture_clk or negedge jtag_reset_n)
    if (!jtag_reset_n)
      id_shifter <= 0;
    else if (capture_en)
      id_shifter <= din_mux;
 
  assign id_so = id_shifter[0];
 
endmodule  // xgate_id_reg
 
 
// -----------------------------------------------------------------------------
// JTAG Instruction decoder of the IR Register
// -----------------------------------------------------------------------------
module xgate_instr_decode #(parameter IR_BITS = 4)    // Number of Instruction Register Bits
  (
    output reg bypass,
    output reg clamp,
    output reg highz,
    output reg extest,
    output reg force_pul_lo,
    output reg force_pul_hi,
    output reg sample,
    output reg idcode,
    output reg usercode,
    output reg udi_1,
 
    output     sel_bypass,
    output     sel_bsd,
    output     sel_id,
    output     sel_udi_1,
 
    input  [IR_BITS-1:0] ir_reg
  );
 
  assign sel_bypass = bypass || clamp || highz || force_pul_lo || force_pul_hi;
  assign sel_bsd = extest || sample;
  assign sel_id = idcode || usercode;
  assign sel_udi_1 = udi_1;
 
  always @*
    begin
      bypass     = 0;
      clamp      = 0;
      highz      = 0;
      extest     = 0;
      force_pul_lo = 0;
      force_pul_hi = 0;
      sample     = 0;
      idcode     = 0;
      usercode   = 0;
      udi_1      = 0;
      casez (ir_reg)
        4'b0110: clamp = 1;
        4'b0101: highz = 1;
        4'b0000: extest = 1;
        4'b1001: force_pul_lo = 1;
        4'b1010: force_pul_hi = 1;
        4'b0111: sample = 1;
        4'b0001: idcode = 1;
        4'b0011: usercode = 1;
        4'b1100: udi_1 = 1;
        default: bypass = 1;
      endcase
    end
 
endmodule  // xgate_instr_decode
 
 
// -----------------------------------------------------------------------------
// JTAG Test Data Output mux
// -----------------------------------------------------------------------------
module xgate_tdo_mux
  (
    input  sel_bypass,
    input  sel_bsd,
    input  sel_id,
    input  sel_udi_1,
 
    input  bypass_so,
    input  bsd_so,
    input  id_so,
    input  user1_so,
    input  ir_so,
 
    input  shift_dr,
    input  shift_ir,
    input  update_clk,
    input  jtag_reset_n,
 
    output reg jtag_tdo,
    output reg jtag_tdo_en
  );
 
  wire bypass_gate = shift_dr && sel_bypass && bypass_so;
  wire bsd_gate    = shift_dr && sel_bsd    && bsd_so;
  wire id_gate     = shift_dr && sel_id     && id_so;
  wire udi_1_gate  = shift_dr && sel_udi_1  && user1_so;
  wire ir_gate     = shift_ir && ir_so;
 
  wire jtag_tdo_mux = bypass_gate || bsd_gate || id_gate || udi_1_gate || ir_gate;
 
  // JTAG TDO Retiming Register
  always @(posedge update_clk or negedge jtag_reset_n)
    if (!jtag_reset_n)
      jtag_tdo <= 0;
    else
      jtag_tdo <= jtag_tdo_mux;
 
  // JTAG Output Enable Register
  always @(posedge update_clk or negedge jtag_reset_n)
    if (!jtag_reset_n)
      jtag_tdo_en <= 0;
    else
      jtag_tdo_en <= shift_dr || shift_ir;
 
endmodule  // xgate_tdo_mux
 
 
// -----------------------------------------------------------------------------
// Boundary Scan Cell #7
// -----------------------------------------------------------------------------
module bc_7
  (
    input      capture_clk,  // Shift and input capture clock
    input      update_clk,   // Load holding register
    input      capture_en,   // Enable shift/capture register parallel input loading,
    input      update_en,    // Enable holding register input loading
    input      shift_dr,     // Select eather shift mode or parallel capture mode
    input      mode,         // Select test mode or mission mode control of pad
    input      si,           // Serial data input
    input      pin_input,    // Mission mode input from pin
    input      control_out,  // Signal from bc_2 module controlling output enable pin
    input      output_data,  // mission mode data in from core
    input      reset_n,      // reset
 
    output     data_out,     // Final data to pad
    output reg so            // Serial data out
  );
 
  reg data_reg;
 
  // Shift register
  always @(posedge capture_clk or negedge reset_n)
    if (!reset_n)
      so <= 0;
    else if (capture_en)
      so <= shift_dr ? si : ((!control_out || mode) ? pin_input : output_data);
 
  // Holding register
  always @(posedge update_clk or negedge reset_n)
    if (!reset_n)
      data_reg <= 0;
    else if (update_en)
      data_reg <= so;
 
  assign data_out = mode ? data_reg : output_data;
 
endmodule  // bc_7
 
 
// -----------------------------------------------------------------------------
// Boundary Scan Cell #2
// -----------------------------------------------------------------------------
module bc_2
  (
    input      capture_clk,  // Shift and input capture clock
    input      update_clk,   // Load holding register
    input      capture_en,   // Enable shift/capture register parallel input loading
    input      update_en,    // Enable holding register input loading
    input      shift_dr,     // Select eather shift mode or parallel capture mode
    input      mode,         // Select test mode or mission mode control of pad
    input      si,           // Serial data input
    input      data_in,      // Mission mode input
    input      reset_n,      // reset
 
    output     data_out,     // Final data to pad
    output reg so            // Serial data out
  );
 
  reg data_reg;
 
  // Shift register
  always @(posedge capture_clk or negedge reset_n)
    if (!reset_n)
      so <= 0;
    else if (capture_en)
      so <= shift_dr ? si : data_out;
 
  // Holding register
  always @(posedge update_clk or negedge reset_n)
    if (!reset_n)
      data_reg <= 0;
    else if (update_en)
      data_reg <= so;
 
  assign data_out = mode ? data_reg : data_in;
 
endmodule  // bc_2
 
 
 

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.