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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [core/] [rtl/] [verilog/] [omsp_mem_backbone.v] - Blame information for rev 225

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 olivier.gi
//----------------------------------------------------------------------------
2 117 olivier.gi
// Copyright (C) 2009 , Olivier Girard
3 2 olivier.gi
//
4 117 olivier.gi
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions
6
// are met:
7
//     * Redistributions of source code must retain the above copyright
8
//       notice, this list of conditions and the following disclaimer.
9
//     * Redistributions in binary form must reproduce the above copyright
10
//       notice, this list of conditions and the following disclaimer in the
11
//       documentation and/or other materials provided with the distribution.
12
//     * Neither the name of the authors nor the names of its contributors
13
//       may be used to endorse or promote products derived from this software
14
//       without specific prior written permission.
15 2 olivier.gi
//
16 117 olivier.gi
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26
// THE POSSIBILITY OF SUCH DAMAGE
27 2 olivier.gi
//
28
//----------------------------------------------------------------------------
29
//
30 34 olivier.gi
// *File Name: omsp_mem_backbone.v
31 202 olivier.gi
//
32 2 olivier.gi
// *Module Description:
33
//                       Memory interface backbone (decoder + arbiter)
34
//
35
// *Author(s):
36
//              - Olivier Girard,    olgirard@gmail.com
37
//
38
//----------------------------------------------------------------------------
39 17 olivier.gi
// $Rev: 205 $
40
// $LastChangedBy: olivier.girard $
41
// $LastChangedDate: 2015-07-15 22:59:52 +0200 (Wed, 15 Jul 2015) $
42
//----------------------------------------------------------------------------
43 103 olivier.gi
`ifdef OMSP_NO_INCLUDE
44
`else
45 23 olivier.gi
`include "openMSP430_defines.v"
46 103 olivier.gi
`endif
47 2 olivier.gi
 
48 34 olivier.gi
module  omsp_mem_backbone (
49 2 olivier.gi
 
50
// OUTPUTs
51 202 olivier.gi
    cpu_halt_cmd,                       // Halt CPU command
52
    dbg_mem_din,                        // Debug unit Memory data input
53
    dmem_addr,                          // Data Memory address
54
    dmem_cen,                           // Data Memory chip enable (low active)
55
    dmem_din,                           // Data Memory data input
56
    dmem_wen,                           // Data Memory write enable (low active)
57
    eu_mdb_in,                          // Execution Unit Memory data bus input
58
    fe_mdb_in,                          // Frontend Memory data bus input
59
    fe_pmem_wait,                       // Frontend wait for Instruction fetch
60
    dma_dout,                           // Direct Memory Access data output
61
    dma_ready,                          // Direct Memory Access is complete
62
    dma_resp,                           // Direct Memory Access response (0:Okay / 1:Error)
63
    per_addr,                           // Peripheral address
64
    per_din,                            // Peripheral data input
65
    per_we,                             // Peripheral write enable (high active)
66
    per_en,                             // Peripheral enable (high active)
67
    pmem_addr,                          // Program Memory address
68
    pmem_cen,                           // Program Memory chip enable (low active)
69
    pmem_din,                           // Program Memory data input (optional)
70
    pmem_wen,                           // Program Memory write enable (low active) (optional)
71 2 olivier.gi
 
72
// INPUTs
73 202 olivier.gi
    cpu_halt_st,                        // Halt/Run status from CPU
74
    dbg_halt_cmd,                       // Debug interface Halt CPU command
75
    dbg_mem_addr,                       // Debug address for rd/wr access
76
    dbg_mem_dout,                       // Debug unit data output
77
    dbg_mem_en,                         // Debug unit memory enable
78
    dbg_mem_wr,                         // Debug unit memory write
79
    dmem_dout,                          // Data Memory data output
80
    eu_mab,                             // Execution Unit Memory address bus
81
    eu_mb_en,                           // Execution Unit Memory bus enable
82
    eu_mb_wr,                           // Execution Unit Memory bus write transfer
83
    eu_mdb_out,                         // Execution Unit Memory data bus output
84
    fe_mab,                             // Frontend Memory address bus
85
    fe_mb_en,                           // Frontend Memory bus enable
86
    mclk,                               // Main system clock
87
    dma_addr,                           // Direct Memory Access address
88
    dma_din,                            // Direct Memory Access data input
89
    dma_en,                             // Direct Memory Access enable (high active)
90
    dma_priority,                       // Direct Memory Access priority (0:low / 1:high)
91
    dma_we,                             // Direct Memory Access write byte enable (high active)
92
    per_dout,                           // Peripheral data output
93
    pmem_dout,                          // Program Memory data output
94
    puc_rst,                            // Main system reset
95
    scan_enable                         // Scan enable (active during scan shifting)
96 2 olivier.gi
);
97
 
98
// OUTPUTs
99
//=========
100 202 olivier.gi
output               cpu_halt_cmd;      // Halt CPU command
101
output        [15:0] dbg_mem_din;       // Debug unit Memory data input
102
output [`DMEM_MSB:0] dmem_addr;         // Data Memory address
103
output               dmem_cen;          // Data Memory chip enable (low active)
104
output        [15:0] dmem_din;          // Data Memory data input
105
output         [1:0] dmem_wen;          // Data Memory write enable (low active)
106
output        [15:0] eu_mdb_in;         // Execution Unit Memory data bus input
107
output        [15:0] fe_mdb_in;         // Frontend Memory data bus input
108
output               fe_pmem_wait;      // Frontend wait for Instruction fetch
109
output        [15:0] dma_dout;          // Direct Memory Access data output
110
output               dma_ready;         // Direct Memory Access is complete
111
output               dma_resp;          // Direct Memory Access response (0:Okay / 1:Error)
112
output        [13:0] per_addr;          // Peripheral address
113
output        [15:0] per_din;           // Peripheral data input
114
output         [1:0] per_we;            // Peripheral write enable (high active)
115
output               per_en;            // Peripheral enable (high active)
116
output [`PMEM_MSB:0] pmem_addr;         // Program Memory address
117
output               pmem_cen;          // Program Memory chip enable (low active)
118
output        [15:0] pmem_din;          // Program Memory data input (optional)
119
output         [1:0] pmem_wen;          // Program Memory write enable (low active) (optional)
120 2 olivier.gi
 
121
// INPUTs
122
//=========
123 202 olivier.gi
input                cpu_halt_st;       // Halt/Run status from CPU
124
input                dbg_halt_cmd;      // Debug interface Halt CPU command
125
input         [15:1] dbg_mem_addr;      // Debug address for rd/wr access
126
input         [15:0] dbg_mem_dout;      // Debug unit data output
127
input                dbg_mem_en;        // Debug unit memory enable
128
input          [1:0] dbg_mem_wr;        // Debug unit memory write
129
input         [15:0] dmem_dout;         // Data Memory data output
130
input         [14:0] eu_mab;            // Execution Unit Memory address bus
131
input                eu_mb_en;          // Execution Unit Memory bus enable
132
input          [1:0] eu_mb_wr;          // Execution Unit Memory bus write transfer
133
input         [15:0] eu_mdb_out;        // Execution Unit Memory data bus output
134
input         [14:0] fe_mab;            // Frontend Memory address bus
135
input                fe_mb_en;          // Frontend Memory bus enable
136
input                mclk;              // Main system clock
137
input         [15:1] dma_addr;          // Direct Memory Access address
138
input         [15:0] dma_din;           // Direct Memory Access data input
139
input                dma_en;            // Direct Memory Access enable (high active)
140
input                dma_priority;      // Direct Memory Access priority (0:low / 1:high)
141
input          [1:0] dma_we;            // Direct Memory Access write byte enable (high active)
142
input         [15:0] per_dout;          // Peripheral data output
143
input         [15:0] pmem_dout;         // Program Memory data output
144
input                puc_rst;           // Main system reset
145
input                scan_enable;       // Scan enable (active during scan shifting)
146 2 olivier.gi
 
147 202 olivier.gi
wire                 ext_mem_en;
148
wire          [15:0] ext_mem_din;
149
wire                 ext_dmem_sel;
150
wire                 ext_dmem_en;
151
wire                 ext_pmem_sel;
152
wire                 ext_pmem_en;
153
wire                 ext_per_sel;
154
wire                 ext_per_en;
155 2 olivier.gi
 
156 202 olivier.gi
 
157 2 olivier.gi
//=============================================================================
158
// 1)  DECODER
159
//=============================================================================
160
 
161 202 olivier.gi
//------------------------------------------
162
// Arbiter between DMA and Debug interface
163
//------------------------------------------
164
`ifdef DMA_IF_EN
165 2 olivier.gi
 
166 202 olivier.gi
// Debug-interface always stops the CPU
167
// Master interface stops the CPU in priority mode
168
assign      cpu_halt_cmd  =  dbg_halt_cmd | (dma_en & dma_priority);
169
 
170
// Return ERROR response if address lays outside the memory spaces (Peripheral, Data & Program memories)
171
assign      dma_resp      = ~dbg_mem_en & ~(ext_dmem_sel | ext_pmem_sel | ext_per_sel) & dma_en;
172
 
173
// Master interface access is ready when the memory access occures
174
assign      dma_ready     = ~dbg_mem_en &  (ext_dmem_en  | ext_pmem_en  | ext_per_en | dma_resp);
175
 
176
// Use delayed version of 'dma_ready' to mask the 'dma_dout' data output
177
// when not accessed and reduce toggle rate (thus power consumption)
178
reg         dma_ready_dly;
179
always @ (posedge mclk or posedge puc_rst)
180
  if (puc_rst)  dma_ready_dly <=  1'b0;
181
  else          dma_ready_dly <=  dma_ready;
182
 
183
// Mux between debug and master interface
184
assign      ext_mem_en    =  dbg_mem_en | dma_en;
185
wire  [1:0] ext_mem_wr    =  dbg_mem_en ? dbg_mem_wr    :  dma_we;
186
wire [15:1] ext_mem_addr  =  dbg_mem_en ? dbg_mem_addr  :  dma_addr;
187
wire [15:0] ext_mem_dout  =  dbg_mem_en ? dbg_mem_dout  :  dma_din;
188
 
189
// External interface read data
190
assign      dbg_mem_din   =  ext_mem_din;
191
assign      dma_dout      =  ext_mem_din & {16{dma_ready_dly}};
192
 
193
 
194
`else
195
// Debug-interface always stops the CPU
196
assign      cpu_halt_cmd  =  dbg_halt_cmd;
197
 
198
// Master interface access is always ready with error response when excluded
199
assign      dma_resp      =  1'b1;
200
assign      dma_ready     =  1'b1;
201
 
202
// Debug interface only
203
assign      ext_mem_en    =  dbg_mem_en;
204
wire  [1:0] ext_mem_wr    =  dbg_mem_wr;
205
wire [15:1] ext_mem_addr  =  dbg_mem_addr;
206
wire [15:0] ext_mem_dout  =  dbg_mem_dout;
207
 
208
// External interface read data
209
assign      dbg_mem_din   =  ext_mem_din;
210
assign      dma_dout      =  16'h0000;
211
 
212
// LINT Cleanup
213
wire [15:1] UNUSED_dma_addr     = dma_addr;
214
wire [15:0] UNUSED_dma_din      = dma_din;
215
wire        UNUSED_dma_en       = dma_en;
216
wire        UNUSED_dma_priority = dma_priority;
217
wire  [1:0] UNUSED_dma_we       = dma_we;
218
 
219
`endif
220
 
221
//------------------------------------------
222
// DATA-MEMORY Interface
223
//------------------------------------------
224
parameter          DMEM_END      = `DMEM_BASE+`DMEM_SIZE;
225
 
226 2 olivier.gi
// Execution unit access
227 202 olivier.gi
wire               eu_dmem_sel   = (eu_mab>=(`DMEM_BASE>>1)) &
228
                                   (eu_mab< ( DMEM_END >>1));
229
wire               eu_dmem_en    = eu_mb_en & eu_dmem_sel;
230 111 olivier.gi
wire        [15:0] eu_dmem_addr  = {1'b0, eu_mab}-(`DMEM_BASE>>1);
231 2 olivier.gi
 
232 202 olivier.gi
// Front-end access
233
// -- not allowed to execute from data memory --
234 2 olivier.gi
 
235 202 olivier.gi
// External Master/Debug interface access
236
assign             ext_dmem_sel  = (ext_mem_addr[15:1]>=(`DMEM_BASE>>1)) &
237
                                   (ext_mem_addr[15:1]< ( DMEM_END >>1));
238
assign             ext_dmem_en   = ext_mem_en &  ext_dmem_sel & ~eu_dmem_en;
239
wire        [15:0] ext_dmem_addr = {1'b0, ext_mem_addr[15:1]}-(`DMEM_BASE>>1);
240 2 olivier.gi
 
241
 
242 202 olivier.gi
// Data-Memory Interface
243
wire               dmem_cen      = ~(ext_dmem_en | eu_dmem_en);
244
wire         [1:0] dmem_wen      =   ext_dmem_en ? ~ext_mem_wr                 : ~eu_mb_wr;
245
wire [`DMEM_MSB:0] dmem_addr     =   ext_dmem_en ?  ext_dmem_addr[`DMEM_MSB:0] :  eu_dmem_addr[`DMEM_MSB:0];
246
wire        [15:0] dmem_din      =   ext_dmem_en ?  ext_mem_dout               :  eu_mdb_out;
247
 
248
 
249
//------------------------------------------
250
// PROGRAM-MEMORY Interface
251
//------------------------------------------
252
 
253 33 olivier.gi
parameter          PMEM_OFFSET   = (16'hFFFF-`PMEM_SIZE+1);
254 2 olivier.gi
 
255
// Execution unit access (only read access are accepted)
256 202 olivier.gi
wire               eu_pmem_sel   = (eu_mab>=(PMEM_OFFSET>>1));
257
wire               eu_pmem_en    = eu_mb_en & ~|eu_mb_wr & eu_pmem_sel;
258 33 olivier.gi
wire        [15:0] eu_pmem_addr  = eu_mab-(PMEM_OFFSET>>1);
259 2 olivier.gi
 
260
// Front-end access
261 202 olivier.gi
wire               fe_pmem_sel   = (fe_mab>=(PMEM_OFFSET>>1));
262
wire               fe_pmem_en    = fe_mb_en & fe_pmem_sel;
263 33 olivier.gi
wire        [15:0] fe_pmem_addr  = fe_mab-(PMEM_OFFSET>>1);
264 2 olivier.gi
 
265 202 olivier.gi
// External Master/Debug interface access
266
assign             ext_pmem_sel  = (ext_mem_addr[15:1]>=(PMEM_OFFSET>>1));
267
assign             ext_pmem_en   = ext_mem_en & ext_pmem_sel & ~eu_pmem_en & ~fe_pmem_en;
268
wire        [15:0] ext_pmem_addr = {1'b0, ext_mem_addr[15:1]}-(PMEM_OFFSET>>1);
269 2 olivier.gi
 
270
 
271 202 olivier.gi
// Program-Memory Interface (Execution unit has priority over the Front-end)
272
wire               pmem_cen      = ~(fe_pmem_en | eu_pmem_en | ext_pmem_en);
273
wire         [1:0] pmem_wen      =  ext_pmem_en ? ~ext_mem_wr                 : 2'b11;
274
wire [`PMEM_MSB:0] pmem_addr     =  ext_pmem_en ?  ext_pmem_addr[`PMEM_MSB:0] :
275
                                    eu_pmem_en  ?  eu_pmem_addr[`PMEM_MSB:0]  : fe_pmem_addr[`PMEM_MSB:0];
276
wire        [15:0] pmem_din      =  ext_mem_dout;
277 2 olivier.gi
 
278 202 olivier.gi
wire               fe_pmem_wait  = (fe_pmem_en & eu_pmem_en);
279 2 olivier.gi
 
280
 
281 202 olivier.gi
//------------------------------------------
282
// PERIPHERALS Interface
283
//------------------------------------------
284 2 olivier.gi
 
285 202 olivier.gi
// Execution unit access
286
wire               eu_per_sel    =  (eu_mab<(`PER_SIZE>>1));
287
wire               eu_per_en     =  eu_mb_en & eu_per_sel;
288
 
289
// Front-end access
290
// -- not allowed to execute from peripherals memory space --
291
 
292
// External Master/Debug interface access
293
assign             ext_per_sel   =  (ext_mem_addr[15:1]<(`PER_SIZE>>1));
294
assign             ext_per_en    =  ext_mem_en & ext_per_sel & ~eu_per_en;
295
 
296
// Peripheral Interface
297
wire               per_en        =  ext_per_en | eu_per_en;
298
wire         [1:0] per_we        =  ext_per_en ? ext_mem_wr                 : eu_mb_wr;
299
wire  [`PER_MSB:0] per_addr_mux  =  ext_per_en ? ext_mem_addr[`PER_MSB+1:1] : eu_mab[`PER_MSB:0];
300
wire        [14:0] per_addr_ful  =  {{15-`PER_AWIDTH{1'b0}}, per_addr_mux};
301
wire        [13:0] per_addr      =  per_addr_ful[13:0];
302
wire        [15:0] per_din       =  ext_per_en ? ext_mem_dout               : eu_mdb_out;
303
 
304
// Register peripheral data read path
305 2 olivier.gi
reg   [15:0] per_dout_val;
306 111 olivier.gi
always @ (posedge mclk or posedge puc_rst)
307 202 olivier.gi
  if (puc_rst)  per_dout_val    <=  16'h0000;
308
  else          per_dout_val    <=  per_dout;
309 2 olivier.gi
 
310
 
311 202 olivier.gi
//------------------------------------------
312 2 olivier.gi
// Frontend data Mux
313 202 olivier.gi
//------------------------------------------
314
// Whenever the frontend doesn't access the program memory,  backup the data
315 2 olivier.gi
 
316
// Detect whenever the data should be backuped and restored
317 202 olivier.gi
reg         fe_pmem_en_dly;
318 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
319 202 olivier.gi
  if (puc_rst) fe_pmem_en_dly <=  1'b0;
320
  else         fe_pmem_en_dly <=  fe_pmem_en;
321 2 olivier.gi
 
322 202 olivier.gi
wire fe_pmem_save    = (~fe_pmem_en &  fe_pmem_en_dly) & ~cpu_halt_st;
323
wire fe_pmem_restore = ( fe_pmem_en & ~fe_pmem_en_dly) |  cpu_halt_st;
324 134 olivier.gi
 
325
`ifdef CLOCK_GATING
326 205 olivier.gi
wire mclk_bckup_gated;
327
omsp_clock_gate clock_gate_bckup (.gclk(mclk_bckup_gated),
328 134 olivier.gi
                                  .clk (mclk), .enable(fe_pmem_save), .scan_enable(scan_enable));
329 205 olivier.gi
`define MCLK_BCKUP           mclk_bckup_gated
330 134 olivier.gi
`else
331 205 olivier.gi
wire    UNUSED_scan_enable = scan_enable;
332
`define MCLK_BCKUP           mclk        // use macro to solve delta cycle issues with some mixed VHDL/Verilog simulators
333 134 olivier.gi
`endif
334 202 olivier.gi
 
335 33 olivier.gi
reg  [15:0] pmem_dout_bckup;
336 205 olivier.gi
always @(posedge `MCLK_BCKUP or posedge puc_rst)
337 202 olivier.gi
  if (puc_rst)              pmem_dout_bckup     <=  16'h0000;
338 134 olivier.gi
`ifdef CLOCK_GATING
339 202 olivier.gi
  else                      pmem_dout_bckup     <=  pmem_dout;
340 134 olivier.gi
`else
341 202 olivier.gi
  else if (fe_pmem_save)    pmem_dout_bckup     <=  pmem_dout;
342 134 olivier.gi
`endif
343 2 olivier.gi
 
344 202 olivier.gi
// Mux between the Program memory data and the backup
345 33 olivier.gi
reg         pmem_dout_bckup_sel;
346 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
347
  if (puc_rst)              pmem_dout_bckup_sel <=  1'b0;
348 33 olivier.gi
  else if (fe_pmem_save)    pmem_dout_bckup_sel <=  1'b1;
349
  else if (fe_pmem_restore) pmem_dout_bckup_sel <=  1'b0;
350 202 olivier.gi
 
351 33 olivier.gi
assign fe_mdb_in = pmem_dout_bckup_sel ? pmem_dout_bckup : pmem_dout;
352 2 olivier.gi
 
353
 
354 202 olivier.gi
//------------------------------------------
355 2 olivier.gi
// Execution-Unit data Mux
356 202 olivier.gi
//------------------------------------------
357 2 olivier.gi
 
358 202 olivier.gi
// Select between Peripherals, Program and Data memories
359 2 olivier.gi
reg [1:0] eu_mdb_in_sel;
360 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
361 202 olivier.gi
  if (puc_rst)  eu_mdb_in_sel  <= 2'b00;
362
  else          eu_mdb_in_sel  <= {eu_pmem_en, eu_per_en};
363 2 olivier.gi
 
364
// Mux
365 202 olivier.gi
assign          eu_mdb_in       = eu_mdb_in_sel[1] ? pmem_dout    :
366
                                  eu_mdb_in_sel[0] ? per_dout_val : dmem_dout;
367 2 olivier.gi
 
368
 
369 202 olivier.gi
//------------------------------------------
370
// External Master/Debug interface data Mux
371
//------------------------------------------
372
 
373
// Select between Peripherals, Program and Data memories
374
reg   [1:0] ext_mem_din_sel;
375 111 olivier.gi
always @(posedge mclk or posedge puc_rst)
376 202 olivier.gi
  if (puc_rst)  ext_mem_din_sel <= 2'b00;
377
  else          ext_mem_din_sel <= {ext_pmem_en, ext_per_en};
378 2 olivier.gi
 
379
// Mux
380 202 olivier.gi
assign          ext_mem_din      = ext_mem_din_sel[1] ? pmem_dout    :
381
                                   ext_mem_din_sel[0] ? per_dout_val : dmem_dout;
382 2 olivier.gi
 
383 202 olivier.gi
 
384 34 olivier.gi
endmodule // omsp_mem_backbone
385 2 olivier.gi
 
386 103 olivier.gi
`ifdef OMSP_NO_INCLUDE
387
`else
388 33 olivier.gi
`include "openMSP430_undefines.v"
389 103 olivier.gi
`endif

powered by: WebSVN 2.1.0

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