Line 1... |
Line 1... |
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// Copyright (C) 2001 Authors
|
// Copyright (C) 2009 , Olivier Girard
|
//
|
//
|
// This source file may be used and distributed without restriction provided
|
// Redistribution and use in source and binary forms, with or without
|
// that this copyright statement is not removed from the file and that any
|
// modification, are permitted provided that the following conditions
|
// derivative work contains the original copyright notice and the associated
|
// are met:
|
// disclaimer.
|
// * Redistributions of source code must retain the above copyright
|
//
|
// notice, this list of conditions and the following disclaimer.
|
// This source file is free software; you can redistribute it and/or modify
|
// * Redistributions in binary form must reproduce the above copyright
|
// it under the terms of the GNU Lesser General Public License as published
|
// notice, this list of conditions and the following disclaimer in the
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
// documentation and/or other materials provided with the distribution.
|
// (at your option) any later version.
|
// * Neither the name of the authors nor the names of its contributors
|
//
|
// may be used to endorse or promote products derived from this software
|
// This source is distributed in the hope that it will be useful, but WITHOUT
|
// without specific prior written permission.
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
//
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
// License for more details.
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
//
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
// You should have received a copy of the GNU Lesser General Public License
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
// along with this source; if not, write to the Free Software Foundation,
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
// THE POSSIBILITY OF SUCH DAMAGE
|
//
|
//
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
//
|
//
|
// *File Name: omsp_dbg.v
|
// *File Name: omsp_dbg.v
|
//
|
//
|
Line 53... |
Line 58... |
dbg_cpu_reset, // Reset CPU from debug interface
|
dbg_cpu_reset, // Reset CPU from debug interface
|
dbg_uart_txd, // Debug interface: UART TXD
|
dbg_uart_txd, // Debug interface: UART TXD
|
|
|
// INPUTs
|
// INPUTs
|
cpu_en_s, // Enable CPU code execution (synchronous)
|
cpu_en_s, // Enable CPU code execution (synchronous)
|
|
cpu_id, // CPU ID
|
dbg_clk, // Debug unit clock
|
dbg_clk, // Debug unit clock
|
dbg_en_s, // Debug interface enable (synchronous)
|
dbg_en_s, // Debug interface enable (synchronous)
|
dbg_halt_st, // Halt/Run status from CPU
|
dbg_halt_st, // Halt/Run status from CPU
|
dbg_mem_din, // Debug unit Memory data input
|
dbg_mem_din, // Debug unit Memory data input
|
dbg_reg_din, // Debug unit CPU register data input
|
dbg_reg_din, // Debug unit CPU register data input
|
Line 70... |
Line 76... |
eu_mdb_out, // Memory data bus output
|
eu_mdb_out, // Memory data bus output
|
exec_done, // Execution completed
|
exec_done, // Execution completed
|
fe_mb_en, // Frontend Memory bus enable
|
fe_mb_en, // Frontend Memory bus enable
|
fe_mdb_in, // Frontend Memory data bus input
|
fe_mdb_in, // Frontend Memory data bus input
|
pc, // Program counter
|
pc, // Program counter
|
puc_rst // Main system reset
|
puc_pnd_set // PUC pending set for the serial debug interface
|
);
|
);
|
|
|
// OUTPUTs
|
// OUTPUTs
|
//=========
|
//=========
|
output dbg_freeze; // Freeze peripherals
|
output dbg_freeze; // Freeze peripherals
|
Line 88... |
Line 94... |
output dbg_uart_txd; // Debug interface: UART TXD
|
output dbg_uart_txd; // Debug interface: UART TXD
|
|
|
// INPUTs
|
// INPUTs
|
//=========
|
//=========
|
input cpu_en_s; // Enable CPU code execution (synchronous)
|
input cpu_en_s; // Enable CPU code execution (synchronous)
|
|
input [31:0] cpu_id; // CPU ID
|
input dbg_clk; // Debug unit clock
|
input dbg_clk; // Debug unit clock
|
input dbg_en_s; // Debug interface enable (synchronous)
|
input dbg_en_s; // Debug interface enable (synchronous)
|
input dbg_halt_st; // Halt/Run status from CPU
|
input dbg_halt_st; // Halt/Run status from CPU
|
input [15:0] dbg_mem_din; // Debug unit Memory data input
|
input [15:0] dbg_mem_din; // Debug unit Memory data input
|
input [15:0] dbg_reg_din; // Debug unit CPU register data input
|
input [15:0] dbg_reg_din; // Debug unit CPU register data input
|
Line 105... |
Line 112... |
input [15:0] eu_mdb_out; // Memory data bus output
|
input [15:0] eu_mdb_out; // Memory data bus output
|
input exec_done; // Execution completed
|
input exec_done; // Execution completed
|
input fe_mb_en; // Frontend Memory bus enable
|
input fe_mb_en; // Frontend Memory bus enable
|
input [15:0] fe_mdb_in; // Frontend Memory data bus input
|
input [15:0] fe_mdb_in; // Frontend Memory data bus input
|
input [15:0] pc; // Program counter
|
input [15:0] pc; // Program counter
|
input puc_rst; // Main system reset
|
input puc_pnd_set; // PUC pending set for the serial debug interface
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 1) WIRE & PARAMETER DECLARATION
|
// 1) WIRE & PARAMETER DECLARATION
|
//=============================================================================
|
//=============================================================================
|
Line 138... |
Line 145... |
wire [15:0] brk2_dout;
|
wire [15:0] brk2_dout;
|
wire brk3_halt;
|
wire brk3_halt;
|
wire brk3_pnd;
|
wire brk3_pnd;
|
wire [15:0] brk3_dout;
|
wire [15:0] brk3_dout;
|
|
|
|
// Number of registers
|
|
parameter NR_REG = 24;
|
|
|
// Register addresses
|
// Register addresses
|
parameter CPU_ID_LO = 6'h00;
|
parameter CPU_ID_LO = 6'h00;
|
parameter CPU_ID_HI = 6'h01;
|
parameter CPU_ID_HI = 6'h01;
|
parameter CPU_CTL = 6'h02;
|
parameter CPU_CTL = 6'h02;
|
parameter CPU_STAT = 6'h03;
|
parameter CPU_STAT = 6'h03;
|
Line 173... |
Line 183... |
parameter BRK3_ADDR0 = 6'h16;
|
parameter BRK3_ADDR0 = 6'h16;
|
parameter BRK3_ADDR1 = 6'h17;
|
parameter BRK3_ADDR1 = 6'h17;
|
`endif
|
`endif
|
|
|
// Register one-hot decoder
|
// Register one-hot decoder
|
parameter CPU_ID_LO_D = (64'h1 << CPU_ID_LO);
|
parameter BASE_D = {{NR_REG-1{1'b0}}, 1'b1};
|
parameter CPU_ID_HI_D = (64'h1 << CPU_ID_HI);
|
parameter CPU_ID_LO_D = (BASE_D << CPU_ID_LO);
|
parameter CPU_CTL_D = (64'h1 << CPU_CTL);
|
parameter CPU_ID_HI_D = (BASE_D << CPU_ID_HI);
|
parameter CPU_STAT_D = (64'h1 << CPU_STAT);
|
parameter CPU_CTL_D = (BASE_D << CPU_CTL);
|
parameter MEM_CTL_D = (64'h1 << MEM_CTL);
|
parameter CPU_STAT_D = (BASE_D << CPU_STAT);
|
parameter MEM_ADDR_D = (64'h1 << MEM_ADDR);
|
parameter MEM_CTL_D = (BASE_D << MEM_CTL);
|
parameter MEM_DATA_D = (64'h1 << MEM_DATA);
|
parameter MEM_ADDR_D = (BASE_D << MEM_ADDR);
|
parameter MEM_CNT_D = (64'h1 << MEM_CNT);
|
parameter MEM_DATA_D = (BASE_D << MEM_DATA);
|
|
parameter MEM_CNT_D = (BASE_D << MEM_CNT);
|
`ifdef DBG_HWBRK_0
|
`ifdef DBG_HWBRK_0
|
parameter BRK0_CTL_D = (64'h1 << BRK0_CTL);
|
parameter BRK0_CTL_D = (BASE_D << BRK0_CTL);
|
parameter BRK0_STAT_D = (64'h1 << BRK0_STAT);
|
parameter BRK0_STAT_D = (BASE_D << BRK0_STAT);
|
parameter BRK0_ADDR0_D = (64'h1 << BRK0_ADDR0);
|
parameter BRK0_ADDR0_D = (BASE_D << BRK0_ADDR0);
|
parameter BRK0_ADDR1_D = (64'h1 << BRK0_ADDR1);
|
parameter BRK0_ADDR1_D = (BASE_D << BRK0_ADDR1);
|
`endif
|
`endif
|
`ifdef DBG_HWBRK_1
|
`ifdef DBG_HWBRK_1
|
parameter BRK1_CTL_D = (64'h1 << BRK1_CTL);
|
parameter BRK1_CTL_D = (BASE_D << BRK1_CTL);
|
parameter BRK1_STAT_D = (64'h1 << BRK1_STAT);
|
parameter BRK1_STAT_D = (BASE_D << BRK1_STAT);
|
parameter BRK1_ADDR0_D = (64'h1 << BRK1_ADDR0);
|
parameter BRK1_ADDR0_D = (BASE_D << BRK1_ADDR0);
|
parameter BRK1_ADDR1_D = (64'h1 << BRK1_ADDR1);
|
parameter BRK1_ADDR1_D = (BASE_D << BRK1_ADDR1);
|
`endif
|
`endif
|
`ifdef DBG_HWBRK_2
|
`ifdef DBG_HWBRK_2
|
parameter BRK2_CTL_D = (64'h1 << BRK2_CTL);
|
parameter BRK2_CTL_D = (BASE_D << BRK2_CTL);
|
parameter BRK2_STAT_D = (64'h1 << BRK2_STAT);
|
parameter BRK2_STAT_D = (BASE_D << BRK2_STAT);
|
parameter BRK2_ADDR0_D = (64'h1 << BRK2_ADDR0);
|
parameter BRK2_ADDR0_D = (BASE_D << BRK2_ADDR0);
|
parameter BRK2_ADDR1_D = (64'h1 << BRK2_ADDR1);
|
parameter BRK2_ADDR1_D = (BASE_D << BRK2_ADDR1);
|
`endif
|
`endif
|
`ifdef DBG_HWBRK_3
|
`ifdef DBG_HWBRK_3
|
parameter BRK3_CTL_D = (64'h1 << BRK3_CTL);
|
parameter BRK3_CTL_D = (BASE_D << BRK3_CTL);
|
parameter BRK3_STAT_D = (64'h1 << BRK3_STAT);
|
parameter BRK3_STAT_D = (BASE_D << BRK3_STAT);
|
parameter BRK3_ADDR0_D = (64'h1 << BRK3_ADDR0);
|
parameter BRK3_ADDR0_D = (BASE_D << BRK3_ADDR0);
|
parameter BRK3_ADDR1_D = (64'h1 << BRK3_ADDR1);
|
parameter BRK3_ADDR1_D = (BASE_D << BRK3_ADDR1);
|
`endif
|
`endif
|
|
|
// PUC is localy used as a data.
|
|
reg [1:0] puc_sync;
|
|
always @ (posedge dbg_clk or posedge dbg_rst)
|
|
if (dbg_rst) puc_sync <= 2'b11;
|
|
else puc_sync <= {puc_sync[0] , puc_rst};
|
|
wire puc_s = puc_sync[1];
|
|
|
|
|
|
//============================================================================
|
//============================================================================
|
// 2) REGISTER DECODER
|
// 2) REGISTER DECODER
|
//============================================================================
|
//============================================================================
|
|
|
// Select Data register during a burst
|
// Select Data register during a burst
|
wire [5:0] dbg_addr_in = mem_burst ? MEM_DATA : dbg_addr;
|
wire [5:0] dbg_addr_in = mem_burst ? MEM_DATA : dbg_addr;
|
|
|
// Register address decode
|
// Register address decode
|
reg [63:0] reg_dec;
|
reg [NR_REG-1:0] reg_dec;
|
always @(dbg_addr_in)
|
always @(dbg_addr_in)
|
case (dbg_addr_in)
|
case (dbg_addr_in)
|
CPU_ID_LO : reg_dec = CPU_ID_LO_D;
|
CPU_ID_LO : reg_dec = CPU_ID_LO_D;
|
CPU_ID_HI : reg_dec = CPU_ID_HI_D;
|
CPU_ID_HI : reg_dec = CPU_ID_HI_D;
|
CPU_CTL : reg_dec = CPU_CTL_D;
|
CPU_CTL : reg_dec = CPU_CTL_D;
|
Line 257... |
Line 261... |
BRK3_CTL : reg_dec = BRK3_CTL_D;
|
BRK3_CTL : reg_dec = BRK3_CTL_D;
|
BRK3_STAT : reg_dec = BRK3_STAT_D;
|
BRK3_STAT : reg_dec = BRK3_STAT_D;
|
BRK3_ADDR0: reg_dec = BRK3_ADDR0_D;
|
BRK3_ADDR0: reg_dec = BRK3_ADDR0_D;
|
BRK3_ADDR1: reg_dec = BRK3_ADDR1_D;
|
BRK3_ADDR1: reg_dec = BRK3_ADDR1_D;
|
`endif
|
`endif
|
default: reg_dec = {64{1'b0}};
|
// pragma coverage off
|
|
default: reg_dec = {NR_REG{1'b0}};
|
|
// pragma coverage on
|
endcase
|
endcase
|
|
|
// Read/Write probes
|
// Read/Write probes
|
wire reg_write = dbg_wr;
|
wire reg_write = dbg_wr;
|
wire reg_read = 1'b1;
|
wire reg_read = 1'b1;
|
|
|
// Read/Write vectors
|
// Read/Write vectors
|
wire [63:0] reg_wr = reg_dec & {64{reg_write}};
|
wire [NR_REG-1:0] reg_wr = reg_dec & {NR_REG{reg_write}};
|
wire [63:0] reg_rd = reg_dec & {64{reg_read}};
|
wire [NR_REG-1:0] reg_rd = reg_dec & {NR_REG{reg_read}};
|
|
|
|
|
//=============================================================================
|
//=============================================================================
|
// 3) REGISTER: CORE INTERFACE
|
// 3) REGISTER: CORE INTERFACE
|
//=============================================================================
|
//=============================================================================
|
Line 285... |
Line 291... |
// CPU_ID_HI: | 15 14 13 12 11 10 | 9 8 7 6 5 4 3 2 1 | 0 |
|
// CPU_ID_HI: | 15 14 13 12 11 10 | 9 8 7 6 5 4 3 2 1 | 0 |
|
// |----------------------------+-------------------------------+------|
|
// |----------------------------+-------------------------------+------|
|
// | PMEM_SIZE | DMEM_SIZE | MPY |
|
// | PMEM_SIZE | DMEM_SIZE | MPY |
|
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
|
|
wire [2:0] cpu_version = `CPU_VERSION;
|
// This register is assigned in the SFR module
|
`ifdef ASIC
|
|
wire cpu_asic = 1'b1;
|
|
`else
|
|
wire cpu_asic = 1'b0;
|
|
`endif
|
|
wire [4:0] user_version = `USER_VERSION;
|
|
wire [6:0] per_space = (`PER_SIZE >> 9); // cpu_id_per * 512 = peripheral space size
|
|
`ifdef MULTIPLIER
|
|
wire mpy_info = 1'b1;
|
|
`else
|
|
wire mpy_info = 1'b0;
|
|
`endif
|
|
wire [8:0] dmem_size = (`DMEM_SIZE >> 7); // cpu_id_dmem * 128 = data memory size
|
|
wire [5:0] pmem_size = (`PMEM_SIZE >> 10); // cpu_id_pmem * 1024 = program memory size
|
|
|
|
wire [31:0] cpu_id = {pmem_size,
|
|
dmem_size,
|
|
mpy_info,
|
|
per_space,
|
|
user_version,
|
|
cpu_asic,
|
|
cpu_version};
|
|
|
|
|
|
// CPU_CTL Register
|
// CPU_CTL Register
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// 7 6 5 4 3 2 1 0
|
// 7 6 5 4 3 2 1 0
|
Line 321... |
Line 305... |
|
|
wire cpu_ctl_wr = reg_wr[CPU_CTL];
|
wire cpu_ctl_wr = reg_wr[CPU_CTL];
|
|
|
always @ (posedge dbg_clk or posedge dbg_rst)
|
always @ (posedge dbg_clk or posedge dbg_rst)
|
`ifdef DBG_RST_BRK_EN
|
`ifdef DBG_RST_BRK_EN
|
if (dbg_rst) cpu_ctl <= 4'h4;
|
if (dbg_rst) cpu_ctl <= 4'h6;
|
`else
|
`else
|
if (dbg_rst) cpu_ctl <= 4'h0;
|
if (dbg_rst) cpu_ctl <= 4'h2;
|
`endif
|
`endif
|
else if (cpu_ctl_wr) cpu_ctl <= dbg_din[6:3];
|
else if (cpu_ctl_wr) cpu_ctl <= dbg_din[6:3];
|
|
|
wire [7:0] cpu_ctl_full = {1'b0, cpu_ctl, 3'b000};
|
wire [7:0] cpu_ctl_full = {1'b0, cpu_ctl, 3'b000};
|
|
|
Line 342... |
Line 326... |
// HWBRK3_PND HWBRK2_PND HWBRK1_PND HWBRK0_PND SWBRK_PND PUC_PND Res. HALT_RUN
|
// HWBRK3_PND HWBRK2_PND HWBRK1_PND HWBRK0_PND SWBRK_PND PUC_PND Res. HALT_RUN
|
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
reg [3:2] cpu_stat;
|
reg [3:2] cpu_stat;
|
|
|
wire cpu_stat_wr = reg_wr[CPU_STAT];
|
wire cpu_stat_wr = reg_wr[CPU_STAT];
|
wire [3:2] cpu_stat_set = {dbg_swbrk, puc_s};
|
wire [3:2] cpu_stat_set = {dbg_swbrk, puc_pnd_set};
|
wire [3:2] cpu_stat_clr = ~dbg_din[3:2];
|
wire [3:2] cpu_stat_clr = ~dbg_din[3:2];
|
|
|
always @ (posedge dbg_clk or posedge dbg_rst)
|
always @ (posedge dbg_clk or posedge dbg_rst)
|
if (dbg_rst) cpu_stat <= 2'b00;
|
if (dbg_rst) cpu_stat <= 2'b00;
|
else if (cpu_stat_wr) cpu_stat <= ((cpu_stat & cpu_stat_clr) | cpu_stat_set);
|
else if (cpu_stat_wr) cpu_stat <= ((cpu_stat & cpu_stat_clr) | cpu_stat_set);
|
Line 660... |
Line 644... |
wire dbg_cpu_reset = cpu_ctl[`CPU_RST];
|
wire dbg_cpu_reset = cpu_ctl[`CPU_RST];
|
|
|
|
|
// Break after reset
|
// Break after reset
|
//--------------------------
|
//--------------------------
|
wire halt_rst = cpu_ctl[`RST_BRK_EN] & dbg_en_s & puc_s;
|
wire halt_rst = cpu_ctl[`RST_BRK_EN] & dbg_en_s & puc_pnd_set;
|
|
|
|
|
// Freeze peripherals
|
// Freeze peripherals
|
//--------------------------
|
//--------------------------
|
wire dbg_freeze = dbg_halt_st & (cpu_ctl[`FRZ_BRK_EN] | ~cpu_en_s);
|
wire dbg_freeze = dbg_halt_st & (cpu_ctl[`FRZ_BRK_EN] | ~cpu_en_s);
|
Line 750... |
Line 734... |
M_IDLE : mem_state_nxt = ~mem_seq_start ? M_IDLE :
|
M_IDLE : mem_state_nxt = ~mem_seq_start ? M_IDLE :
|
dbg_halt_st ? M_ACCESS : M_SET_BRK;
|
dbg_halt_st ? M_ACCESS : M_SET_BRK;
|
M_SET_BRK : mem_state_nxt = dbg_halt_st ? M_ACCESS_BRK : M_SET_BRK;
|
M_SET_BRK : mem_state_nxt = dbg_halt_st ? M_ACCESS_BRK : M_SET_BRK;
|
M_ACCESS_BRK : mem_state_nxt = M_IDLE;
|
M_ACCESS_BRK : mem_state_nxt = M_IDLE;
|
M_ACCESS : mem_state_nxt = M_IDLE;
|
M_ACCESS : mem_state_nxt = M_IDLE;
|
|
// pragma coverage off
|
default : mem_state_nxt = M_IDLE;
|
default : mem_state_nxt = M_IDLE;
|
|
// pragma coverage on
|
endcase
|
endcase
|
|
|
// State machine
|
// State machine
|
always @(posedge dbg_clk or posedge dbg_rst)
|
always @(posedge dbg_clk or posedge dbg_rst)
|
if (dbg_rst) mem_state <= M_IDLE;
|
if (dbg_rst) mem_state <= M_IDLE;
|