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 |
|