370 lines
12 KiB
Coq
370 lines
12 KiB
Coq
|
// ==================================================================
|
||
|
// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
// ------------------------------------------------------------------
|
||
|
// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
|
||
|
// ALL RIGHTS RESERVED
|
||
|
// ------------------------------------------------------------------
|
||
|
//
|
||
|
// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
|
||
|
//
|
||
|
// Permission:
|
||
|
//
|
||
|
// Lattice Semiconductor grants permission to use this code
|
||
|
// pursuant to the terms of the Lattice Semiconductor Corporation
|
||
|
// Open Source License Agreement.
|
||
|
//
|
||
|
// Disclaimer:
|
||
|
//
|
||
|
// Lattice Semiconductor provides no warranty regarding the use or
|
||
|
// functionality of this code. It is the user's responsibility to
|
||
|
// verify the user's design for consistency and functionality through
|
||
|
// the use of formal verification methods.
|
||
|
//
|
||
|
// --------------------------------------------------------------------
|
||
|
//
|
||
|
// Lattice Semiconductor Corporation
|
||
|
// 5555 NE Moore Court
|
||
|
// Hillsboro, OR 97214
|
||
|
// U.S.A
|
||
|
//
|
||
|
// TEL: 1-800-Lattice (USA and Canada)
|
||
|
// 503-286-8001 (other locations)
|
||
|
//
|
||
|
// web: http://www.latticesemi.com/
|
||
|
// email: techsupport@latticesemi.com
|
||
|
//
|
||
|
// --------------------------------------------------------------------
|
||
|
// FILE DETAILS
|
||
|
// Project : LatticeMico32
|
||
|
// File : lm32_debug.v
|
||
|
// Title : Hardware debug registers and associated logic.
|
||
|
// Dependencies : lm32_include.v
|
||
|
// Version : 6.1.17
|
||
|
// : Initial Release
|
||
|
// Version : 7.0SP2, 3.0
|
||
|
// : No Change
|
||
|
// Version : 3.1
|
||
|
// : No Change
|
||
|
// Version : 3.2
|
||
|
// : Fixed simulation bug which flares up when number of
|
||
|
// : watchpoints is zero.
|
||
|
// =============================================================================
|
||
|
|
||
|
`include "lm32_include.v"
|
||
|
|
||
|
`ifdef CFG_DEBUG_ENABLED
|
||
|
|
||
|
// States for single-step FSM
|
||
|
`define LM32_DEBUG_SS_STATE_RNG 2:0
|
||
|
`define LM32_DEBUG_SS_STATE_IDLE 3'b000
|
||
|
`define LM32_DEBUG_SS_STATE_WAIT_FOR_RET 3'b001
|
||
|
`define LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN 3'b010
|
||
|
`define LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT 3'b011
|
||
|
`define LM32_DEBUG_SS_STATE_RESTART 3'b100
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
// Module interface
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
module lm32_debug (
|
||
|
// ----- Inputs -------
|
||
|
clk_i,
|
||
|
rst_i,
|
||
|
pc_x,
|
||
|
load_x,
|
||
|
store_x,
|
||
|
load_store_address_x,
|
||
|
csr_write_enable_x,
|
||
|
csr_write_data,
|
||
|
csr_x,
|
||
|
`ifdef CFG_HW_DEBUG_ENABLED
|
||
|
jtag_csr_write_enable,
|
||
|
jtag_csr_write_data,
|
||
|
jtag_csr,
|
||
|
`endif
|
||
|
`ifdef LM32_SINGLE_STEP_ENABLED
|
||
|
eret_q_x,
|
||
|
bret_q_x,
|
||
|
stall_x,
|
||
|
exception_x,
|
||
|
q_x,
|
||
|
`ifdef CFG_DCACHE_ENABLED
|
||
|
dcache_refill_request,
|
||
|
`endif
|
||
|
`endif
|
||
|
// ----- Outputs -------
|
||
|
`ifdef LM32_SINGLE_STEP_ENABLED
|
||
|
dc_ss,
|
||
|
`endif
|
||
|
dc_re,
|
||
|
bp_match,
|
||
|
wp_match
|
||
|
);
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
// Parameters
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
parameter breakpoints = 0; // Number of breakpoint CSRs
|
||
|
parameter watchpoints = 0; // Number of watchpoint CSRs
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
// Inputs
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
input clk_i; // Clock
|
||
|
input rst_i; // Reset
|
||
|
|
||
|
input [`LM32_PC_RNG] pc_x; // X stage PC
|
||
|
input load_x; // Load instruction in X stage
|
||
|
input store_x; // Store instruction in X stage
|
||
|
input [`LM32_WORD_RNG] load_store_address_x; // Load or store effective address
|
||
|
input csr_write_enable_x; // wcsr instruction in X stage
|
||
|
input [`LM32_WORD_RNG] csr_write_data; // Data to write to CSR
|
||
|
input [`LM32_CSR_RNG] csr_x; // Which CSR to write
|
||
|
`ifdef CFG_HW_DEBUG_ENABLED
|
||
|
input jtag_csr_write_enable; // JTAG interface CSR write enable
|
||
|
input [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to CSR
|
||
|
input [`LM32_CSR_RNG] jtag_csr; // Which CSR to write
|
||
|
`endif
|
||
|
`ifdef LM32_SINGLE_STEP_ENABLED
|
||
|
input eret_q_x; // eret instruction in X stage
|
||
|
input bret_q_x; // bret instruction in X stage
|
||
|
input stall_x; // Instruction in X stage is stalled
|
||
|
input exception_x; // An exception has occured in X stage
|
||
|
input q_x; // Indicates the instruction in the X stage is qualified
|
||
|
`ifdef CFG_DCACHE_ENABLED
|
||
|
input dcache_refill_request; // Indicates data cache wants to be refilled
|
||
|
`endif
|
||
|
`endif
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
// Outputs
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
`ifdef LM32_SINGLE_STEP_ENABLED
|
||
|
output dc_ss; // Single-step enable
|
||
|
reg dc_ss;
|
||
|
`endif
|
||
|
output dc_re; // Remap exceptions
|
||
|
reg dc_re;
|
||
|
output bp_match; // Indicates a breakpoint has matched
|
||
|
wire bp_match;
|
||
|
output wp_match; // Indicates a watchpoint has matched
|
||
|
wire wp_match;
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
// Internal nets and registers
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
genvar i; // Loop index for generate statements
|
||
|
|
||
|
// Debug CSRs
|
||
|
|
||
|
reg [`LM32_PC_RNG] bp_a[0:breakpoints-1]; // Instruction breakpoint address
|
||
|
reg bp_e[0:breakpoints-1]; // Instruction breakpoint enable
|
||
|
wire [0:breakpoints-1]bp_match_n; // Indicates if a h/w instruction breakpoint matched
|
||
|
|
||
|
reg [`LM32_WPC_C_RNG] wpc_c[0:watchpoints-1]; // Watchpoint enable
|
||
|
reg [`LM32_WORD_RNG] wp[0:watchpoints-1]; // Watchpoint address
|
||
|
wire [0:watchpoints]wp_match_n; // Indicates if a h/w data watchpoint matched
|
||
|
|
||
|
wire debug_csr_write_enable; // Debug CSR write enable (from either a wcsr instruction of external debugger)
|
||
|
wire [`LM32_WORD_RNG] debug_csr_write_data; // Data to write to debug CSR
|
||
|
wire [`LM32_CSR_RNG] debug_csr; // Debug CSR to write to
|
||
|
|
||
|
`ifdef LM32_SINGLE_STEP_ENABLED
|
||
|
// FIXME: Declaring this as a reg causes ModelSim 6.1.15b to crash, so use integer for now
|
||
|
//reg [`LM32_DEBUG_SS_STATE_RNG] state; // State of single-step FSM
|
||
|
integer state; // State of single-step FSM
|
||
|
`endif
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
// Functions
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
`include "lm32_functions.v"
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
// Combinational Logic
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
// Check for breakpoints
|
||
|
generate
|
||
|
for (i = 0; i < breakpoints; i = i + 1)
|
||
|
begin : bp_comb
|
||
|
assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == `TRUE));
|
||
|
end
|
||
|
endgenerate
|
||
|
generate
|
||
|
`ifdef LM32_SINGLE_STEP_ENABLED
|
||
|
if (breakpoints > 0)
|
||
|
assign bp_match = (|bp_match_n) || (state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT);
|
||
|
else
|
||
|
assign bp_match = state == `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT;
|
||
|
`else
|
||
|
if (breakpoints > 0)
|
||
|
assign bp_match = |bp_match_n;
|
||
|
else
|
||
|
assign bp_match = `FALSE;
|
||
|
`endif
|
||
|
endgenerate
|
||
|
|
||
|
// Check for watchpoints
|
||
|
generate
|
||
|
for (i = 0; i < watchpoints; i = i + 1)
|
||
|
begin : wp_comb
|
||
|
assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1]));
|
||
|
end
|
||
|
endgenerate
|
||
|
generate
|
||
|
if (watchpoints > 0)
|
||
|
assign wp_match = |wp_match_n;
|
||
|
else
|
||
|
assign wp_match = `FALSE;
|
||
|
endgenerate
|
||
|
|
||
|
`ifdef CFG_HW_DEBUG_ENABLED
|
||
|
// Multiplex between wcsr instruction writes and debugger writes to the debug CSRs
|
||
|
assign debug_csr_write_enable = (csr_write_enable_x == `TRUE) || (jtag_csr_write_enable == `TRUE);
|
||
|
assign debug_csr_write_data = jtag_csr_write_enable == `TRUE ? jtag_csr_write_data : csr_write_data;
|
||
|
assign debug_csr = jtag_csr_write_enable == `TRUE ? jtag_csr : csr_x;
|
||
|
`else
|
||
|
assign debug_csr_write_enable = csr_write_enable_x;
|
||
|
assign debug_csr_write_data = csr_write_data;
|
||
|
assign debug_csr = csr_x;
|
||
|
`endif
|
||
|
|
||
|
/////////////////////////////////////////////////////
|
||
|
// Sequential Logic
|
||
|
/////////////////////////////////////////////////////
|
||
|
|
||
|
// Breakpoint address and enable CSRs
|
||
|
generate
|
||
|
for (i = 0; i < breakpoints; i = i + 1)
|
||
|
begin : bp_seq
|
||
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||
|
begin
|
||
|
if (rst_i == `TRUE)
|
||
|
begin
|
||
|
bp_a[i] <= {`LM32_PC_WIDTH{1'bx}};
|
||
|
bp_e[i] <= `FALSE;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_BP0 + i))
|
||
|
begin
|
||
|
bp_a[i] <= debug_csr_write_data[`LM32_PC_RNG];
|
||
|
bp_e[i] <= debug_csr_write_data[0];
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
endgenerate
|
||
|
|
||
|
// Watchpoint address and control flags CSRs
|
||
|
generate
|
||
|
for (i = 0; i < watchpoints; i = i + 1)
|
||
|
begin : wp_seq
|
||
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||
|
begin
|
||
|
if (rst_i == `TRUE)
|
||
|
begin
|
||
|
wp[i] <= {`LM32_WORD_WIDTH{1'bx}};
|
||
|
wpc_c[i] <= `LM32_WPC_C_DISABLED;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if (debug_csr_write_enable == `TRUE)
|
||
|
begin
|
||
|
if (debug_csr == `LM32_CSR_DC)
|
||
|
wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2];
|
||
|
if (debug_csr == `LM32_CSR_WP0 + i)
|
||
|
wp[i] <= debug_csr_write_data;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
endgenerate
|
||
|
|
||
|
// Remap exceptions control bit
|
||
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||
|
begin
|
||
|
if (rst_i == `TRUE)
|
||
|
dc_re <= `FALSE;
|
||
|
else
|
||
|
begin
|
||
|
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC))
|
||
|
dc_re <= debug_csr_write_data[1];
|
||
|
end
|
||
|
end
|
||
|
|
||
|
`ifdef LM32_SINGLE_STEP_ENABLED
|
||
|
// Single-step control flag
|
||
|
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
|
||
|
begin
|
||
|
if (rst_i == `TRUE)
|
||
|
begin
|
||
|
state <= `LM32_DEBUG_SS_STATE_IDLE;
|
||
|
dc_ss <= `FALSE;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
if ((debug_csr_write_enable == `TRUE) && (debug_csr == `LM32_CSR_DC))
|
||
|
begin
|
||
|
dc_ss <= debug_csr_write_data[0];
|
||
|
if (debug_csr_write_data[0] == `FALSE)
|
||
|
state <= `LM32_DEBUG_SS_STATE_IDLE;
|
||
|
else
|
||
|
state <= `LM32_DEBUG_SS_STATE_WAIT_FOR_RET;
|
||
|
end
|
||
|
case (state)
|
||
|
`LM32_DEBUG_SS_STATE_WAIT_FOR_RET:
|
||
|
begin
|
||
|
// Wait for eret or bret instruction to be executed
|
||
|
if ( ( (eret_q_x == `TRUE)
|
||
|
|| (bret_q_x == `TRUE)
|
||
|
)
|
||
|
&& (stall_x == `FALSE)
|
||
|
)
|
||
|
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
|
||
|
end
|
||
|
`LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN:
|
||
|
begin
|
||
|
// Wait for an instruction to be executed
|
||
|
if ((q_x == `TRUE) && (stall_x == `FALSE))
|
||
|
state <= `LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT;
|
||
|
end
|
||
|
`LM32_DEBUG_SS_STATE_RAISE_BREAKPOINT:
|
||
|
begin
|
||
|
// Wait for exception to be raised
|
||
|
`ifdef CFG_DCACHE_ENABLED
|
||
|
if (dcache_refill_request == `TRUE)
|
||
|
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
|
||
|
else
|
||
|
`endif
|
||
|
if ((exception_x == `TRUE) && (q_x == `TRUE) && (stall_x == `FALSE))
|
||
|
begin
|
||
|
dc_ss <= `FALSE;
|
||
|
state <= `LM32_DEBUG_SS_STATE_RESTART;
|
||
|
end
|
||
|
end
|
||
|
`LM32_DEBUG_SS_STATE_RESTART:
|
||
|
begin
|
||
|
// Watch to see if stepped instruction is restarted due to a cache miss
|
||
|
`ifdef CFG_DCACHE_ENABLED
|
||
|
if (dcache_refill_request == `TRUE)
|
||
|
state <= `LM32_DEBUG_SS_STATE_EXECUTE_ONE_INSN;
|
||
|
else
|
||
|
`endif
|
||
|
state <= `LM32_DEBUG_SS_STATE_IDLE;
|
||
|
end
|
||
|
endcase
|
||
|
end
|
||
|
end
|
||
|
`endif
|
||
|
|
||
|
endmodule
|
||
|
|
||
|
`endif
|