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

Subversion Repositories adv_debug_sys

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /adv_debug_sys/tags/ADS_RELEASE_1_1_0/Hardware/adv_dbg_if/rtl/verilog
    from Rev 8 to Rev 18
    Reverse comparison

Rev 8 → Rev 18

/adbg_or1k_module.v
0,0 → 1,672
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_or1k_module.v ////
//// ////
//// ////
//// This file is part of the SoC Advanced Debug Interface. ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_or1k_module.v,v $
// Revision 1.2 2009/05/17 20:54:56 Nathan
// Changed email address to opencores.org
//
// Revision 1.1 2008/07/22 20:28:31 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.7 2008/07/11 08:13:29 Nathan
// Latch opcode on posedge, like other signals. This fixes a problem
// when the module is used with a Xilinx BSCAN TAP. Added signals to
// allow modules to inhibit latching of a new active module by the top
// module. This allows the sub-modules to force the top level module
// to ignore the command present in the input shift register after e.g.
// a burst read.
//
 
 
`include "adbg_or1k_defines.v"
 
// Module interface
module adbg_or1k_module (
// JTAG signals
tck_i,
module_tdo_o,
tdi_i,
 
// TAP states
capture_dr_i,
shift_dr_i,
update_dr_i,
 
data_register_i, // the data register is at top level, shared between all modules
module_select_i,
top_inhibit_o,
rst_i,
 
// Interfate to the OR1K debug unit
cpu_clk_i,
cpu_addr_o,
cpu_data_i,
cpu_data_o,
cpu_bp_i,
cpu_stall_o,
cpu_stb_o,
cpu_we_o,
cpu_ack_i,
cpu_rst_o
);
 
// JTAG signals
input tck_i;
output module_tdo_o;
input tdi_i; // This is only used by the CRC module - data_register_i[MSB] is delayed a cycle
 
// TAP states
input capture_dr_i;
input shift_dr_i;
input update_dr_i;
 
input [52:0] data_register_i;
input module_select_i;
output top_inhibit_o;
input rst_i;
 
// WISHBONE master interface
input cpu_clk_i; // 'bus' style interface to SPRs
output [31:0] cpu_addr_o;
input [31:0] cpu_data_i;
output [31:0] cpu_data_o;
output cpu_stb_o;
output cpu_we_o;
input cpu_ack_i;
output cpu_rst_o; // control lines
input cpu_bp_i;
output cpu_stall_o;
 
// Declare inputs / outputs as wires / registers
reg module_tdo_o;
reg top_inhibit_o;
 
 
// Registers to hold state etc.
reg [31:0] address_counter; // Holds address for next Wishbone access
reg [5:0] bit_count; // How many bits have been shifted in/out
reg [15:0] word_count; // bytes remaining in current burst command
reg [3:0] operation; // holds the current command (rd/wr, word size)
reg [31:0] data_out_shift_reg; // parallel-load output shift register
reg [`DBG_OR1K_REGSELECT_SIZE-1:0] internal_register_select; // Holds index of currently selected register
wire [1:0] internal_reg_status; // Holds CPU stall and reset status - signal is output of separate module
 
 
// Control signals for the various counters / registers / state machines
reg addr_sel; // Selects data for address_counter. 0 = data_register_i, 1 = incremented address count
reg addr_ct_en; // Enable signal for address counter register
reg op_reg_en; // Enable signal for 'operation' register
reg bit_ct_en; // enable bit counter
reg bit_ct_rst; // reset (zero) bit count register
reg word_ct_sel; // Selects data for byte counter. 0 = data_register_i, 1 = decremented byte count
reg word_ct_en; // Enable byte counter register
reg out_reg_ld_en; // Enable parallel load of data_out_shift_reg
reg out_reg_shift_en; // Enable shift of data_out_shift_reg
reg out_reg_data_sel; // 0 = BIU data, 1 = internal register data
reg [1:0] tdo_output_sel; // Selects signal to send to TDO. 0 = ready bit, 1 = output register, 2 = CRC match, 3 = CRC shift reg.
reg biu_strobe; // Indicates that the bus unit should latch data and start a transaction
reg crc_clr; // resets CRC module
reg crc_en; // does 1-bit iteration in CRC module
reg crc_in_sel; // selects incoming write data (=0) or outgoing read data (=1)as input to CRC module
reg crc_shift_en; // CRC reg is also it's own output shift register; this enables a shift
reg regsel_ld_en; // Reg. select register load enable
reg intreg_ld_en; // load enable for internal registers
 
 
// Status signals
wire word_count_zero; // true when byte counter is zero
wire bit_count_max; // true when bit counter is equal to current word size
wire module_cmd; // inverse of MSB of data_register_i. 1 means current cmd not for top level (but is for us)
wire biu_ready; // indicates that the BIU has finished the last command
wire burst_instruction; // True when the input_data_i reg has a valid burst instruction for this module
wire intreg_instruction; // True when the input_data_i reg has a valid internal register instruction
wire intreg_write; // True when the input_data_i reg has an internal register write op
wire rd_op; // True when operation in the opcode reg is a read, false when a write
wire crc_match; // indicates whether data_register_i matches computed CRC
wire bit_count_32; // true when bit count register == 32, for CRC after burst writes
 
// Intermediate signals
wire [5:0] word_size_bits; // 8,16, or 32. Decoded from 'operation'
wire [2:0] address_increment; // How much to add to the address counter each iteration
wire [32:0] incremented_address; // value of address counter plus 'word_size'
wire [31:0] data_to_addr_counter; // output of the mux in front of the address counter inputs
wire [15:0] data_to_word_counter; // output of the mux in front of the byte counter input
wire [15:0] decremented_word_count;
wire [31:0] address_data_in; // from data_register_i
wire [15:0] count_data_in; // from data_register_i
wire [3:0] operation_in; // from data_register_i
wire [31:0] data_to_biu; // from data_register_i
wire [31:0] data_from_biu; // to data_out_shift_register
wire [31:0] crc_data_out; // output of CRC module, to output shift register
wire crc_data_in; // input to CRC module, either data_register_i[52] or data_out_shift_reg[0]
wire crc_serial_out;
wire [`DBG_OR1K_REGSELECT_SIZE-1:0] reg_select_data; // from data_register_i, input to internal register select register
wire [31:0] out_reg_data; // parallel input to the output shift register
reg [31:0] data_from_internal_reg; // data from internal reg. MUX to output shift register
wire status_reg_wr;
 
 
/////////////////////////////////////////////////
// Combinatorial assignments
 
assign module_cmd = ~(data_register_i[52]);
assign operation_in = data_register_i[51:48];
assign address_data_in = data_register_i[47:16];
assign count_data_in = data_register_i[15:0];
assign data_to_biu = data_register_i[52:21];
assign reg_select_data = data_register_i[47:(47-(`DBG_OR1K_REGSELECT_SIZE-1))];
 
////////////////////////////////////////////////
// Operation decoder
 
// These are only used before the operation is latched, so decode them from operation_in
assign burst_instruction = (operation_in == `DBG_OR1K_CMD_BWRITE32) | (operation_in == `DBG_OR1K_CMD_BREAD32);
assign intreg_instruction = ((operation_in == `DBG_OR1K_CMD_IREG_WR) | (operation_in == `DBG_OR1K_CMD_IREG_SEL));
assign intreg_write = (operation_in == `DBG_OR1K_CMD_IREG_WR);
 
// These are constant, the CPU module only does 32-bit accesses
assign word_size_bits = 5'd31; // Bits is actually bits-1, to make the FSM easier
assign address_increment = 3'd1; // This is only used to increment the address. SPRs are word-addressed.
 
// This is the only thing that actually needs to be saved and 'decoded' from the latched opcode
// It goes to the BIU each time a transaction is started.
assign rd_op = operation[2];
 
 
////////////////////////////////////////////////
// Module-internal register select register (no, that's not redundant.)
// Also internal register output MUX
 
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) internal_register_select = 1'h0;
else if(regsel_ld_en) internal_register_select = reg_select_data;
end
 
// This is completely unnecessary here, since the module has only 1 internal
// register. However, to make the module expandable, it is included anyway.
always @ (internal_register_select or internal_reg_status)
begin
case(internal_register_select)
`DBG_OR1K_INTREG_STATUS: data_from_internal_reg = {30'h0, internal_reg_status};
default: data_from_internal_reg = {30'h0, internal_reg_status};
endcase
end
 
 
////////////////////////////////////////////////////////////////////
// Module-internal registers
// These have generic read/write/select code, but
// individual registers may have special behavior, defined here.
 
// This is the status register, which holds the reset and stall states.
 
assign status_reg_wr = (intreg_ld_en & (reg_select_data == `DBG_OR1K_INTREG_STATUS));
 
adbg_or1k_status_reg or1k_statusreg_i (
.data_i(data_register_i[(47-`DBG_OR1K_REGSELECT_SIZE):(47-(`DBG_OR1K_REGSELECT_SIZE+1))]),
.we_i(status_reg_wr),
.tck_i(tck_i),
.bp_i(cpu_bp_i),
.rst_i(rst_i),
.cpu_clk_i(cpu_clk_i),
.ctrl_reg_o(internal_reg_status),
.cpu_stall_o(cpu_stall_o),
.cpu_rst_o(cpu_rst_o)
);
 
 
///////////////////////////////////////////////
// Address counter
 
assign data_to_addr_counter = (addr_sel) ? incremented_address[31:0] : address_data_in;
assign incremented_address = address_counter + address_increment;
 
// Technically, since this data (sometimes) comes from the input shift reg, we should latch on
// negedge, per the JTAG spec. But that makes things difficult when incrementing.
always @ (posedge tck_i or posedge rst_i) // JTAG spec specifies latch on negative edge in UPDATE_DR state
begin
if(rst_i)
address_counter <= 32'h0;
else if(addr_ct_en)
address_counter <= data_to_addr_counter;
end
 
////////////////////////////////////////
// Opcode latch
 
always @ (posedge tck_i or posedge rst_i) // JTAG spec specifies latch on negative edge in UPDATE_DR state
begin
if(rst_i)
operation <= 4'h0;
else if(op_reg_en)
operation <= operation_in;
end
 
//////////////////////////////////////
// Bit counter
 
always @ (posedge tck_i or posedge rst_i)
begin
 
if(rst_i) bit_count <= 6'h0;
else if(bit_ct_rst) bit_count <= 6'h0;
else if(bit_ct_en) bit_count <= bit_count + 6'h1;
 
end
 
assign bit_count_max = (bit_count == word_size_bits) ? 1'b1 : 1'b0 ;
assign bit_count_32 = (bit_count == 6'h20) ? 1'b1 : 1'b0;
 
////////////////////////////////////////
// Word counter
 
assign data_to_word_counter = (word_ct_sel) ? decremented_word_count : count_data_in;
assign decremented_word_count = word_count - 16'h1;
 
// Technically, since this data (sometimes) comes from the input shift reg, we should latch on
// negedge, per the JTAG spec. But that makes things difficult when incrementing.
always @ (posedge tck_i or posedge rst_i) // JTAG spec specifies latch on negative edge in UPDATE_DR state
begin
if(rst_i)
word_count <= 16'h0;
else if(word_ct_en)
word_count <= data_to_word_counter;
end
 
assign word_count_zero = (word_count == 16'h0);
 
/////////////////////////////////////////////////////
// Output register and TDO output MUX
 
assign out_reg_data = (out_reg_data_sel) ? data_from_internal_reg : data_from_biu;
 
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) data_out_shift_reg <= 32'h0;
else if(out_reg_ld_en) data_out_shift_reg <= out_reg_data;
else if(out_reg_shift_en) data_out_shift_reg <= {1'b0, data_out_shift_reg[31:1]};
end
 
 
always @ (tdo_output_sel or data_out_shift_reg[0] or biu_ready or crc_match or crc_serial_out)
begin
if(tdo_output_sel == 2'h0) module_tdo_o <= biu_ready;
else if(tdo_output_sel == 2'h1) module_tdo_o <= data_out_shift_reg[0];
else if(tdo_output_sel == 2'h2) module_tdo_o <= crc_match;
else module_tdo_o <= crc_serial_out;
end
 
////////////////////////////////////////
// Bus Interface Unit (to OR1K SPR bus)
// It is assumed that the BIU has internal registers, and will
// latch address, operation, and write data on rising clock edge
// when strobe is asserted
 
adbg_or1k_biu or1k_biu_i (
// Debug interface signals
.tck_i (tck_i),
.rst_i (rst_i),
.data_i (data_to_biu),
.data_o (data_from_biu),
.addr_i (address_counter),
.strobe_i (biu_strobe),
.rd_wrn_i (rd_op), // If 0, then write op
.rdy_o (biu_ready),
// This bus has no error signal
// OR1K SPR bus signals
.cpu_clk_i(cpu_clk_i),
.cpu_addr_o(cpu_addr_o),
.cpu_data_i(cpu_data_i),
.cpu_data_o(cpu_data_o),
.cpu_stb_o(cpu_stb_o),
.cpu_we_o(cpu_we_o),
.cpu_ack_i(cpu_ack_i)
);
 
 
 
/////////////////////////////////////
// CRC module
 
assign crc_data_in = (crc_in_sel) ? tdi_i : data_out_shift_reg[0]; // MUX, write or read data
 
adbg_crc32 or1k_crc_i
(
.clk(tck_i),
.data(crc_data_in),
.enable(crc_en),
.shift(crc_shift_en),
.clr(crc_clr),
.rst(rst_i),
.crc_out(crc_data_out),
.serial_out(crc_serial_out)
);
 
assign crc_match = (data_register_i[52:21] == crc_data_out) ? 1'b1 : 1'b0;
 
////////////////////////////////////////
// Control FSM
 
// Definition of machine state values.
// Don't worry too much about the state encoding, the synthesis tool
// will probably re-encode it anyway.
 
`define STATE_idle 4'h0
`define STATE_Rbegin 4'h1
`define STATE_Rready 4'h2
`define STATE_Rstatus 4'h3
`define STATE_Rburst 4'h4
`define STATE_Wready 4'h5
`define STATE_Wwait 4'h6
`define STATE_Wburst 4'h7
`define STATE_Wstatus 4'h8
`define STATE_Rcrc 4'h9
`define STATE_Wcrc 4'ha
`define STATE_Wmatch 4'hb
 
reg [3:0] module_state; // FSM state
reg [3:0] module_next_state; // combinatorial signal, not actually a register
 
 
 
// sequential part of the FSM
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i)
module_state <= `STATE_idle;
else
module_state <= module_next_state;
end
 
 
// Determination of next state; purely combinatorial
always @ (module_state or module_select_i or update_dr_i or capture_dr_i or shift_dr_i or operation_in[2]
or word_count_zero or bit_count_max or data_register_i[52] or bit_count_32 or biu_ready
or module_cmd or intreg_write or decremented_word_count or burst_instruction)
begin
case(module_state)
`STATE_idle:
begin
if(module_cmd && module_select_i && update_dr_i && burst_instruction && operation_in[2]) module_next_state <= `STATE_Rbegin;
else if(module_cmd && module_select_i && update_dr_i && burst_instruction) module_next_state <= `STATE_Wready;
else module_next_state <= `STATE_idle;
end
 
`STATE_Rbegin:
begin
if(word_count_zero) module_next_state <= `STATE_idle; // set up a burst of size 0, illegal.
else module_next_state <= `STATE_Rready;
end
`STATE_Rready:
begin
if(module_select_i && capture_dr_i) module_next_state <= `STATE_Rstatus;
else module_next_state <= `STATE_Rready;
end
`STATE_Rstatus:
begin
if(update_dr_i) module_next_state <= `STATE_idle;
else if (biu_ready) module_next_state <= `STATE_Rburst;
else module_next_state <= `STATE_Rstatus;
end
`STATE_Rburst:
begin
if(update_dr_i) module_next_state <= `STATE_idle;
else if(bit_count_max && word_count_zero) module_next_state <= `STATE_Rcrc;
else if(bit_count_max) module_next_state <= `STATE_Rstatus;
else module_next_state <= `STATE_Rburst;
end
`STATE_Rcrc:
begin
if(update_dr_i) module_next_state <= `STATE_idle;
// This doubles as the 'recovery' state, so stay here until update_dr_i.
else module_next_state <= `STATE_Rcrc;
end
 
`STATE_Wready:
begin
if(word_count_zero) module_next_state <= `STATE_idle;
else if(module_select_i && capture_dr_i) module_next_state <= `STATE_Wwait;
else module_next_state <= `STATE_Wready;
end
`STATE_Wwait:
begin
if(update_dr_i) module_next_state <= `STATE_idle; // client terminated early
else if(module_select_i && data_register_i[52]) module_next_state <= `STATE_Wburst; // Got a start bit
else module_next_state <= `STATE_Wwait;
end
`STATE_Wburst:
begin
if(update_dr_i) module_next_state <= `STATE_idle; // client terminated early
else if(bit_count_max) module_next_state <= `STATE_Wstatus;
else module_next_state <= `STATE_Wburst;
end
`STATE_Wstatus:
begin
if(update_dr_i) module_next_state <= `STATE_idle; // client terminated early
else if(word_count_zero) module_next_state <= `STATE_Wcrc;
// can't wait until bus ready if multiple devices in chain...
// Would have to read postfix_bits, then send another start bit and push it through
// prefix_bits...potentially very inefficient.
else module_next_state <= `STATE_Wburst;
end
`STATE_Wcrc:
begin
if(update_dr_i) module_next_state <= `STATE_idle; // client terminated early
else if(bit_count_32) module_next_state <= `STATE_Wmatch;
else module_next_state <= `STATE_Wcrc;
end
`STATE_Wmatch:
begin
if(update_dr_i) module_next_state <= `STATE_idle;
// This doubles as our recovery state, stay here until update_dr_i
else module_next_state <= `STATE_Wmatch;
end
 
default: module_next_state <= `STATE_idle; // shouldn't actually happen...
endcase
end
 
 
// Outputs of state machine, pure combinatorial
always @ (module_state or module_next_state or module_select_i or update_dr_i or capture_dr_i or shift_dr_i or operation_in[2]
or word_count_zero or bit_count_max or data_register_i[52] or biu_ready or intreg_instruction
or module_cmd or intreg_write or decremented_word_count)
begin
// Default everything to 0, keeps the case statement simple
addr_sel <= 1'b1; // Selects data for address_counter. 0 = data_register_i, 1 = incremented address count
addr_ct_en <= 1'b0; // Enable signal for address counter register
op_reg_en <= 1'b0; // Enable signal for 'operation' register
bit_ct_en <= 1'b0; // enable bit counter
bit_ct_rst <= 1'b0; // reset (zero) bit count register
word_ct_sel <= 1'b1; // Selects data for byte counter. 0 = data_register_i, 1 = decremented byte count
word_ct_en <= 1'b0; // Enable byte counter register
out_reg_ld_en <= 1'b0; // Enable parallel load of data_out_shift_reg
out_reg_shift_en <= 1'b0; // Enable shift of data_out_shift_reg
tdo_output_sel <= 2'b1; // 1 = data reg, 0 = biu_ready, 2 = crc_match, 3 = CRC data
biu_strobe <= 1'b0;
crc_clr <= 1'b0;
crc_en <= 1'b0; // add the input bit to the CRC calculation
crc_in_sel <= 1'b0; // 0 = tdo, 1 = tdi
crc_shift_en <= 1'b0;
out_reg_data_sel <= 1'b1; // 0 = BIU data, 1 = internal register data
regsel_ld_en <= 1'b0;
intreg_ld_en <= 1'b0;
top_inhibit_o <= 1'b0; // Don't disable the top-level module in the default case
 
case(module_state)
`STATE_idle:
begin
addr_sel <= 1'b0;
word_ct_sel <= 1'b0;
// Operations for internal registers - stay in idle state
if(module_select_i & shift_dr_i) out_reg_shift_en <= 1'b1; // For module regs
if(module_select_i & capture_dr_i)
begin
out_reg_data_sel <= 1'b1; // select internal register data
out_reg_ld_en <= 1'b1; // For module regs
end
if(module_select_i & module_cmd & update_dr_i) begin
if(intreg_instruction) regsel_ld_en <= 1'b1; // For module regs
if(intreg_write) intreg_ld_en <= 1'b1; // For module regs
end
// Burst operations
if(module_next_state != `STATE_idle) begin // Do the same to receive read or write opcode
addr_ct_en <= 1'b1;
op_reg_en <= 1'b1;
bit_ct_rst <= 1'b1;
word_ct_en <= 1'b1;
crc_clr <= 1'b1;
end
end
 
`STATE_Rbegin:
begin
if(!word_count_zero) begin // Start a biu read transaction
biu_strobe <= 1'b1;
addr_sel <= 1'b1;
addr_ct_en <= 1'b1;
end
end
 
`STATE_Rready:
; // Just a wait state
`STATE_Rstatus:
begin
tdo_output_sel <= 2'h0;
top_inhibit_o <= 1'b1; // in case of early termination
if (module_next_state == `STATE_Rburst) begin
out_reg_data_sel <= 1'b0; // select BIU data
out_reg_ld_en <= 1'b1;
bit_ct_rst <= 1'b1;
word_ct_sel <= 1'b1;
word_ct_en <= 1'b1;
if(!(decremented_word_count == 0) && !word_count_zero) begin // Start a biu read transaction
biu_strobe <= 1'b1;
addr_sel <= 1'b1;
addr_ct_en <= 1'b1;
end
end
end
 
`STATE_Rburst:
begin
tdo_output_sel <= 2'h1;
out_reg_shift_en <= 1'b1;
bit_ct_en <= 1'b1;
crc_en <= 1'b1;
crc_in_sel <= 1'b0; // read data in output shift register LSB (tdo)
top_inhibit_o <= 1'b1; // in case of early termination
end
 
`STATE_Rcrc:
begin
// Just shift out the data, don't bother counting, we don't move on until update_dr_i
tdo_output_sel <= 2'h3;
crc_shift_en <= 1'b1;
top_inhibit_o <= 1'b1;
end
 
`STATE_Wready:
; // Just a wait state
 
`STATE_Wwait:
begin
tdo_output_sel <= 2'h1;
top_inhibit_o <= 1'b1; // in case of early termination
if(module_next_state == `STATE_Wburst) begin
bit_ct_en <= 1'b1;
word_ct_sel <= 1'b1; // Pre-decrement the byte count
word_ct_en <= 1'b1;
crc_en <= 1'b1; // CRC gets tdi_i, which is 1 cycle ahead of data_register_i, so we need the bit there now in the CRC
crc_in_sel <= 1'b1; // read data from tdi_i
end
end
 
`STATE_Wburst:
begin
bit_ct_en <= 1'b1;
tdo_output_sel <= 2'h1;
crc_en <= 1'b1;
crc_in_sel <= 1'b1; // read data from tdi_i
top_inhibit_o <= 1'b1; // in case of early termination
end
 
`STATE_Wstatus:
begin
tdo_output_sel <= 2'h0; // Send the status bit to TDO
// start transaction
biu_strobe <= 1'b1; // Start a BIU transaction
word_ct_sel <= 1'b1; // Decrement the byte count
word_ct_en <= 1'b1;
bit_ct_rst <= 1'b1; // Zero the bit count
addr_ct_en <= 1'b1; // Increment thte address counter
top_inhibit_o <= 1'b1; // in case of early termination
end
`STATE_Wcrc:
begin
bit_ct_en <= 1'b1;
top_inhibit_o <= 1'b1; // in case of early termination
if(module_next_state == `STATE_Wmatch) tdo_output_sel <= 2'h2; // This is when the 'match' bit is actually read
end
`STATE_Wmatch:
begin
tdo_output_sel <= 2'h2;
top_inhibit_o <= 1'b1; // in case of early termination
end
 
default: ;
endcase
end
 
 
endmodule
 
/adbg_top.v
0,0 → 1,386
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_top.v ////
//// ////
//// ////
//// This file is part of the SoC Advanced Debug Interface. ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_top.v,v $
// Revision 1.2 2009/05/17 20:54:56 Nathan
// Changed email address to opencores.org
//
// Revision 1.1 2008/07/22 20:28:32 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.10 2008/07/11 08:13:29 Nathan
// Latch opcode on posedge, like other signals. This fixes a problem
// when the module is used with a Xilinx BSCAN TAP. Added signals to
// allow modules to inhibit latching of a new active module by the top
// module. This allows the sub-modules to force the top level module
// to ignore the command present in the input shift register after e.g.
// a burst read.
//
// Revision 1.7 2008/06/30 20:09:20 Nathan
// Removed code to select top-level module as active (it served no
// purpose). Re-numbered modules, requiring changes to testbench and
// software driver.
//
 
 
`include "adbg_defines.v"
 
 
// Top module
module adbg_top(
// JTAG signals
tck_i,
tdi_i,
tdo_o,
rst_i,
 
 
// TAP states
shift_dr_i,
pause_dr_i,
update_dr_i,
capture_dr_i,
 
// Instructions
debug_select_i
 
 
`ifdef DBG_WISHBONE_SUPPORTED
// WISHBONE common signals
,
wb_clk_i,
 
// WISHBONE master interface
wb_adr_o,
wb_dat_o,
wb_dat_i,
wb_cyc_o,
wb_stb_o,
wb_sel_o,
wb_we_o,
wb_ack_i,
wb_cab_o,
wb_err_i,
wb_cti_o,
wb_bte_o
`endif
 
`ifdef DBG_CPU0_SUPPORTED
// CPU signals
,
cpu0_clk_i,
cpu0_addr_o,
cpu0_data_i,
cpu0_data_o,
cpu0_bp_i,
cpu0_stall_o,
cpu0_stb_o,
cpu0_we_o,
cpu0_ack_i,
cpu0_rst_o
`endif
 
`ifdef DBG_CPU1_SUPPORTED
// CPU signals
,
cpu1_clk_i,
cpu1_addr_o,
cpu1_data_i,
cpu1_data_o,
cpu1_bp_i,
cpu1_stall_o,
cpu1_stb_o,
cpu1_we_o,
cpu1_ack_i,
cpu1_rst_o
`endif
 
);
 
 
// JTAG signals
input tck_i;
input tdi_i;
output tdo_o;
input rst_i;
 
// TAP states
input shift_dr_i;
input pause_dr_i;
input update_dr_i;
input capture_dr_i;
 
// Module select from TAP
input debug_select_i;
 
`ifdef DBG_WISHBONE_SUPPORTED
input wb_clk_i;
output [31:0] wb_adr_o;
output [31:0] wb_dat_o;
input [31:0] wb_dat_i;
output wb_cyc_o;
output wb_stb_o;
output [3:0] wb_sel_o;
output wb_we_o;
input wb_ack_i;
output wb_cab_o;
input wb_err_i;
output [2:0] wb_cti_o;
output [1:0] wb_bte_o;
`endif
 
`ifdef DBG_CPU0_SUPPORTED
// CPU signals
input cpu0_clk_i;
output [31:0] cpu0_addr_o;
input [31:0] cpu0_data_i;
output [31:0] cpu0_data_o;
input cpu0_bp_i;
output cpu0_stall_o;
output cpu0_stb_o;
output cpu0_we_o;
input cpu0_ack_i;
output cpu0_rst_o;
`endif
 
`ifdef DBG_CPU1_SUPPORTED
input cpu1_clk_i;
output [31:0] cpu1_addr_o;
input [31:0] cpu1_data_i;
output [31:0] cpu1_data_o;
input cpu1_bp_i;
output cpu1_stall_o;
output cpu1_stb_o;
output cpu1_we_o;
input cpu1_ack_i;
output cpu1_rst_o;
`endif
 
 
reg tdo_o;
wire tdo_wb;
wire tdo_cpu0;
wire tdo_cpu1;
 
 
// Registers
reg [`DBG_TOP_MODULE_DATA_LEN-1:0] input_shift_reg; // 1 bit sel/cmd, 4 bit opcode, 32 bit address, 16 bit length = 53 bits
//reg output_shift_reg; // Just 1 bit for status (valid module selected)
reg [`DBG_TOP_MODULE_ID_LENGTH -1:0] module_id_reg; // Module selection register
 
 
// Control signals
wire select_cmd; // True when the command (registered at Update_DR) is for top level/module selection
wire [(`DBG_TOP_MODULE_ID_LENGTH - 1) : 0] module_id_in; // The part of the input_shift_register to be used as the module select data
reg [(`DBG_TOP_MAX_MODULES - 1) : 0] module_selects; // Select signals for the individual modules
wire select_inhibit; // OR of inhibit signals from sub-modules, prevents latching of a new module ID
wire [2:0] module_inhibit; // signals to allow submodules to prevent top level from latching new module ID
 
///////////////////////////////////////
// Combinatorial assignments
 
assign select_cmd = input_shift_reg[52];
assign module_id_in = input_shift_reg[51:50];
 
//////////////////////////////////////////////////////////
// Module select register and select signals
 
always @ (posedge tck_i or posedge rst_i)
begin
if (rst_i)
module_id_reg <= 2'b0;
else if(debug_select_i && select_cmd && update_dr_i && !select_inhibit) // Chain select
module_id_reg <= module_id_in;
end
 
 
always @ (module_id_reg)
begin
module_selects <= `DBG_TOP_MODULE_ID_LENGTH'h0;
module_selects[module_id_reg] <= 1'b1;
end
 
///////////////////////////////////////////////
// Data input shift register
 
always @ (posedge tck_i or posedge rst_i)
begin
if (rst_i)
input_shift_reg <= 53'h0;
else if(debug_select_i && shift_dr_i)
input_shift_reg <= {tdi_i, input_shift_reg[52:1]};
end
 
 
//////////////////////////////////////////////
// Debug module instantiations
 
`ifdef DBG_WISHBONE_SUPPORTED
// Connecting wishbone module
adbg_wb_module i_dbg_wb (
// JTAG signals
.tck_i (tck_i),
.module_tdo_o (tdo_wb),
.tdi_i (tdi_i),
 
// TAP states
.capture_dr_i (capture_dr_i),
.shift_dr_i (shift_dr_i),
.update_dr_i (update_dr_i),
 
.data_register_i (input_shift_reg),
.module_select_i (module_selects[`DBG_TOP_WISHBONE_DEBUG_MODULE]),
.top_inhibit_o (module_inhibit[`DBG_TOP_WISHBONE_DEBUG_MODULE]),
.rst_i (rst_i),
 
// WISHBONE common signals
.wb_clk_i (wb_clk_i),
 
// WISHBONE master interface
.wb_adr_o (wb_adr_o),
.wb_dat_o (wb_dat_o),
.wb_dat_i (wb_dat_i),
.wb_cyc_o (wb_cyc_o),
.wb_stb_o (wb_stb_o),
.wb_sel_o (wb_sel_o),
.wb_we_o (wb_we_o),
.wb_ack_i (wb_ack_i),
.wb_cab_o (wb_cab_o),
.wb_err_i (wb_err_i),
.wb_cti_o (wb_cti_o),
.wb_bte_o (wb_bte_o)
);
`else
assign tdo_wb = 1'b0;
assign module_inhibit[`DBG_TOP_WISHBONE_DEBUG_MODULE] = 1'b0;
`endif
 
 
 
`ifdef DBG_CPU0_SUPPORTED
adbg_or1k_module i_dbg_cpu_or1k (
// JTAG signals
.tck_i (tck_i),
.module_tdo_o (tdo_cpu0),
.tdi_i (tdi_i),
 
// TAP states
.capture_dr_i (capture_dr_i),
.shift_dr_i (shift_dr_i),
.update_dr_i (update_dr_i),
 
.data_register_i (input_shift_reg),
.module_select_i (module_selects[`DBG_TOP_CPU0_DEBUG_MODULE]),
.top_inhibit_o (module_inhibit[`DBG_TOP_CPU0_DEBUG_MODULE]),
.rst_i (rst_i),
 
// CPU signals
.cpu_clk_i (cpu0_clk_i),
.cpu_addr_o (cpu0_addr_o),
.cpu_data_i (cpu0_data_i),
.cpu_data_o (cpu0_data_o),
.cpu_bp_i (cpu0_bp_i),
.cpu_stall_o (cpu0_stall_o),
.cpu_stb_o (cpu0_stb_o),
.cpu_we_o (cpu0_we_o),
.cpu_ack_i (cpu0_ack_i),
.cpu_rst_o (cpu0_rst_o)
);
`else
assign tdo_cpu0 = 1'b0;
assign module_inhibit[`DBG_TOP_CPU0_DEBUG_MODULE] = 1'b0;
`endif // DBG_CPU0_SUPPORTED
 
 
 
`ifdef DBG_CPU1_SUPPORTED
// Connecting cpu module
adbg_or1k_module i_dbg_cpu_8051 (
// JTAG signals
.tck_i (tck_i),
.module_tdo_o (tdo_cpu1),
.tdi_i (tdi_i),
// TAP states
.capture_dr_i (capture_dr_i),
.shift_dr_i (shift_dr_i),
.update_dr_i (update_dr_i),
 
.data_register_i (input_shift_reg),
.module_select_i (module_selects[`DBG_TOP_CPU1_DEBUG_MODULE]),
.top_inhibit_o (module_inhibit[`DBG_TOP_CPU1_DEBUG_MODULE]),
.rst_i (rst_i),
 
// CPU signals
.cpu_clk_i (cpu1_clk_i),
.cpu_addr_o (cpu1_addr_o),
.cpu_data_i (cpu1_data_i),
.cpu_data_o (cpu1_data_o),
.cpu_bp_i (cpu1_bp_i),
.cpu_stall_o (cpu1_stall_o),
.cpu_stb_o (cpu1_stb_o),
.cpu_we_o (cpu1_we_o),
.cpu_ack_i (cpu1_ack_i),
.cpu_rst_o (cpu1_rst_o)
);
`else
assign tdo_cpu1 = 1'b0;
assign module_inhibit[`DBG_TOP_CPU1_DEBUG_MODULE] = 1'b0;
`endif
 
assign select_inhibit = |module_inhibit;
 
/////////////////////////////////////////////////
// TDO output MUX
 
always @ (module_id_reg or tdo_wb or tdo_cpu0 or tdo_cpu1)
begin
case (module_id_reg)
`DBG_TOP_WISHBONE_DEBUG_MODULE: tdo_o <= tdo_wb;
`DBG_TOP_CPU0_DEBUG_MODULE: tdo_o <= tdo_cpu0;
`DBG_TOP_CPU1_DEBUG_MODULE: tdo_o <= tdo_cpu1;
default: tdo_o <= 1'b0;
endcase
 
end
 
 
endmodule
/adbg_wb_defines.v
0,0 → 1,89
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_wb_defines.v ////
//// ////
//// ////
//// This file is part of the SoC Advanced Debug Interface. ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_wb_defines.v,v $
// Revision 1.3 2009/05/17 20:54:57 Nathan
// Changed email address to opencores.org
//
// Revision 1.2 2009/05/04 00:50:11 Nathan
// Changed the WB BIU to use big-endian byte ordering, to match the OR1000. Kept little-endian ordering as a compile-time option in case this is ever used with a little-endian CPU.
//
// Revision 1.1 2008/07/22 20:28:32 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
 
// Endian-ness of the Wishbone interface.
// Default is BIG endian, to match the OR1200.
// If using a LITTLE endian CPU, e.g. an x86, un-comment this line.
//`define DBG_WB_LITTLE_ENDIAN
 
// These relate to the number of internal registers, and how
// many bits are required in the Reg. Select register
`define DBG_WB_REGSELECT_SIZE 1
`define DBG_WB_NUM_INTREG 1
 
// Register index definitions for module-internal registers
// The WB module has just 1, the error register
`define DBG_WB_INTREG_ERROR 1'b0
 
// Valid commands/opcodes for the wishbone debug module
// 0000 NOP
// 0001 Write burst, 8-bit access
// 0010 Write burst, 16-bit access
// 0011 Write burst, 32-bit access
// 0100 Reserved
// 0101 Read burst, 8-bit access
// 0110 Read burst, 16-bit access
// 0111 Read burst, 32-bit access
// 1000 Reserved
// 1001 Internal register select/write
// 1010 - 1100 Reserved
// 1101 Internal register select
// 1110 - 1111 Reserved
 
`define DBG_WB_CMD_BWRITE8 4'h1
`define DBG_WB_CMD_BWRITE16 4'h2
`define DBG_WB_CMD_BWRITE32 4'h3
`define DBG_WB_CMD_BREAD8 4'h5
`define DBG_WB_CMD_BREAD16 4'h6
`define DBG_WB_CMD_BREAD32 4'h7
`define DBG_WB_CMD_IREG_WR 4'h9
`define DBG_WB_CMD_IREG_SEL 4'hd
/adbg_wb_biu.v
0,0 → 1,434
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_wb_biu.v ////
//// ////
//// ////
//// This file is part of the SoC Debug Interface. ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_wb_biu.v,v $
// Revision 1.3 2009/05/17 20:54:57 Nathan
// Changed email address to opencores.org
//
// Revision 1.2 2009/05/04 00:50:10 Nathan
// Changed the WB BIU to use big-endian byte ordering, to match the OR1000. Kept little-endian ordering as a compile-time option in case this is ever used with a little-endian CPU.
//
// Revision 1.1 2008/07/22 20:28:32 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.4 2008/07/08 19:04:04 Nathan
// Many small changes to eliminate compiler warnings, no functional changes.
// System will now pass SRAM and CPU self-tests on Altera FPGA using
// altera_virtual_jtag TAP.
//
 
`include "adbg_wb_defines.v"
 
// Top module
module adbg_wb_biu
(
// Debug interface signals
tck_i,
rst_i,
data_i,
data_o,
addr_i,
strobe_i,
rd_wrn_i, // If 0, then write op
rdy_o,
err_o,
word_size_i, // 1,2, or 4
 
// Wishbone signals
wb_clk_i,
wb_adr_o,
wb_dat_o,
wb_dat_i,
wb_cyc_o,
wb_stb_o,
wb_sel_o,
wb_we_o,
wb_ack_i,
wb_cab_o,
wb_err_i,
wb_cti_o,
wb_bte_o
);
 
// Debug interface signals
input tck_i;
input rst_i;
input [31:0] data_i; // Assume short words are in UPPER order bits!
output [31:0] data_o;
input [31:0] addr_i;
input strobe_i;
input rd_wrn_i;
output rdy_o;
output err_o;
input [2:0] word_size_i;
 
// Wishbone signals
input wb_clk_i;
output [31:0] wb_adr_o;
output [31:0] wb_dat_o;
input [31:0] wb_dat_i;
output wb_cyc_o;
output wb_stb_o;
output [3:0] wb_sel_o;
output wb_we_o;
input wb_ack_i;
output wb_cab_o;
input wb_err_i;
output [2:0] wb_cti_o;
output [1:0] wb_bte_o;
 
wire [31:0] data_o;
reg rdy_o;
wire err_o;
 
wire [31:0] wb_adr_o;
reg wb_cyc_o;
reg wb_stb_o;
wire [31:0] wb_dat_o;
wire [3:0] wb_sel_o;
wire wb_we_o;
wire wb_cab_o;
wire [2:0] wb_cti_o;
wire [1:0] wb_bte_o;
 
 
// Registers
reg [3:0] sel_reg;
reg [29:0] addr_reg; // Don't need the two LSB, this info is in the SEL bits
reg [31:0] data_in_reg; // dbg->WB
reg [31:0] data_out_reg; // WB->dbg
reg wr_reg;
reg str_sync; // This is 'active-toggle' rather than -high or -low.
reg rdy_sync; // ditto, active-toggle
reg err_reg;
 
// Sync registers. TFF indicates TCK domain, WBFF indicates wb_clk domain
reg rdy_sync_tff1;
reg rdy_sync_tff2;
reg rdy_sync_tff2q; // used to detect toggles
reg str_sync_wbff1;
reg str_sync_wbff2;
reg str_sync_wbff2q; // used to detect toggles
 
 
// Control Signals
reg data_o_en; // latch wb_data_i
reg rdy_sync_en; // toggle the rdy_sync signal, indicate ready to TCK domain
reg err_en; // latch the wb_err_i signal
 
// Internal signals
reg [3:0] be_dec; // word_size and low-order address bits decoded to SEL bits
wire start_toggle; // WB domain, indicates a toggle on the start strobe
reg [31:0] swapped_data_i;
reg [31:0] swapped_data_out;
 
//////////////////////////////////////////////////////
// TCK clock domain
// There is no FSM here, just signal latching and clock
// domain synchronization
 
// Create byte enable signals from word_size and address (combinatorial)
`ifdef DBG_WB_LITTLE_ENDIAN
// This uses LITTLE ENDIAN byte ordering...lowest-addressed bytes is the
// least-significant byte of the 32-bit WB bus.
always @ (word_size_i or addr_i)
begin
case (word_size_i)
3'h1:
begin
if(addr_i[1:0] == 2'b00) be_dec <= 4'b0001;
else if(addr_i[1:0] == 2'b01) be_dec <= 4'b0010;
else if(addr_i[1:0] == 2'b10) be_dec <= 4'b0100;
else be_dec <= 4'b1000;
end
3'h2:
begin
if(addr_i[1]) be_dec <= 4'b1100;
else be_dec <= 4'b0011;
end
3'h4: be_dec <= 4'b1111;
default: be_dec <= 4'b1111; // default to 32-bit access
endcase
end
`else
// This is for a BIG ENDIAN CPU...lowest-addressed byte is
// the 8 most significant bits of the 32-bit WB bus.
always @ (word_size_i or addr_i)
begin
case (word_size_i)
3'h1:
begin
if(addr_i[1:0] == 2'b00) be_dec <= 4'b1000;
else if(addr_i[1:0] == 2'b01) be_dec <= 4'b0100;
else if(addr_i[1:0] == 2'b10) be_dec <= 4'b0010;
else be_dec <= 4'b0001;
end
3'h2:
begin
if(addr_i[1] == 1'b1) be_dec <= 4'b0011;
else be_dec <= 4'b1100;
end
3'h4: be_dec <= 4'b1111;
default: be_dec <= 4'b1111; // default to 32-bit access
endcase
end
`endif
 
 
// Byte- or word-swap data as necessary. Use the non-latched be_dec signal,
// since it and the swapped data will be latched at the same time.
// Remember that since the data is shifted in LSB-first, shorter words
// will be in the high-order bits. (combinatorial)
always @ (be_dec or data_i)
begin
case (be_dec)
4'b1111: swapped_data_i <= data_i;
4'b0011: swapped_data_i <= {16'h0,data_i[31:16]};
4'b1100: swapped_data_i <= data_i;
4'b0001: swapped_data_i <= {24'h0, data_i[31:24]};
4'b0010: swapped_data_i <= {16'h0, data_i[31:24], 8'h0};
4'b0100: swapped_data_i <= {8'h0, data_i[31:24], 16'h0};
4'b1000: swapped_data_i <= {data_i[31:24], 24'h0};
default: swapped_data_i <= data_i; // Shouldn't be possible
endcase
end
 
// Latch input data on 'start' strobe, if ready.
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) begin
sel_reg <= 4'h0;
addr_reg <= 30'h0;
data_in_reg <= 32'h0;
wr_reg <= 1'b0;
end
else
if(strobe_i && rdy_o) begin
sel_reg <= be_dec;
addr_reg <= addr_i[31:2];
if(!rd_wrn_i) data_in_reg <= swapped_data_i;
wr_reg <= ~rd_wrn_i;
end
end
 
// Create toggle-active strobe signal for clock sync. This will start a transaction
// on the WB once the toggle propagates to the FSM in the WB domain.
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) str_sync <= 1'b0;
else if(strobe_i && rdy_o) str_sync <= ~str_sync;
end
 
// Create rdy_o output. Set on reset, clear on strobe (if set), set on input toggle
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) begin
rdy_sync_tff1 <= 1'b0;
rdy_sync_tff2 <= 1'b0;
rdy_sync_tff2q <= 1'b0;
rdy_o <= 1'b1;
end
else begin
rdy_sync_tff1 <= rdy_sync; // Synchronize the ready signal across clock domains
rdy_sync_tff2 <= rdy_sync_tff1;
rdy_sync_tff2q <= rdy_sync_tff2; // used to detect toggles
 
if(strobe_i && rdy_o) rdy_o <= 1'b0;
else if(rdy_sync_tff2 != rdy_sync_tff2q) rdy_o <= 1'b1;
end
 
end
 
//////////////////////////////////////////////////////////
// Direct assignments, unsynchronized
 
assign wb_dat_o = data_in_reg;
assign wb_we_o = wr_reg;
assign wb_adr_o = {addr_reg, 2'h0};
assign wb_sel_o = sel_reg;
 
assign data_o = data_out_reg;
assign err_o = err_reg;
 
assign wb_cti_o = 3'h0;
assign wb_bte_o = 2'h0;
assign wb_cab_o = 1'b0;
 
///////////////////////////////////////////////////////
// Wishbone clock domain
 
// synchronize the start strobe
always @ (posedge wb_clk_i or posedge rst_i)
begin
if(rst_i) begin
str_sync_wbff1 <= 1'b0;
str_sync_wbff2 <= 1'b0;
str_sync_wbff2q <= 1'b0;
end
else begin
str_sync_wbff1 <= str_sync;
str_sync_wbff2 <= str_sync_wbff1;
str_sync_wbff2q <= str_sync_wbff2; // used to detect toggles
end
end
 
assign start_toggle = (str_sync_wbff2 != str_sync_wbff2q);
 
// Error indicator register
always @ (posedge wb_clk_i or posedge rst_i)
begin
if(rst_i) err_reg <= 1'b0;
else if(err_en) err_reg <= wb_err_i;
end
 
// Byte- or word-swap the WB->dbg data, as necessary (combinatorial)
// We assume bits not required by SEL are don't care. We reuse assignments
// where possible to keep the MUX smaller. (combinatorial)
always @ (sel_reg or wb_dat_i)
begin
case (sel_reg)
4'b1111: swapped_data_out <= wb_dat_i;
4'b0011: swapped_data_out <= wb_dat_i;
4'b1100: swapped_data_out <= {16'h0, wb_dat_i[31:16]};
4'b0001: swapped_data_out <= wb_dat_i;
4'b0010: swapped_data_out <= {24'h0, wb_dat_i[15:8]};
4'b0100: swapped_data_out <= {16'h0, wb_dat_i[31:16]};
4'b1000: swapped_data_out <= {24'h0, wb_dat_i[31:24]};
default: swapped_data_out <= wb_dat_i; // Shouldn't be possible
endcase
end
 
// WB->dbg data register
always @ (posedge wb_clk_i or posedge rst_i)
begin
if(rst_i) data_out_reg <= 32'h0;
else if(data_o_en) data_out_reg <= swapped_data_out;
end
 
// Create a toggle-active ready signal to send to the TCK domain
always @ (posedge wb_clk_i or posedge rst_i)
begin
if(rst_i) rdy_sync <= 1'b0;
else if(rdy_sync_en) rdy_sync <= ~rdy_sync;
end
 
/////////////////////////////////////////////////////
// Small state machine to create WB accesses
// Not much more that an 'in_progress' bit, but easier
// to read. Deals with single-cycle and multi-cycle
// accesses.
 
reg wb_fsm_state;
reg next_fsm_state;
 
`define STATE_IDLE 1'h0
`define STATE_TRANSFER 1'h1
 
// Sequential bit
always @ (posedge wb_clk_i or posedge rst_i)
begin
if(rst_i) wb_fsm_state <= `STATE_IDLE;
else wb_fsm_state <= next_fsm_state;
end
 
// Determination of next state (combinatorial)
always @ (wb_fsm_state or start_toggle or wb_ack_i or wb_err_i)
begin
case (wb_fsm_state)
`STATE_IDLE:
begin
if(start_toggle && !(wb_ack_i || wb_err_i)) next_fsm_state <= `STATE_TRANSFER; // Don't go to next state for 1-cycle transfer
else next_fsm_state <= `STATE_IDLE;
end
`STATE_TRANSFER:
begin
if(wb_ack_i || wb_err_i) next_fsm_state <= `STATE_IDLE;
else next_fsm_state <= `STATE_TRANSFER;
end
endcase
end
 
// Outputs of state machine (combinatorial)
always @ (wb_fsm_state or start_toggle or wb_ack_i or wb_err_i or wr_reg)
begin
rdy_sync_en <= 1'b0;
err_en <= 1'b0;
data_o_en <= 1'b0;
wb_cyc_o <= 1'b0;
wb_stb_o <= 1'b0;
case (wb_fsm_state)
`STATE_IDLE:
begin
if(start_toggle) begin
wb_cyc_o <= 1'b1;
wb_stb_o <= 1'b1;
if(wb_ack_i || wb_err_i) begin
err_en <= 1'b1;
rdy_sync_en <= 1'b1;
end
if (wb_ack_i && !wr_reg) begin
data_o_en <= 1'b1;
end
end
end
 
`STATE_TRANSFER:
begin
wb_cyc_o <= 1'b1;
wb_stb_o <= 1'b1;
if(wb_ack_i) begin
err_en <= 1'b1;
data_o_en <= 1'b1;
rdy_sync_en <= 1'b1;
end
else if (wb_err_i) begin
err_en <= 1'b1;
rdy_sync_en <= 1'b1;
end
end
endcase
 
end
 
endmodule
 
/adbg_or1k_defines.v
0,0 → 1,86
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_or1k_defines.v ////
//// ////
//// ////
//// This file is part of the SoC Advanced Debug Interface. ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_or1k_defines.v,v $
// Revision 1.2 2009/05/17 20:54:56 Nathan
// Changed email address to opencores.org
//
// Revision 1.1 2008/07/22 20:28:31 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.3 2008/07/06 20:02:54 Nathan
// Fixes for synthesis with Xilinx ISE (also synthesizable with
// Quartus II 7.0). Ran through dos2unix.
//
// Revision 1.2 2008/06/26 20:52:31 Nathan
// OR1K module tested and working. Added copyright / license info
// to _define files. Other cleanup.
//
 
 
// These relate to the number of internal registers, and how
// many bits are required in the Reg. Select register
`define DBG_OR1K_REGSELECT_SIZE 1
`define DBG_OR1K_NUM_INTREG 1
 
// Register index definitions for module-internal registers
// Index 0 is the Status register, used for stall and reset
`define DBG_OR1K_INTREG_STATUS 1'b0
 
`define DBG_OR1K_STATUS_LEN 2
 
// Valid commands/opcodes for the or1k debug module
// 0000 NOP
// 0001 - 0010 Reserved
// 0011 Write burst, 32-bit access
// 0100 - 0110 Reserved
// 0111 Read burst, 32-bit access
// 1000 Reserved
// 1001 Internal register select/write
// 1010 - 1100 Reserved
// 1101 Internal register select
// 1110 - 1111 Reserved
 
 
`define DBG_OR1K_CMD_BWRITE32 4'h3
`define DBG_OR1K_CMD_BREAD32 4'h7
`define DBG_OR1K_CMD_IREG_WR 4'h9
`define DBG_OR1K_CMD_IREG_SEL 4'hd
/adbg_or1k_biu.v
0,0 → 1,296
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_or1k_biu.v ////
//// ////
//// ////
//// This file is part of the SoC Advanced Debug Interface. ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_or1k_biu.v,v $
// Revision 1.2 2009/05/17 20:54:56 Nathan
// Changed email address to opencores.org
//
// Revision 1.1 2008/07/22 20:28:30 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.5 2008/07/08 19:04:03 Nathan
// Many small changes to eliminate compiler warnings, no functional
// changes. System will now pass SRAM and CPU self-tests on Altera
// FPGA using altera_virtual_jtag TAP.
//
 
 
 
module adbg_or1k_biu
(
// Debug interface signals
tck_i,
rst_i,
data_i,
data_o,
addr_i,
strobe_i,
rd_wrn_i, // If 0, then write op
rdy_o,
 
// OR1K SPR bus signals
cpu_clk_i,
cpu_addr_o,
cpu_data_i,
cpu_data_o,
cpu_stb_o,
cpu_we_o,
cpu_ack_i
);
 
// Debug interface signals
input tck_i;
input rst_i;
input [31:0] data_i; // Assume short words are in UPPER order bits!
output [31:0] data_o;
input [31:0] addr_i;
input strobe_i;
input rd_wrn_i;
output rdy_o;
 
 
// OR1K SPR bus signals
input cpu_clk_i;
output [31:0] cpu_addr_o;
input [31:0] cpu_data_i;
output [31:0] cpu_data_o;
output cpu_stb_o;
output cpu_we_o;
input cpu_ack_i;
 
reg rdy_o;
reg cpu_stb_o;
 
 
// Registers
reg [31:0] addr_reg;
reg [31:0] data_in_reg; // dbg->WB
reg [31:0] data_out_reg; // WB->dbg
reg wr_reg;
reg str_sync; // This is 'active-toggle' rather than -high or -low.
reg rdy_sync; // ditto, active-toggle
 
 
// Sync registers. TFF indicates TCK domain, WBFF indicates cpu_clk domain
reg rdy_sync_tff1;
reg rdy_sync_tff2;
reg rdy_sync_tff2q; // used to detect toggles
reg str_sync_wbff1;
reg str_sync_wbff2;
reg str_sync_wbff2q; // used to detect toggles
 
 
// Control Signals
reg data_o_en; // latch wb_data_i
reg rdy_sync_en; // toggle the rdy_sync signal, indicate ready to TCK domain
 
 
// Internal signals
wire start_toggle; // CPU domain, indicates a toggle on the start strobe
 
 
//////////////////////////////////////////////////////
// TCK clock domain
// There is no FSM here, just signal latching and clock
// domain synchronization
 
 
// Latch input data on 'start' strobe, if ready.
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) begin
addr_reg <= 32'h0;
data_in_reg <= 32'h0;
wr_reg <= 1'b0;
end
else
if(strobe_i && rdy_o) begin
addr_reg <= addr_i;
if(!rd_wrn_i) data_in_reg <= data_i;
wr_reg <= ~rd_wrn_i;
end
end
 
// Create toggle-active strobe signal for clock sync. This will start a transaction
// to the CPU once the toggle propagates to the FSM in the cpu_clk domain.
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) str_sync <= 1'b0;
else if(strobe_i && rdy_o) str_sync <= ~str_sync;
end
 
// Create rdy_o output. Set on reset, clear on strobe (if set), set on input toggle
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) begin
rdy_sync_tff1 <= 1'b0;
rdy_sync_tff2 <= 1'b0;
rdy_sync_tff2q <= 1'b0;
rdy_o <= 1'b1;
end
else begin
rdy_sync_tff1 <= rdy_sync; // Synchronize the ready signal across clock domains
rdy_sync_tff2 <= rdy_sync_tff1;
rdy_sync_tff2q <= rdy_sync_tff2; // used to detect toggles
 
if(strobe_i && rdy_o) rdy_o <= 1'b0;
else if(rdy_sync_tff2 != rdy_sync_tff2q) rdy_o <= 1'b1;
end
 
end
 
//////////////////////////////////////////////////////////
// Direct assignments, unsynchronized
 
assign cpu_data_o = data_in_reg;
assign cpu_we_o = wr_reg;
assign cpu_addr_o = addr_reg;
 
assign data_o = data_out_reg;
 
 
///////////////////////////////////////////////////////
// Wishbone clock domain
 
// synchronize the start strobe
always @ (posedge cpu_clk_i or posedge rst_i)
begin
if(rst_i) begin
str_sync_wbff1 <= 1'b0;
str_sync_wbff2 <= 1'b0;
str_sync_wbff2q <= 1'b0;
end
else begin
str_sync_wbff1 <= str_sync;
str_sync_wbff2 <= str_sync_wbff1;
str_sync_wbff2q <= str_sync_wbff2; // used to detect toggles
end
end
 
assign start_toggle = (str_sync_wbff2 != str_sync_wbff2q);
 
 
// CPU->dbg data register
always @ (posedge cpu_clk_i or posedge rst_i)
begin
if(rst_i) data_out_reg <= 32'h0;
else if(data_o_en) data_out_reg <= cpu_data_i;
end
 
// Create a toggle-active ready signal to send to the TCK domain
always @ (posedge cpu_clk_i or posedge rst_i)
begin
if(rst_i) rdy_sync <= 1'b0;
else if(rdy_sync_en) rdy_sync <= ~rdy_sync;
end
 
/////////////////////////////////////////////////////
// Small state machine to create OR1K SPR bus accesses
// Not much more that an 'in_progress' bit, but easier
// to read. Deals with single-cycle and multi-cycle
// accesses.
 
reg cpu_fsm_state;
reg next_fsm_state;
 
`define STATE_IDLE 1'h0
`define STATE_TRANSFER 1'h1
 
// Sequential bit
always @ (posedge cpu_clk_i or posedge rst_i)
begin
if(rst_i) cpu_fsm_state <= `STATE_IDLE;
else cpu_fsm_state <= next_fsm_state;
end
 
// Determination of next state (combinatorial)
always @ (cpu_fsm_state or start_toggle or cpu_ack_i)
begin
case (cpu_fsm_state)
`STATE_IDLE:
begin
if(start_toggle && !cpu_ack_i) next_fsm_state <= `STATE_TRANSFER; // Don't go to next state for 1-cycle transfer
else next_fsm_state <= `STATE_IDLE;
end
`STATE_TRANSFER:
begin
if(cpu_ack_i) next_fsm_state <= `STATE_IDLE;
else next_fsm_state <= `STATE_TRANSFER;
end
endcase
end
 
// Outputs of state machine (combinatorial)
always @ (cpu_fsm_state or start_toggle or cpu_ack_i or wr_reg)
begin
rdy_sync_en <= 1'b0;
data_o_en <= 1'b0;
cpu_stb_o <= 1'b0;
case (cpu_fsm_state)
`STATE_IDLE:
begin
if(start_toggle) begin
cpu_stb_o <= 1'b1;
if(cpu_ack_i) begin
rdy_sync_en <= 1'b1;
end
if (cpu_ack_i && !wr_reg) begin // latch read data
data_o_en <= 1'b1;
end
end
end
 
`STATE_TRANSFER:
begin
cpu_stb_o <= 1'b1; // OR1K behavioral model needs this. OR1200 should be indifferent.
if(cpu_ack_i) begin
data_o_en <= 1'b1;
rdy_sync_en <= 1'b1;
end
end
endcase
 
end
 
endmodule
 
/adbg_crc32.v
0,0 → 1,114
//////////////////////////////////////////////////////////////////////
// File: CRC32.v
// Date: Thu Nov 27 13:56:49 2003
//
// Copyright (C) 1999-2003 Easics NV.
// 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 SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Purpose: Verilog module containing a synthesizable CRC function
// * polynomial: (0 1 2 4 5 7 8 10 11 12 16 22 23 26 32)
// * data width: 1
//
// Info: janz@easics.be (Jan Zegers)
// http://www.easics.com
//
// Modified by Nathan Yawn for the Advanced Debug Module
// Changes (C) 2008 Nathan Yawn
///////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_crc32.v,v $
// Revision 1.1 2008/07/22 20:28:29 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.3 2008/07/06 20:02:53 Nathan
// Fixes for synthesis with Xilinx ISE (also synthesizable with
// Quartus II 7.0). Ran through dos2unix.
//
// Revision 1.2 2008/06/20 19:22:10 Nathan
// Reversed the direction of the CRC computation shift, for a more
// hardware-efficient implementation.
//
//
//
//
 
 
module adbg_crc32 (clk, data, enable, shift, clr, rst, crc_out, serial_out);
 
input clk;
input data;
input enable;
input shift;
input clr;
input rst;
output [31:0] crc_out;
output serial_out;
 
 
reg [31:0] crc;
wire [31:0] new_crc;
 
 
// You may notice that the 'poly' in this implementation is backwards.
// This is because the shift is also 'backwards', so that the data can
// be shifted out in the same direction, which saves on logic + routing.
assign new_crc[0] = crc[1];
assign new_crc[1] = crc[2];
assign new_crc[2] = crc[3];
assign new_crc[3] = crc[4];
assign new_crc[4] = crc[5];
assign new_crc[5] = crc[6] ^ data ^ crc[0];
assign new_crc[6] = crc[7];
assign new_crc[7] = crc[8];
assign new_crc[8] = crc[9] ^ data ^ crc[0];
assign new_crc[9] = crc[10] ^ data ^ crc[0];
assign new_crc[10] = crc[11];
assign new_crc[11] = crc[12];
assign new_crc[12] = crc[13];
assign new_crc[13] = crc[14];
assign new_crc[14] = crc[15];
assign new_crc[15] = crc[16] ^ data ^ crc[0];
assign new_crc[16] = crc[17];
assign new_crc[17] = crc[18];
assign new_crc[18] = crc[19];
assign new_crc[19] = crc[20] ^ data ^ crc[0];
assign new_crc[20] = crc[21] ^ data ^ crc[0];
assign new_crc[21] = crc[22] ^ data ^ crc[0];
assign new_crc[22] = crc[23];
assign new_crc[23] = crc[24] ^ data ^ crc[0];
assign new_crc[24] = crc[25] ^ data ^ crc[0];
assign new_crc[25] = crc[26];
assign new_crc[26] = crc[27] ^ data ^ crc[0];
assign new_crc[27] = crc[28] ^ data ^ crc[0];
assign new_crc[28] = crc[29];
assign new_crc[29] = crc[30] ^ data ^ crc[0];
assign new_crc[30] = crc[31] ^ data ^ crc[0];
assign new_crc[31] = data ^ crc[0];
 
always @ (posedge clk or posedge rst)
begin
if(rst)
crc[31:0] <= #1 32'hffffffff;
else if(clr)
crc[31:0] <= #1 32'hffffffff;
else if(enable)
crc[31:0] <= #1 new_crc;
else if (shift)
crc[31:0] <= #1 {1'b0, crc[31:1]};
end
 
 
//assign crc_match = (crc == 32'h0);
assign crc_out = crc; //[31];
assign serial_out = crc[0];
 
endmodule
/adbg_or1k_status_reg.v
0,0 → 1,192
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_or1k_status_reg.v ////
//// ////
//// ////
//// This file is part of the SoC Debug Interface. ////
//// ////
//// Author(s): ////
//// Igor Mohor (igorm@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 - 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_or1k_status_reg.v,v $
// Revision 1.1 2008/07/22 20:28:31 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.3 2008/07/06 20:02:54 Nathan
// Fixes for synthesis with Xilinx ISE (also synthesizable with
// Quartus II 7.0). Ran through dos2unix.
//
// Revision 1.2 2008/06/26 20:52:32 Nathan
// OR1K module tested and working. Added copyright / license info
// to _define files. Other cleanup.
//
//
//
//
 
`include "adbg_or1k_defines.v"
 
module adbg_or1k_status_reg (
data_i,
we_i,
tck_i,
bp_i,
rst_i,
cpu_clk_i,
ctrl_reg_o,
cpu_stall_o,
cpu_rst_o
);
 
 
input [`DBG_OR1K_STATUS_LEN - 1:0] data_i;
input we_i;
input tck_i;
input bp_i;
input rst_i;
input cpu_clk_i;
 
output [`DBG_OR1K_STATUS_LEN - 1:0] ctrl_reg_o;
output cpu_stall_o;
output cpu_rst_o;
 
reg cpu_reset;
wire [2:1] cpu_op_out;
 
reg stall_bp, stall_bp_csff, stall_bp_tck;
reg stall_reg, stall_reg_csff, stall_reg_cpu;
reg cpu_reset_csff;
reg cpu_rst_o;
 
 
 
// Breakpoint is latched and synchronized. Stall is set and latched.
// This is done in the CPU clock domain, because the JTAG clock (TCK) is
// irregular. By only allowing bp_i to set (but not reset) the stall_bp
// signal, we insure that the CPU will remain in the stalled state until
// the debug host can read the state.
always @ (posedge cpu_clk_i or posedge rst_i)
begin
if(rst_i)
stall_bp <= #1 1'b0;
else if(bp_i)
stall_bp <= #1 1'b1;
else if(stall_reg_cpu)
stall_bp <= #1 1'b0;
end
 
 
// Synchronizing
always @ (posedge tck_i or posedge rst_i)
begin
if (rst_i)
begin
stall_bp_csff <= #1 1'b0;
stall_bp_tck <= #1 1'b0;
end
else
begin
stall_bp_csff <= #1 stall_bp;
stall_bp_tck <= #1 stall_bp_csff;
end
end
 
 
always @ (posedge cpu_clk_i or posedge rst_i)
begin
if (rst_i)
begin
stall_reg_csff <= #1 1'b0;
stall_reg_cpu <= #1 1'b0;
end
else
begin
stall_reg_csff <= #1 stall_reg;
stall_reg_cpu <= #1 stall_reg_csff;
end
end
 
// bp_i forces a stall immediately on a breakpoint
// stall_bp holds the stall until the debug host acts
// stall_reg_cpu allows the debug host to control a stall.
assign cpu_stall_o = bp_i | stall_bp | stall_reg_cpu;
 
 
// Writing data to the control registers (stall)
// This can be set either by the debug host, or by
// a CPU breakpoint. It can only be cleared by the host.
always @ (posedge tck_i or posedge rst_i)
begin
if (rst_i)
stall_reg <= #1 1'b0;
else if (stall_bp_tck)
stall_reg <= #1 1'b1;
else if (we_i)
stall_reg <= #1 data_i[0];
end
 
 
// Writing data to the control registers (reset)
always @ (posedge tck_i or posedge rst_i)
begin
if (rst_i)
cpu_reset <= #1 1'b0;
else if(we_i)
cpu_reset <= #1 data_i[1];
end
 
 
// Synchronizing signals from registers
always @ (posedge cpu_clk_i or posedge rst_i)
begin
if (rst_i)
begin
cpu_reset_csff <= #1 1'b0;
cpu_rst_o <= #1 1'b0;
end
else
begin
cpu_reset_csff <= #1 cpu_reset;
cpu_rst_o <= #1 cpu_reset_csff;
end
end
 
 
 
// Value for read back
assign ctrl_reg_o = {cpu_reset, stall_reg};
 
 
endmodule
 
/adbg_defines.v
0,0 → 1,82
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_defines.v ////
//// ////
//// ////
//// This file is part of the Advanced Debug Interface. ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_defines.v,v $
// Revision 1.2 2009/05/17 20:54:56 Nathan
// Changed email address to opencores.org
//
// Revision 1.1 2008/07/22 20:28:30 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.5 2008/07/06 20:02:53 Nathan
// Fixes for synthesis with Xilinx ISE (also synthesizable with
// Quartus II 7.0). Ran through dos2unix.
//
// Revision 1.4 2008/06/30 20:09:20 Nathan
// Removed code to select top-level module as active (it served no
// purpose). Re-numbered modules, requiring changes to testbench and software driver.
//
 
// Length of the MODULE ID register
`define DBG_TOP_MODULE_ID_LENGTH 2
 
// How many modules can be supported by the module id length
`define DBG_TOP_MAX_MODULES 4
 
// Chains
`define DBG_TOP_WISHBONE_DEBUG_MODULE 2'h0
`define DBG_TOP_CPU0_DEBUG_MODULE 2'h1
`define DBG_TOP_CPU1_DEBUG_MODULE 2'h2
 
// Length of data
`define DBG_TOP_MODULE_DATA_LEN 53
 
 
// If WISHBONE sub-module is supported uncomment the folowing line
`define DBG_WISHBONE_SUPPORTED
 
// If CPU_0 sub-module is supported uncomment the folowing line
`define DBG_CPU0_SUPPORTED
 
// If CPU_1 sub-module is supported uncomment the folowing line
//`define DBG_CPU1_SUPPORTED
 
 
/adbg_wb_module.v
0,0 → 1,736
//////////////////////////////////////////////////////////////////////
//// ////
//// adbg_wb_module.v ////
//// ////
//// ////
//// This file is part of the SoC Advanced Debug Interface. ////
//// ////
//// Author(s): ////
//// Nathan Yawn (nathan.yawn@opencores.org) ////
//// ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008 Authors ////
//// ////
//// 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 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source is distributed in the hope that it will be ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
//// PURPOSE. See the GNU Lesser General Public License for more ////
//// details. ////
//// ////
//// You should have received a copy of the GNU Lesser General ////
//// Public License along with this source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: adbg_wb_module.v,v $
// Revision 1.2 2009/05/17 20:54:57 Nathan
// Changed email address to opencores.org
//
// Revision 1.1 2008/07/22 20:28:33 Nathan
// Changed names of all files and modules (prefixed an a, for advanced). Cleanup, indenting. No functional changes.
//
// Revision 1.12 2008/07/11 08:13:30 Nathan
// Latch opcode on posedge, like other signals. This fixes a problem when
// the module is used with a Xilinx BSCAN TAP. Added signals to allow modules
// to inhibit latching of a new active module by the top module. This allows
// the sub-modules to force the top level module to ignore the command present
// in the input shift register after e.g. a burst read.
//
 
 
`include "adbg_wb_defines.v"
 
// Top module
module adbg_wb_module (
// JTAG signals
tck_i,
module_tdo_o,
tdi_i,
 
// TAP states
capture_dr_i,
shift_dr_i,
update_dr_i,
 
data_register_i, // the data register is at top level, shared between all modules
module_select_i,
top_inhibit_o,
rst_i,
 
// WISHBONE common signals
wb_clk_i,
 
// WISHBONE master interface
wb_adr_o, wb_dat_o, wb_dat_i, wb_cyc_o, wb_stb_o, wb_sel_o,
wb_we_o, wb_ack_i, wb_cab_o, wb_err_i, wb_cti_o, wb_bte_o
 
);
 
// JTAG signals
input tck_i;
output module_tdo_o;
input tdi_i; // This is only used by the CRC module - data_register_i[MSB] is delayed a cycle
 
// TAP states
input capture_dr_i;
input shift_dr_i;
input update_dr_i;
 
input [52:0] data_register_i;
input module_select_i;
output top_inhibit_o;
input rst_i;
 
// WISHBONE master interface
input wb_clk_i;
output [31:0] wb_adr_o;
output [31:0] wb_dat_o;
input [31:0] wb_dat_i;
output wb_cyc_o;
output wb_stb_o;
output [3:0] wb_sel_o;
output wb_we_o;
input wb_ack_i;
output wb_cab_o;
input wb_err_i;
output [2:0] wb_cti_o;
output [1:0] wb_bte_o;
//reg wb_cyc_o;
 
// Declare inputs / outputs as wires / registers
reg module_tdo_o;
reg top_inhibit_o;
 
 
// Registers to hold state etc.
reg [31:0] address_counter; // Holds address for next Wishbone access
reg [5:0] bit_count; // How many bits have been shifted in/out
reg [15:0] word_count; // bytes remaining in current burst command
reg [3:0] operation; // holds the current command (rd/wr, word size)
reg [32:0] data_out_shift_reg; // 32 bits to accomodate the internal_reg_error
reg [`DBG_WB_REGSELECT_SIZE-1:0] internal_register_select; // Holds index of currently selected register
reg [32:0] internal_reg_error; // WB error module internal register. 32 bit address + error bit (LSB)
 
 
// Control signals for the various counters / registers / state machines
reg addr_sel; // Selects data for address_counter. 0 = data_register_i, 1 = incremented address count
reg addr_ct_en; // Enable signal for address counter register
reg op_reg_en; // Enable signal for 'operation' register
reg bit_ct_en; // enable bit counter
reg bit_ct_rst; // reset (zero) bit count register
reg word_ct_sel; // Selects data for byte counter. 0 = data_register_i, 1 = decremented byte count
reg word_ct_en; // Enable byte counter register
reg out_reg_ld_en; // Enable parallel load of data_out_shift_reg
reg out_reg_shift_en; // Enable shift of data_out_shift_reg
reg out_reg_data_sel; // 0 = BIU data, 1 = internal register data
reg [1:0] tdo_output_sel; // Selects signal to send to TDO. 0 = ready bit, 1 = output register, 2 = CRC match, 3 = CRC shift reg.
reg biu_strobe; // Indicates that the bus unit should latch data and start a transaction
reg crc_clr; // resets CRC module
reg crc_en; // does 1-bit iteration in CRC module
reg crc_in_sel; // selects incoming write data (=0) or outgoing read data (=1)as input to CRC module
reg crc_shift_en; // CRC reg is also it's own output shift register; this enables a shift
reg regsel_ld_en; // Reg. select register load enable
reg intreg_ld_en; // load enable for internal registers
reg error_reg_en; // Tells the error register to check for and latch a bus error
reg biu_clr_err; // Allows FSM to reset BIU, to clear the biu_err bit which may have been set on the last transaction of the last burst.
 
// Status signals
wire word_count_zero; // true when byte counter is zero
wire bit_count_max; // true when bit counter is equal to current word size
wire module_cmd; // inverse of MSB of data_register_i. 1 means current cmd not for top level (but is for us)
wire biu_ready; // indicates that the BIU has finished the last command
wire biu_err; // indicates wishbone error during BIU transaction
wire burst_instruction; // True when the input_data_i reg has a valid burst instruction for this module
wire intreg_instruction; // True when the input_data_i reg has a valid internal register instruction
wire intreg_write; // True when the input_data_i reg has an internal register write op
reg rd_op; // True when operation in the opcode reg is a read, false when a write
wire crc_match; // indicates whether data_register_i matches computed CRC
wire bit_count_32; // true when bit count register == 32, for CRC after burst writes
 
// Intermediate signals
reg [5:0] word_size_bits; // 8,16, or 32. Decoded from 'operation'
reg [2:0] word_size_bytes; // 1,2, or 4
wire [32:0] incremented_address; // value of address counter plus 'word_size'
wire [31:0] data_to_addr_counter; // output of the mux in front of the address counter inputs
wire [15:0] data_to_word_counter; // output of the mux in front of the byte counter input
wire [15:0] decremented_word_count;
wire [31:0] address_data_in; // from data_register_i
wire [15:0] count_data_in; // from data_register_i
wire [3:0] operation_in; // from data_register_i
wire [31:0] data_to_biu; // from data_register_i
wire [31:0] data_from_biu; // to data_out_shift_register
wire [31:0] crc_data_out; // output of CRC module, to output shift register
wire crc_data_in; // input to CRC module, either data_register_i[52] or data_out_shift_reg[0]
wire crc_serial_out;
wire [`DBG_WB_REGSELECT_SIZE-1:0] reg_select_data; // from data_register_i, input to internal register select register
wire [32:0] out_reg_data; // parallel input to the output shift register
reg [32:0] data_from_internal_reg; // data from internal reg. MUX to output shift register
wire biu_rst; // logical OR of rst_i and biu_clr_err
 
/////////////////////////////////////////////////
// Combinatorial assignments
 
assign module_cmd = ~(data_register_i[52]);
assign operation_in = data_register_i[51:48];
assign address_data_in = data_register_i[47:16];
assign count_data_in = data_register_i[15:0];
assign data_to_biu = data_register_i[52:21];
assign reg_select_data = data_register_i[47:(47-(`DBG_WB_REGSELECT_SIZE-1))];
 
////////////////////////////////////////////////
// Operation decoder
 
// These are only used before the operation is latched, so decode them from operation_in
assign burst_instruction = (~operation_in[3]) & (operation_in[0] | operation_in[1]);
assign intreg_instruction = ((operation_in == `DBG_WB_CMD_IREG_WR) | (operation_in == `DBG_WB_CMD_IREG_SEL));
assign intreg_write = (operation_in == `DBG_WB_CMD_IREG_WR);
 
 
// This is decoded from the registered operation
always @ (operation)
begin
case(operation)
`DBG_WB_CMD_BWRITE8:
begin
word_size_bits <= 5'd7; // Bits is actually bits-1, to make the FSM easier
word_size_bytes <= 3'd1;
rd_op <= 1'b0;
end
`DBG_WB_CMD_BWRITE16:
begin
word_size_bits <= 5'd15; // Bits is actually bits-1, to make the FSM easier
word_size_bytes <= 3'd2;
rd_op <= 1'b0;
end
`DBG_WB_CMD_BWRITE32:
begin
word_size_bits <= 5'd31; // Bits is actually bits-1, to make the FSM easier
word_size_bytes <= 3'd4;
rd_op <= 1'b0;
end
`DBG_WB_CMD_BREAD8:
begin
word_size_bits <= 5'd7; // Bits is actually bits-1, to make the FSM easier
word_size_bytes <= 3'd1;
rd_op <= 1'b1;
end
`DBG_WB_CMD_BREAD16:
begin
word_size_bits <= 5'd15; // Bits is actually bits-1, to make the FSM easier
word_size_bytes <= 3'd2;
rd_op <= 1'b1;
end
`DBG_WB_CMD_BREAD32:
begin
word_size_bits <= 5'd31; // Bits is actually bits-1, to make the FSM easier
word_size_bytes <= 3'd4;
rd_op <= 1'b1;
end
default:
begin
word_size_bits <= 5'hXX;
word_size_bytes <= 3'hX;
rd_op <= 1'bX;
end
endcase
end
 
 
////////////////////////////////////////////////
// Module-internal register select register (no, that's not redundant.)
// Also internal register output MUX
 
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) internal_register_select = 1'h0;
else if(regsel_ld_en) internal_register_select = reg_select_data;
end
 
// This is completely unnecessary here, since the WB module has only 1 internal
// register. However, to make the module expandable, it is included anyway.
always @ (internal_register_select or internal_reg_error)
begin
case(internal_register_select)
`DBG_WB_INTREG_ERROR: data_from_internal_reg = internal_reg_error;
default: data_from_internal_reg = internal_reg_error;
endcase
end
 
 
////////////////////////////////////////////////////////////////////
// Module-internal registers
// These have generic read/write/select code, but
// individual registers may have special behavior, defined here.
 
// This is the bus error register, which traps WB errors
// We latch every new BIU address in the upper 32 bits, so we always have the address for the transaction which
// generated the error (the address counter might increment, esp. for writes)
// We stop latching addresses when the error bit (bit 0) is set. Keep the error bit set until it is
// manually cleared by a module internal register write.
// Note we use reg_select_data straight from data_register_i, rather than the latched version -
// otherwise, we would write the previously selected register.
 
 
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) internal_reg_error = 33'h0;
else if(intreg_ld_en && (reg_select_data == `DBG_WB_INTREG_ERROR)) // do load from data input register
begin
if(data_register_i[46]) internal_reg_error[0] = 1'b0; // if write data is 1, reset the error bit
end
else if(error_reg_en && !internal_reg_error[0])
begin
if(biu_err) internal_reg_error[0] = 1'b1;
else if(biu_strobe) internal_reg_error[32:1] = address_counter;
end
else if(biu_strobe && !internal_reg_error[0]) internal_reg_error[32:1] = address_counter; // When no error, latch this whether error_reg_en or not
end
 
///////////////////////////////////////////////
// Address counter
 
assign data_to_addr_counter = (addr_sel) ? incremented_address[31:0] : address_data_in;
assign incremented_address = address_counter + word_size_bytes;
 
// Technically, since this data (sometimes) comes from the input shift reg, we should latch on
// negedge, per the JTAG spec. But that makes things difficult when incrementing.
always @ (posedge tck_i or posedge rst_i) // JTAG spec specifies latch on negative edge in UPDATE_DR state
begin
if(rst_i)
address_counter <= 32'h0;
else if(addr_ct_en)
address_counter <= data_to_addr_counter;
end
 
////////////////////////////////////////
// Opcode latch
 
always @ (posedge tck_i or posedge rst_i) // JTAG spec specifies latch on negative edge in UPDATE_DR state
begin
if(rst_i)
operation <= 4'h0;
else if(op_reg_en)
operation <= operation_in;
end
 
//////////////////////////////////////
// Bit counter
 
always @ (posedge tck_i or posedge rst_i)
begin
 
if(rst_i) bit_count <= 6'h0;
else if(bit_ct_rst) bit_count <= 6'h0;
else if(bit_ct_en) bit_count <= bit_count + 6'h1;
 
end
 
assign bit_count_max = (bit_count == word_size_bits) ? 1'b1 : 1'b0 ;
assign bit_count_32 = (bit_count == 6'h20) ? 1'b1 : 1'b0;
 
////////////////////////////////////////
// Word counter
 
assign data_to_word_counter = (word_ct_sel) ? decremented_word_count : count_data_in;
assign decremented_word_count = word_count - 16'h1;
 
// Technically, since this data (sometimes) comes from the input shift reg, we should latch on
// negedge, per the JTAG spec. But that makes things difficult when incrementing.
always @ (posedge tck_i or posedge rst_i) // JTAG spec specifies latch on negative edge in UPDATE_DR state
begin
if(rst_i)
word_count <= 16'h0;
else if(word_ct_en)
word_count <= data_to_word_counter;
end
 
assign word_count_zero = (word_count == 16'h0);
 
/////////////////////////////////////////////////////
// Output register and TDO output MUX
 
assign out_reg_data = (out_reg_data_sel) ? data_from_internal_reg : {1'b0,data_from_biu};
 
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i) data_out_shift_reg <= 33'h0;
else if(out_reg_ld_en) data_out_shift_reg <= out_reg_data;
else if(out_reg_shift_en) data_out_shift_reg <= {1'b0, data_out_shift_reg[32:1]};
end
 
 
always @ (tdo_output_sel or data_out_shift_reg[0] or biu_ready or crc_match or crc_serial_out)
begin
if(tdo_output_sel == 2'h0) module_tdo_o <= biu_ready;
else if(tdo_output_sel == 2'h1) module_tdo_o <= data_out_shift_reg[0];
else if(tdo_output_sel == 2'h2) module_tdo_o <= crc_match;
else module_tdo_o <= crc_serial_out;
end
 
////////////////////////////////////////
// Bus Interface Unit
// It is assumed that the BIU has internal registers, and will
// latch address, operation, and write data on rising clock edge
// when strobe is asserted
 
assign biu_rst = rst_i | biu_clr_err;
 
adbg_wb_biu wb_biu_i
(
// Debug interface signals
.tck_i (tck_i),
.rst_i (biu_rst),
.data_i (data_to_biu),
.data_o (data_from_biu),
.addr_i (address_counter),
.strobe_i (biu_strobe),
.rd_wrn_i (rd_op), // If 0, then write op
.rdy_o (biu_ready),
.err_o (biu_err),
.word_size_i (word_size_bytes),
 
// Wishbone signals
.wb_clk_i (wb_clk_i),
.wb_adr_o (wb_adr_o),
.wb_dat_o (wb_dat_o),
.wb_dat_i (wb_dat_i),
.wb_cyc_o (wb_cyc_o),
.wb_stb_o (wb_stb_o),
.wb_sel_o (wb_sel_o),
.wb_we_o (wb_we_o),
.wb_ack_i (wb_ack_i),
.wb_cab_o (wb_cab_o),
.wb_err_i (wb_err_i),
.wb_cti_o (wb_cti_o),
.wb_bte_o (wb_bte_o)
);
 
/////////////////////////////////////
// CRC module
 
assign crc_data_in = (crc_in_sel) ? tdi_i : data_out_shift_reg[0]; // MUX, write or read data
 
adbg_crc32 wb_crc_i
(
.clk(tck_i),
.data(crc_data_in),
.enable(crc_en),
.shift(crc_shift_en),
.clr(crc_clr),
.rst(rst_i),
.crc_out(crc_data_out),
.serial_out(crc_serial_out)
);
 
assign crc_match = (data_register_i[52:21] == crc_data_out) ? 1'b1 : 1'b0;
 
////////////////////////////////////////
// Control FSM
 
// Definition of machine state values.
// Don't worry too much about the state encoding, the synthesis tool
// will probably re-encode it anyway.
 
`define STATE_idle 4'h0
`define STATE_Rbegin 4'h1
`define STATE_Rready 4'h2
`define STATE_Rstatus 4'h3
`define STATE_Rburst 4'h4
`define STATE_Wready 4'h5
`define STATE_Wwait 4'h6
`define STATE_Wburst 4'h7
`define STATE_Wstatus 4'h8
`define STATE_Rcrc 4'h9
`define STATE_Wcrc 4'ha
`define STATE_Wmatch 4'hb
 
reg [3:0] module_state; // FSM state
reg [3:0] module_next_state; // combinatorial signal, not actually a register
 
 
 
// sequential part of the FSM
always @ (posedge tck_i or posedge rst_i)
begin
if(rst_i)
module_state <= `STATE_idle;
else
module_state <= module_next_state;
end
 
 
// Determination of next state; purely combinatorial
always @ (module_state or module_select_i or module_cmd or update_dr_i or capture_dr_i or operation_in[2]
or word_count_zero or bit_count_max or data_register_i[52] or bit_count_32 or biu_ready or burst_instruction)
begin
case(module_state)
`STATE_idle:
begin
if(module_cmd && module_select_i && update_dr_i && burst_instruction && operation_in[2]) module_next_state <= `STATE_Rbegin;
else if(module_cmd && module_select_i && update_dr_i && burst_instruction) module_next_state <= `STATE_Wready;
else module_next_state <= `STATE_idle;
end
 
`STATE_Rbegin:
begin
if(word_count_zero) module_next_state <= `STATE_idle; // set up a burst of size 0, illegal.
else module_next_state <= `STATE_Rready;
end
`STATE_Rready:
begin
if(module_select_i && capture_dr_i) module_next_state <= `STATE_Rstatus;
else module_next_state <= `STATE_Rready;
end
`STATE_Rstatus:
begin
if(update_dr_i) module_next_state <= `STATE_idle;
else if (biu_ready) module_next_state <= `STATE_Rburst;
else module_next_state <= `STATE_Rstatus;
end
`STATE_Rburst:
begin
if(update_dr_i) module_next_state <= `STATE_idle;
else if(bit_count_max && word_count_zero) module_next_state <= `STATE_Rcrc;
else if(bit_count_max) module_next_state <= `STATE_Rstatus;
else module_next_state <= `STATE_Rburst;
end
`STATE_Rcrc:
begin
if(update_dr_i) module_next_state <= `STATE_idle;
// This doubles as the 'recovery' state, so stay here until update_dr_i.
else module_next_state <= `STATE_Rcrc;
end
 
`STATE_Wready:
begin
if(word_count_zero) module_next_state <= `STATE_idle;
else if(module_select_i && capture_dr_i) module_next_state <= `STATE_Wwait;
else module_next_state <= `STATE_Wready;
end
`STATE_Wwait:
begin
if(update_dr_i) module_next_state <= `STATE_idle; // client terminated early
else if(module_select_i && data_register_i[52]) module_next_state <= `STATE_Wburst; // Got a start bit
else module_next_state <= `STATE_Wwait;
end
`STATE_Wburst:
begin
if(update_dr_i) module_next_state <= `STATE_idle; // client terminated early
else if(bit_count_max) module_next_state <= `STATE_Wstatus;
else module_next_state <= `STATE_Wburst;
end
`STATE_Wstatus:
begin
if(update_dr_i) module_next_state <= `STATE_idle; // client terminated early
else if(word_count_zero) module_next_state <= `STATE_Wcrc;
// can't wait until bus ready if multiple devices in chain...
// Would have to read postfix_bits, then send another start bit and push it through
// prefix_bits...potentially very inefficient.
else module_next_state <= `STATE_Wburst;
end
`STATE_Wcrc:
begin
if(update_dr_i) module_next_state <= `STATE_idle; // client terminated early
else if(bit_count_32) module_next_state <= `STATE_Wmatch;
else module_next_state <= `STATE_Wcrc;
end
`STATE_Wmatch:
begin
if(update_dr_i) module_next_state <= `STATE_idle;
// This doubles as our recovery state, stay here until update_dr_i
else module_next_state <= `STATE_Wmatch;
end
 
default: module_next_state <= `STATE_idle; // shouldn't actually happen...
endcase
end
 
 
// Outputs of state machine, pure combinatorial
always @ (module_state or module_next_state or module_select_i or update_dr_i or capture_dr_i or shift_dr_i or operation_in[2]
or word_count_zero or bit_count_max or data_register_i[52] or biu_ready or intreg_instruction or module_cmd
or intreg_write or decremented_word_count)
begin
// Default everything to 0, keeps the case statement simple
addr_sel <= 1'b1; // Selects data for address_counter. 0 = data_register_i, 1 = incremented address count
addr_ct_en <= 1'b0; // Enable signal for address counter register
op_reg_en <= 1'b0; // Enable signal for 'operation' register
bit_ct_en <= 1'b0; // enable bit counter
bit_ct_rst <= 1'b0; // reset (zero) bit count register
word_ct_sel <= 1'b1; // Selects data for byte counter. 0 = data_register_i, 1 = decremented byte count
word_ct_en <= 1'b0; // Enable byte counter register
out_reg_ld_en <= 1'b0; // Enable parallel load of data_out_shift_reg
out_reg_shift_en <= 1'b0; // Enable shift of data_out_shift_reg
tdo_output_sel <= 2'b1; // 1 = data reg, 0 = biu_ready, 2 = crc_match, 3 = CRC data
biu_strobe <= 1'b0;
crc_clr <= 1'b0;
crc_en <= 1'b0; // add the input bit to the CRC calculation
crc_in_sel <= 1'b0; // 0 = tdo, 1 = tdi
crc_shift_en <= 1'b0;
out_reg_data_sel <= 1'b1; // 0 = BIU data, 1 = internal register data
regsel_ld_en <= 1'b0;
intreg_ld_en <= 1'b0;
error_reg_en <= 1'b0;
biu_clr_err <= 1'b0; // Set this to reset the BIU, clearing the biu_err bit
top_inhibit_o <= 1'b0; // Don't disable the top-level module in the default case
 
case(module_state)
`STATE_idle:
begin
addr_sel <= 1'b0;
word_ct_sel <= 1'b0;
// Operations for internal registers - stay in idle state
if(module_select_i & shift_dr_i) out_reg_shift_en <= 1'b1; // For module regs
if(module_select_i & capture_dr_i)
begin
out_reg_data_sel <= 1'b1; // select internal register data
out_reg_ld_en <= 1'b1; // For module regs
end
if(module_select_i & module_cmd & update_dr_i) begin
if(intreg_instruction) regsel_ld_en <= 1'b1; // For module regs
if(intreg_write) intreg_ld_en <= 1'b1; // For module regs
end
// Burst operations
if(module_next_state != `STATE_idle) begin // Do the same to receive read or write opcode
addr_ct_en <= 1'b1;
op_reg_en <= 1'b1;
bit_ct_rst <= 1'b1;
word_ct_en <= 1'b1;
crc_clr <= 1'b1;
end
end
 
`STATE_Rbegin:
begin
if(!word_count_zero) begin // Start a biu read transaction
biu_strobe <= 1'b1;
addr_sel <= 1'b1;
addr_ct_en <= 1'b1;
end
end
 
`STATE_Rready:
; // Just a wait state
`STATE_Rstatus:
begin
tdo_output_sel <= 2'h0;
top_inhibit_o <= 1'b1; // in case of early termination
if (module_next_state == `STATE_Rburst) begin
error_reg_en <= 1'b1; // Check the wb_error bit
out_reg_data_sel <= 1'b0; // select BIU data
out_reg_ld_en <= 1'b1;
bit_ct_rst <= 1'b1;
word_ct_sel <= 1'b1;
word_ct_en <= 1'b1;
if(!(decremented_word_count == 0) && !word_count_zero) begin // Start a biu read transaction
biu_strobe <= 1'b1;
addr_sel <= 1'b1;
addr_ct_en <= 1'b1;
end
end
end
 
`STATE_Rburst:
begin
tdo_output_sel <= 2'h1;
out_reg_shift_en <= 1'b1;
bit_ct_en <= 1'b1;
crc_en <= 1'b1;
crc_in_sel <= 1'b0; // read data in output shift register LSB (tdo)
top_inhibit_o <= 1'b1; // in case of early termination
end
 
`STATE_Rcrc:
begin
// Just shift out the data, don't bother counting, we don't move on until update_dr_i
tdo_output_sel <= 2'h3;
crc_shift_en <= 1'b1;
top_inhibit_o <= 1'b1;
end
 
`STATE_Wready:
; // Just a wait state
 
`STATE_Wwait:
begin
tdo_output_sel <= 2'h1;
top_inhibit_o <= 1'b1; // in case of early termination
if(module_next_state == `STATE_Wburst) begin
biu_clr_err <= 1'b1; // If error occurred on last transaction of last burst, biu_err is still set. Clear it.
bit_ct_en <= 1'b1;
word_ct_sel <= 1'b1; // Pre-decrement the byte count
word_ct_en <= 1'b1;
crc_en <= 1'b1; // CRC gets tdi_i, which is 1 cycle ahead of data_register_i, so we need the bit there now in the CRC
crc_in_sel <= 1'b1; // read data from tdi_i
end
end
 
`STATE_Wburst:
begin
bit_ct_en <= 1'b1;
tdo_output_sel <= 2'h1;
crc_en <= 1'b1;
crc_in_sel <= 1'b1; // read data from tdi_i
top_inhibit_o <= 1'b1; // in case of early termination
end
 
`STATE_Wstatus:
begin
tdo_output_sel <= 2'h0; // Send the status bit to TDO
error_reg_en <= 1'b1; // Check the wb_error bit
// start transaction
biu_strobe <= 1'b1; // Start a BIU transaction
word_ct_sel <= 1'b1; // Decrement the byte count
word_ct_en <= 1'b1;
bit_ct_rst <= 1'b1; // Zero the bit count
addr_ct_en <= 1'b1; // Increment thte address counter
top_inhibit_o <= 1'b1; // in case of early termination
end
`STATE_Wcrc:
begin
bit_ct_en <= 1'b1;
top_inhibit_o <= 1'b1; // in case of early termination
if(module_next_state == `STATE_Wmatch) tdo_output_sel <= 2'h2; // This is when the 'match' bit is actually read
end
`STATE_Wmatch:
begin
tdo_output_sel <= 2'h2;
top_inhibit_o <= 1'b1;
// Bit of a hack here...an error on the final write won't be detected in STATE_Wstatus like the rest,
// so we assume the bus transaction is done and check it / latch it into the error register here.
if(module_next_state == `STATE_idle) error_reg_en <= 1'b1;
end
 
default: ;
endcase
end
 
 
endmodule
 

powered by: WebSVN 2.1.0

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