]> rtime.felk.cvut.cz Git - fpga/openmsp430.git/blob - omsp_dbg_hwbrk.v
daadf699c202665726f5e2ecf931b69144c4ceda
[fpga/openmsp430.git] / omsp_dbg_hwbrk.v
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2001 Authors
3 //
4 // This source file may be used and distributed without restriction provided
5 // that this copyright statement is not removed from the file and that any
6 // derivative work contains the original copyright notice and the associated
7 // disclaimer.
8 //
9 // This source file is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU Lesser General Public License as published
11 // by the Free Software Foundation; either version 2.1 of the License, or
12 // (at your option) any later version.
13 //
14 // This source is distributed in the hope that it will be useful, but WITHOUT
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 // License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public License
20 // along with this source; if not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 //----------------------------------------------------------------------------
24 //
25 // *File Name: omsp_dbg_hwbrk.v
26 // 
27 // *Module Description:
28 //                       Hardware Breakpoint / Watchpoint module
29 //
30 // *Author(s):
31 //              - Olivier Girard,    olgirard@gmail.com
32 //
33 //----------------------------------------------------------------------------
34 // $Rev: 57 $
35 // $LastChangedBy: olivier.girard $
36 // $LastChangedDate: 2010-02-01 23:56:03 +0100 (Mon, 01 Feb 2010) $
37 //----------------------------------------------------------------------------
38 `include "timescale.v"
39 `include "openMSP430_defines.v"
40
41 module  omsp_dbg_hwbrk (
42
43 // OUTPUTs
44     brk_halt,                // Hardware breakpoint command
45     brk_pnd,                 // Hardware break/watch-point pending
46     brk_dout,                // Hardware break/watch-point register data input
47                              
48 // INPUTs
49     brk_reg_rd,              // Hardware break/watch-point register read select
50     brk_reg_wr,              // Hardware break/watch-point register write select
51     dbg_din,                 // Debug register data input
52     eu_mab,                  // Execution-Unit Memory address bus
53     eu_mb_en,                // Execution-Unit Memory bus enable
54     eu_mb_wr,                // Execution-Unit Memory bus write transfer
55     eu_mdb_in,               // Memory data bus input
56     eu_mdb_out,              // Memory data bus output
57     exec_done,               // Execution completed
58     fe_mb_en,                // Frontend Memory bus enable
59     mclk,                    // Main system clock
60     pc,                      // Program counter
61     por                      // Power on reset
62 );
63
64 // OUTPUTs
65 //=========
66 output         brk_halt;     // Hardware breakpoint command
67 output         brk_pnd;      // Hardware break/watch-point pending
68 output  [15:0] brk_dout;     // Hardware break/watch-point register data input
69
70 // INPUTs
71 //=========
72 input    [3:0] brk_reg_rd;   // Hardware break/watch-point register read select
73 input    [3:0] brk_reg_wr;   // Hardware break/watch-point register write select
74 input   [15:0] dbg_din;      // Debug register data input
75 input   [15:0] eu_mab;       // Execution-Unit Memory address bus
76 input          eu_mb_en;     // Execution-Unit Memory bus enable
77 input    [1:0] eu_mb_wr;     // Execution-Unit Memory bus write transfer
78 input   [15:0] eu_mdb_in;    // Memory data bus input
79 input   [15:0] eu_mdb_out;   // Memory data bus output
80 input          exec_done;    // Execution completed
81 input          fe_mb_en;     // Frontend Memory bus enable
82 input          mclk;         // Main system clock
83 input   [15:0] pc;           // Program counter
84 input          por;          // Power on reset
85
86
87 //=============================================================================
88 // 1)  WIRE & PARAMETER DECLARATION
89 //=============================================================================
90
91 wire      range_wr_set;
92 wire      range_rd_set;
93 wire      addr1_wr_set;
94 wire      addr1_rd_set;
95 wire      addr0_wr_set;
96 wire      addr0_rd_set;
97
98    
99 parameter BRK_CTL   = 0,
100           BRK_STAT  = 1,
101           BRK_ADDR0 = 2,
102           BRK_ADDR1 = 3;
103
104    
105 //=============================================================================
106 // 2)  CONFIGURATION REGISTERS
107 //=============================================================================
108
109 // BRK_CTL Register
110 //-----------------------------------------------------------------------------
111 //       7   6   5        4            3          2            1  0
112 //        Reserved    RANGE_MODE    INST_EN    BREAK_EN    ACCESS_MODE
113 //
114 // ACCESS_MODE: - 00 : Disabled
115 //              - 01 : Detect read access
116 //              - 10 : Detect write access
117 //              - 11 : Detect read/write access
118 //              NOTE: '10' & '11' modes are not supported on the instruction flow
119 //
120 // BREAK_EN:    -  0 : Watchmode enable
121 //              -  1 : Break enable
122 //
123 // INST_EN:     -  0 : Checks are done on the execution unit (data flow)
124 //              -  1 : Checks are done on the frontend (instruction flow)
125 //
126 // RANGE_MODE:  -  0 : Address match on BRK_ADDR0 or BRK_ADDR1
127 //              -  1 : Address match on BRK_ADDR0->BRK_ADDR1 range
128 //
129 //-----------------------------------------------------------------------------
130 reg   [4:0] brk_ctl;
131
132 wire        brk_ctl_wr = brk_reg_wr[BRK_CTL];
133    
134 always @ (posedge mclk or posedge por)
135   if (por)             brk_ctl <=  5'h00;
136   else if (brk_ctl_wr) brk_ctl <=  {`HWBRK_RANGE & dbg_din[4], dbg_din[3:0]};
137
138 wire  [7:0] brk_ctl_full = {3'b000, brk_ctl};
139
140    
141 // BRK_STAT Register
142 //-----------------------------------------------------------------------------
143 //     7    6       5         4         3         2         1         0
144 //    Reserved  RANGE_WR  RANGE_RD  ADDR1_WR  ADDR1_RD  ADDR0_WR  ADDR0_RD
145 //-----------------------------------------------------------------------------
146 reg   [5:0] brk_stat;
147
148 wire        brk_stat_wr  = brk_reg_wr[BRK_STAT];
149 wire  [5:0] brk_stat_set = {range_wr_set & `HWBRK_RANGE,
150                             range_rd_set & `HWBRK_RANGE,
151                             addr1_wr_set, addr1_rd_set,
152                             addr0_wr_set, addr0_rd_set};
153 wire  [5:0] brk_stat_clr = ~dbg_din[5:0];
154
155 always @ (posedge mclk or posedge por)
156   if (por)              brk_stat <=  6'h00;
157   else if (brk_stat_wr) brk_stat <= ((brk_stat & brk_stat_clr) | brk_stat_set);
158   else                  brk_stat <=  (brk_stat                 | brk_stat_set);
159
160 wire  [7:0] brk_stat_full = {2'b00, brk_stat};
161 wire        brk_pnd       = |brk_stat;
162
163
164 // BRK_ADDR0 Register
165 //-----------------------------------------------------------------------------
166 reg  [15:0] brk_addr0;
167
168 wire        brk_addr0_wr = brk_reg_wr[BRK_ADDR0];
169    
170 always @ (posedge mclk or posedge por)
171   if (por)               brk_addr0 <=  16'h0000;
172   else if (brk_addr0_wr) brk_addr0 <=  dbg_din;
173
174    
175 // BRK_ADDR1/DATA0 Register
176 //-----------------------------------------------------------------------------
177 reg  [15:0] brk_addr1;
178
179 wire        brk_addr1_wr = brk_reg_wr[BRK_ADDR1];
180    
181 always @ (posedge mclk or posedge por)
182   if (por)               brk_addr1 <=  16'h0000;
183   else if (brk_addr1_wr) brk_addr1 <=  dbg_din;
184
185    
186 //============================================================================
187 // 3) DATA OUTPUT GENERATION
188 //============================================================================
189
190 wire [15:0] brk_ctl_rd   = {8'h00, brk_ctl_full}  & {16{brk_reg_rd[BRK_CTL]}};
191 wire [15:0] brk_stat_rd  = {8'h00, brk_stat_full} & {16{brk_reg_rd[BRK_STAT]}};
192 wire [15:0] brk_addr0_rd = brk_addr0              & {16{brk_reg_rd[BRK_ADDR0]}};
193 wire [15:0] brk_addr1_rd = brk_addr1              & {16{brk_reg_rd[BRK_ADDR1]}};
194
195 wire [15:0] brk_dout = brk_ctl_rd   |
196                        brk_stat_rd  |
197                        brk_addr0_rd |
198                        brk_addr1_rd;
199
200    
201 //============================================================================
202 // 4) BREAKPOINT / WATCHPOINT GENERATION
203 //============================================================================
204
205 // Comparators
206 //---------------------------
207 // Note: here the comparison logic is instanciated several times in order
208 //       to improve the timings, at the cost of a bit more area.
209    
210 wire        equ_d_addr0 = eu_mb_en & (eu_mab==brk_addr0) & ~brk_ctl[`BRK_RANGE];
211 wire        equ_d_addr1 = eu_mb_en & (eu_mab==brk_addr1) & ~brk_ctl[`BRK_RANGE];
212 wire        equ_d_range = eu_mb_en & ((eu_mab>=brk_addr0) & (eu_mab<=brk_addr1)) & 
213                           brk_ctl[`BRK_RANGE] & `HWBRK_RANGE;
214
215 reg         fe_mb_en_buf;
216 always @ (posedge mclk or posedge por)
217   if (por)  fe_mb_en_buf <=  1'b0;
218   else      fe_mb_en_buf <=  fe_mb_en;
219
220 wire        equ_i_addr0 = fe_mb_en_buf & (pc==brk_addr0) & ~brk_ctl[`BRK_RANGE];
221 wire        equ_i_addr1 = fe_mb_en_buf & (pc==brk_addr1) & ~brk_ctl[`BRK_RANGE];
222 wire        equ_i_range = fe_mb_en_buf & ((pc>=brk_addr0) & (pc<=brk_addr1)) &
223                           brk_ctl[`BRK_RANGE] & `HWBRK_RANGE;
224
225
226 // Detect accesses
227 //---------------------------
228
229 // Detect Instruction read access
230 wire i_addr0_rd =  equ_i_addr0 &  brk_ctl[`BRK_I_EN];
231 wire i_addr1_rd =  equ_i_addr1 &  brk_ctl[`BRK_I_EN];
232 wire i_range_rd =  equ_i_range &  brk_ctl[`BRK_I_EN];
233
234 // Detect Execution-Unit write access
235 wire d_addr0_wr =  equ_d_addr0 & ~brk_ctl[`BRK_I_EN] &  |eu_mb_wr;
236 wire d_addr1_wr =  equ_d_addr1 & ~brk_ctl[`BRK_I_EN] &  |eu_mb_wr;
237 wire d_range_wr =  equ_d_range & ~brk_ctl[`BRK_I_EN] &  |eu_mb_wr;
238
239 // Detect DATA read access
240 // Whenever an "ADD r9. &0x200" instruction is executed, &0x200 will be read
241 // before being written back. In that case, the read flag should not be set.
242 // In general, We should here make sure no write access occures during the
243 // same instruction cycle before setting the read flag.
244 reg [2:0] d_rd_trig;
245 always @ (posedge mclk or posedge por)
246   if (por)            d_rd_trig <=  3'h0;
247   else if (exec_done) d_rd_trig <=  3'h0;
248   else                d_rd_trig <=  {equ_d_range & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr,
249                                      equ_d_addr1 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr,
250                                      equ_d_addr0 & ~brk_ctl[`BRK_I_EN] & ~|eu_mb_wr};
251    
252 wire d_addr0_rd =  d_rd_trig[0] & exec_done & ~d_addr0_wr;
253 wire d_addr1_rd =  d_rd_trig[1] & exec_done & ~d_addr1_wr;
254 wire d_range_rd =  d_rd_trig[2] & exec_done & ~d_range_wr;
255
256
257 // Set flags
258 assign addr0_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr0_rd  | i_addr0_rd);
259 assign addr0_wr_set = brk_ctl[`BRK_MODE_WR] &  d_addr0_wr;
260 assign addr1_rd_set = brk_ctl[`BRK_MODE_RD] & (d_addr1_rd  | i_addr1_rd);
261 assign addr1_wr_set = brk_ctl[`BRK_MODE_WR] &  d_addr1_wr;
262 assign range_rd_set = brk_ctl[`BRK_MODE_RD] & (d_range_rd  | i_range_rd);
263 assign range_wr_set = brk_ctl[`BRK_MODE_WR] &  d_range_wr;
264
265    
266 // Break CPU
267 assign brk_halt     = brk_ctl[`BRK_EN] & |brk_stat_set;
268    
269      
270 endmodule // omsp_dbg_hwbrk
271
272 `include "openMSP430_undefines.v"