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

Subversion Repositories 8051

[/] [8051/] [trunk/] [rtl/] [verilog/] [oc8051_memory_interface.v] - Blame information for rev 181

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

Line No. Rev Author Line
1 81 simont
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  8051 memory interface                                       ////
4
////                                                              ////
5
////  This file is part of the 8051 cores project                 ////
6
////  http://www.opencores.org/cores/8051/                        ////
7
////                                                              ////
8
////  Description                                                 ////
9
////   comunication betwen cpu and memory                         ////
10
////                                                              ////
11
////  To Do:                                                      ////
12
////   nothing                                                    ////
13
////                                                              ////
14
////  Author(s):                                                  ////
15
////      - Simon Teran, simont@opencores.org                     ////
16
////                                                              ////
17
//////////////////////////////////////////////////////////////////////
18
////                                                              ////
19
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
20
////                                                              ////
21
//// This source file may be used and distributed without         ////
22
//// restriction provided that this copyright statement is not    ////
23
//// removed from the file and that any derivative work contains  ////
24
//// the original copyright notice and the associated disclaimer. ////
25
////                                                              ////
26
//// This source file is free software; you can redistribute it   ////
27
//// and/or modify it under the terms of the GNU Lesser General   ////
28
//// Public License as published by the Free Software Foundation; ////
29
//// either version 2.1 of the License, or (at your option) any   ////
30
//// later version.                                               ////
31
////                                                              ////
32
//// This source is distributed in the hope that it will be       ////
33
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
34
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
35
//// PURPOSE.  See the GNU Lesser General Public License for more ////
36
//// details.                                                     ////
37
////                                                              ////
38
//// You should have received a copy of the GNU Lesser General    ////
39
//// Public License along with this source; if not, download it   ////
40
//// from http://www.opencores.org/lgpl.shtml                     ////
41
////                                                              ////
42
//////////////////////////////////////////////////////////////////////
43
//
44
// CVS Revision History
45
//
46
// $Log: not supported by cvs2svn $
47 181 simont
// Revision 1.12  2003/07/01 20:47:39  simont
48
// add /* synopsys xx_case */ to case statments.
49
//
50 179 simont
// Revision 1.11  2003/06/20 13:35:10  simont
51
// simualtion `ifdef added
52
//
53 173 simont
// Revision 1.10  2003/06/05 11:15:02  simont
54
// fix bug.
55
//
56 158 simont
// Revision 1.9  2003/06/03 17:09:57  simont
57
// pipelined acces to axternal instruction interface added.
58
//
59 149 simont
// Revision 1.8  2003/05/12 16:27:40  simont
60
// fix bug in movc intruction.
61
//
62 146 simont
// Revision 1.7  2003/05/06 09:39:34  simont
63
// cahnge assigment to pc_wait (remove istb_o)
64
//
65 140 simont
// Revision 1.6  2003/05/05 15:46:37  simont
66
// add aditional alu destination to solve critical path.
67
//
68 139 simont
// Revision 1.5  2003/04/25 17:15:51  simont
69
// change branch instruction execution (reduse needed clock periods).
70
//
71 132 simont
// Revision 1.4  2003/04/16 10:04:09  simont
72
// chance idat_ir to 24 bit wide
73
//
74 128 simont
// Revision 1.3  2003/04/11 10:05:08  simont
75
// Change pc add value from 23'h to 16'h
76
//
77 121 simont
// Revision 1.2  2003/04/09 16:24:03  simont
78
// change wr_sft to 2 bit wire.
79
//
80 118 simont
// Revision 1.1  2003/01/13 14:13:12  simont
81
// initial import
82 81 simont
//
83 118 simont
//
84 81 simont
 
85
// synopsys translate_off
86
`include "oc8051_timescale.v"
87
// synopsys translate_on
88
 
89
`include "oc8051_defines.v"
90
 
91
 
92
module oc8051_memory_interface (clk, rst,
93 149 simont
 
94 81 simont
//decoder
95 149 simont
     wr_i,
96
     wr_bit_i,
97
     rd_sel,
98
     wr_sel,
99
     pc_wr_sel,
100
     pc_wr,
101
     pc,
102
     rd,
103
     mem_wait,
104
     mem_act,
105
     istb,
106
 
107 81 simont
//internal ram
108 149 simont
     wr_o,
109
     wr_bit_o,
110
     rd_addr,
111
     wr_addr,
112
     rd_ind,
113
     wr_ind,
114
     wr_dat,
115 81 simont
 
116 149 simont
     bit_in,
117
     in_ram,
118
     sfr,
119
     sfr_bit,
120
     bit_out,
121
     iram_out,
122 81 simont
 
123
//program rom
124 149 simont
     iadr_o,
125
     ea,
126
     ea_int,
127
     op1_out,
128
     op2_out,
129
     op3_out,
130
 
131 81 simont
//internal
132 149 simont
     idat_onchip,
133
 
134 81 simont
//external
135 149 simont
     iack_i,
136
     istb_o,
137
     idat_i,
138 81 simont
 
139
//external data ram
140 149 simont
     dadr_o,
141
     dwe_o,
142
     dstb_o,
143 173 simont
     dack_i,
144 149 simont
     ddat_i,
145
     ddat_o,
146
 
147 81 simont
//interrupt interface
148 149 simont
     intr,
149
     int_v,
150
     int_ack,
151 81 simont
 
152
//alu
153 149 simont
     des_acc,
154
     des1,
155
     des2,
156 81 simont
 
157
//sfr's
158 149 simont
     dptr,
159
     ri,
160
     sp,
161
     sp_w,
162
     rn,
163
     acc,
164
     reti
165
   );
166 81 simont
 
167
 
168 149 simont
input         clk,
169
              rst,
170
              wr_i,
171
              wr_bit_i;
172 81 simont
 
173 149 simont
input         bit_in,
174
              sfr_bit,
175
              dack_i;
176
input [2:0]   mem_act;
177
input [7:0]   in_ram,
178
              sfr,
179
              acc,
180
              sp_w;
181
input [31:0]  idat_i;
182 81 simont
 
183 149 simont
output        bit_out,
184
              mem_wait,
185
              reti;
186
output [7:0]  iram_out,
187
              wr_dat;
188
 
189
reg           bit_out,
190
              reti;
191
reg [7:0]     iram_out,
192
              sp_r;
193
reg           rd_addr_r;
194
output        wr_o,
195
              wr_bit_o;
196
 
197 81 simont
//????
198 149 simont
reg           dack_ir;
199
reg [7:0]     ddat_ir;
200
reg [23:0]    idat_ir;
201 81 simont
 
202
/////////////////////////////
203
//
204
//  rom_addr_sel
205
//
206
/////////////////////////////
207 149 simont
input         iack_i;
208
input [7:0]   des_acc,
209
              des1,
210
              des2;
211 81 simont
output [15:0] iadr_o;
212
 
213 149 simont
wire          ea_rom_sel;
214 81 simont
 
215
/////////////////////////////
216
//
217
// ext_addr_sel
218
//
219
/////////////////////////////
220 149 simont
input [7:0]   ri,
221
              ddat_i;
222
input [15:0]  dptr;
223 81 simont
 
224 149 simont
output        dstb_o,
225
              dwe_o;
226
output [7:0]  ddat_o;
227 81 simont
output [15:0] dadr_o;
228
 
229
/////////////////////////////
230
//
231
// ram_adr_sel
232
//
233
/////////////////////////////
234
 
235 149 simont
input [2:0]   rd_sel,
236
              wr_sel;
237
input [4:0]   rn;
238
input [7:0]   sp;
239 81 simont
 
240 149 simont
output        rd_ind,
241
              wr_ind;
242
output [7:0]  wr_addr,
243
              rd_addr;
244
reg           rd_ind,
245
              wr_ind;
246
reg [7:0]     wr_addr,
247
              rd_addr;
248 81 simont
 
249 149 simont
reg [4:0]     rn_r;
250
reg [7:0]     ri_r,
251
              imm_r,
252
              imm2_r,
253
              op1_r;
254
wire [7:0]    imm,
255
              imm2;
256 81 simont
 
257
/////////////////////////////
258
//
259
// op_select
260
//
261
/////////////////////////////
262
 
263 149 simont
input         intr,
264
              rd,
265
              ea,
266
              ea_int,
267
              istb;
268 81 simont
 
269 149 simont
input  [7:0]  int_v;
270 81 simont
 
271 149 simont
input  [31:0] idat_onchip;
272 81 simont
 
273 149 simont
output        int_ack,
274
              istb_o;
275 81 simont
 
276 149 simont
output  [7:0] op1_out,
277
              op3_out,
278
              op2_out;
279
 
280
reg           int_ack_t,
281
              int_ack,
282
              int_ack_buff;
283
 
284
reg [7:0]     int_vec_buff;
285
reg [7:0]     op1_out,
286
              op2_buff,
287
              op3_buff;
288
reg [7:0]     op1_o,
289
              op2_o,
290
              op3_o;
291
 
292
reg [7:0]     op1_xt,
293
              op2_xt,
294
              op3_xt;
295
 
296
reg [7:0]     op1,
297
              op2,
298
              op3;
299
wire [7:0]    op2_direct;
300
 
301
input [2:0]   pc_wr_sel;
302
 
303
input         pc_wr;
304 81 simont
output [15:0] pc;
305
 
306 149 simont
reg [15:0]    pc;
307 81 simont
 
308
//
309
//pc            program counter register, save current value
310 149 simont
reg [15:0]    pc_buf;
311
wire [15:0]   alu;
312 81 simont
 
313
 
314 149 simont
reg           int_buff,
315
              int_buff1; // interrupt buffer: used to prevent interrupting in the middle of executin instructions
316 81 simont
 
317 149 simont
 
318 81 simont
//
319
//
320
////////////////////////////
321 149 simont
reg           istb_t,
322
              imem_wait,
323
              dstb_o,
324
              dwe_o;
325 81 simont
 
326 149 simont
reg [7:0]     ddat_o;
327
reg [15:0]    iadr_t,
328
              dadr_ot;
329
reg           dmem_wait;
330
wire          pc_wait;
331
wire [1:0]    bank;
332
wire [7:0]    isr_call;
333
 
334
reg [1:0]     op_length;
335
reg [2:0]     op_pos;
336
wire          inc_pc;
337
 
338
reg           pc_wr_r;
339
 
340
wire [15:0]   pc_out;
341
 
342
reg [31:0]    idat_cur,
343
              idat_old;
344
 
345
reg           inc_pc_r,
346
              pc_wr_r2;
347
 
348
reg [7:0]     cdata;
349
reg           cdone;
350
 
351
 
352
assign bank       = rn[4:3];
353
assign imm        = op2_out;
354
assign imm2       = op3_out;
355
assign alu        = {des2, des_acc};
356 81 simont
assign ea_rom_sel = ea && ea_int;
357 149 simont
assign wr_o       = wr_i;
358
assign wr_bit_o   = wr_bit_i;
359 81 simont
 
360 149 simont
//assign mem_wait   = dmem_wait || imem_wait || pc_wr_r;
361
assign mem_wait   = dmem_wait || imem_wait || pc_wr_r2;
362
//assign mem_wait   = dmem_wait || imem_wait;
363
assign istb_o     = (istb || (istb_t & !iack_i)) && !dstb_o && !ea_rom_sel;
364 81 simont
 
365 149 simont
assign pc_wait    = rd && (ea_rom_sel || (!istb_t && iack_i));
366 81 simont
 
367 149 simont
assign wr_dat     = des1;
368 81 simont
 
369
 
370 173 simont
`ifdef OC8051_SIMULATION
371
  always @(negedge rst) begin
372
    #5
373
    if (ea_rom_sel)
374
      $display("   progran execution from external rom");
375
    else
376
      $display("   progran execution from internal rom");
377
  end
378
 
379
`endif
380
 
381
 
382 81 simont
/////////////////////////////
383
//
384
//  ram_select
385
//
386 140 simont
/////////////////////////////
387 139 simont
always @(rd_addr_r or in_ram or sfr or bit_in or sfr_bit or rd_ind)
388 81 simont
begin
389 139 simont
  if (rd_addr_r && !rd_ind) begin
390 81 simont
    iram_out = sfr;
391
    bit_out = sfr_bit;
392
  end else begin
393
    iram_out = in_ram;
394
    bit_out = bit_in;
395
  end
396
end
397
 
398
/////////////////////////////
399
//
400
// ram_adr_sel
401
//
402
/////////////////////////////
403
 
404 140 simont
always @(rd_sel or sp or ri or rn or imm or dadr_o[15:0] or bank)
405 81 simont
begin
406 179 simont
  case (rd_sel) /* synopsys full_case parallel_case */
407 139 simont
    `OC8051_RRS_RN   : rd_addr = {3'h0, rn};
408
    `OC8051_RRS_I    : rd_addr = ri;
409
    `OC8051_RRS_D    : rd_addr = imm;
410
    `OC8051_RRS_SP   : rd_addr = sp;
411 81 simont
 
412 139 simont
    `OC8051_RRS_B    : rd_addr = `OC8051_SFR_B;
413
    `OC8051_RRS_DPTR : rd_addr = `OC8051_SFR_DPTR_LO;
414
    `OC8051_RRS_PSW  : rd_addr = `OC8051_SFR_PSW;
415
    `OC8051_RRS_ACC  : rd_addr = `OC8051_SFR_ACC;
416 179 simont
//    default          : rd_addr = 2'bxx;
417 139 simont
  endcase
418 81 simont
 
419
end
420
 
421
 
422
//
423
//
424
always @(wr_sel or sp_w or rn_r or imm_r or ri_r or imm2_r or op1_r or dadr_o[15:0])
425
begin
426 179 simont
  case (wr_sel) /* synopsys full_case parallel_case */
427 139 simont
    `OC8051_RWS_RN : wr_addr = {3'h0, rn_r};
428
    `OC8051_RWS_I  : wr_addr = ri_r;
429
    `OC8051_RWS_D  : wr_addr = imm_r;
430
    `OC8051_RWS_SP : wr_addr = sp_w;
431
    `OC8051_RWS_D3 : wr_addr = imm2_r;
432
    `OC8051_RWS_B  : wr_addr = `OC8051_SFR_B;
433 179 simont
//    default        : wr_addr = 2'bxx;
434 139 simont
  endcase
435 81 simont
end
436
 
437
always @(posedge clk or posedge rst)
438
  if (rst)
439
    rd_ind <= #1 1'b0;
440
  else if ((rd_sel==`OC8051_RRS_I) || (rd_sel==`OC8051_RRS_SP))
441
    rd_ind <= #1 1'b1;
442
  else
443
    rd_ind <= #1 1'b0;
444
 
445
always @(wr_sel)
446
  if ((wr_sel==`OC8051_RWS_I) || (wr_sel==`OC8051_RWS_SP))
447
    wr_ind = 1'b1;
448
  else
449
    wr_ind = 1'b0;
450
 
451
 
452
/////////////////////////////
453
//
454
//  rom_addr_sel
455
//
456
/////////////////////////////
457
//
458
// output address is alu destination
459
// (instructions MOVC)
460
 
461 149 simont
//assign iadr_o = (istb_t & !iack_i) ? iadr_t : pc_out;
462
assign iadr_o = (istb_t) ? iadr_t : pc_out;
463 81 simont
 
464
 
465
always @(posedge clk or posedge rst)
466
begin
467
  if (rst) begin
468
    iadr_t <= #1 23'h0;
469
    istb_t <= #1 1'b0;
470
    imem_wait <= #1 1'b0;
471
    idat_ir <= #1 24'h0;
472
  end else if (mem_act==`OC8051_MAS_CODE) begin
473 139 simont
    iadr_t <= #1 alu;
474 81 simont
    istb_t <= #1 1'b1;
475
    imem_wait <= #1 1'b1;
476 149 simont
  end else if (ea_rom_sel && imem_wait) begin
477
    imem_wait <= #1 1'b0;
478
  end else if (!imem_wait && istb_t) begin
479
    istb_t <= #1 1'b0;
480
  end else if (iack_i) begin
481
    imem_wait <= #1 1'b0;
482
    idat_ir <= #1 idat_i [23:0];
483 81 simont
  end
484
end
485
 
486
/////////////////////////////
487
//
488
// ext_addr_sel
489
//
490
/////////////////////////////
491
 
492
assign dadr_o = dadr_ot;
493
 
494
always @(posedge clk or posedge rst)
495
begin
496
  if (rst) begin
497
    dwe_o <= #1 1'b0;
498
    dmem_wait <= #1 1'b0;
499
    dstb_o <= #1 1'b0;
500
    ddat_o <= #1 8'h00;
501
    dadr_ot <= #1 23'h0;
502
  end else if (dack_i) begin
503
    dwe_o <= #1 1'b0;
504
    dstb_o <= #1 1'b0;
505
    dmem_wait <= #1 1'b0;
506
  end else begin
507 179 simont
    case (mem_act) /* synopsys full_case parallel_case */
508 81 simont
      `OC8051_MAS_DPTR_R: begin  // read from external rom: acc=(dptr)
509
        dwe_o <= #1 1'b0;
510
        dstb_o <= #1 1'b1;
511
        ddat_o <= #1 8'h00;
512
        dadr_ot <= #1 {7'h0, dptr};
513
        dmem_wait <= #1 1'b1;
514
      end
515
      `OC8051_MAS_DPTR_W: begin  // write to external rom: (dptr)=acc
516
        dwe_o <= #1 1'b1;
517
        dstb_o <= #1 1'b1;
518
        ddat_o <= #1 acc;
519
        dadr_ot <= #1 {7'h0, dptr};
520
        dmem_wait <= #1 1'b1;
521
      end
522
      `OC8051_MAS_RI_R:   begin  // read from external rom: acc=(Ri)
523
        dwe_o <= #1 1'b0;
524
        dstb_o <= #1 1'b1;
525
        ddat_o <= #1 8'h00;
526
        dadr_ot <= #1 {15'h0, ri};
527
        dmem_wait <= #1 1'b1;
528
      end
529
      `OC8051_MAS_RI_W: begin    // write to external rom: (Ri)=acc
530
        dwe_o <= #1 1'b1;
531
        dstb_o <= #1 1'b1;
532
        ddat_o <= #1 acc;
533
        dadr_ot <= #1 {15'h0, ri};
534
        dmem_wait <= #1 1'b1;
535
      end
536
    endcase
537
  end
538
end
539
 
540
/////////////////////////////
541
//
542
// op_select
543
//
544
/////////////////////////////
545
 
546
 
547
 
548 149 simont
always @(posedge clk or posedge rst)
549
begin
550
  if (rst) begin
551
    idat_cur <= #1 32'h0;
552
    idat_old <= #1 32'h0;
553
  end else if ((iack_i | ea_rom_sel) & (inc_pc | pc_wr_r2)) begin
554
    idat_cur <= #1 ea_rom_sel ? idat_onchip : idat_i;
555
    idat_old <= #1 idat_cur;
556
  end
557 81 simont
 
558 149 simont
end
559
 
560
always @(posedge clk or posedge rst)
561
begin
562
  if (rst) begin
563
    cdata <= #1 8'h00;
564
    cdone <= #1 1'b0;
565
  end else if (istb_t) begin
566
    cdata <= #1 ea_rom_sel ? idat_onchip[7:0] : idat_i[7:0];
567
    cdone <= #1 1'b1;
568
  end else begin
569
    cdone <= #1 1'b0;
570
  end
571
end
572
 
573
always @(op_pos or idat_cur or idat_old)
574
begin
575 179 simont
  case (op_pos)  /* synopsys parallel_case */
576 149 simont
    3'b000: begin
577
       op1 = idat_old[7:0]  ;
578
       op2 = idat_old[15:8] ;
579
       op3 = idat_old[23:16];
580
      end
581
    3'b001: begin
582
       op1 = idat_old[15:8] ;
583
       op2 = idat_old[23:16];
584
       op3 = idat_old[31:24];
585
      end
586
    3'b010: begin
587
       op1 = idat_old[23:16];
588
       op2 = idat_old[31:24];
589
       op3 = idat_cur[7:0]  ;
590
      end
591
    3'b011: begin
592
       op1 = idat_old[31:24];
593
       op2 = idat_cur[7:0]  ;
594
       op3 = idat_cur[15:8] ;
595
      end
596
    3'b100: begin
597
       op1 = idat_cur[7:0]  ;
598
       op2 = idat_cur[15:8] ;
599
       op3 = idat_cur[23:16];
600
      end
601
    default: begin
602
       op1 = idat_cur[15:8] ;
603
       op2 = idat_cur[23:16];
604
       op3 = idat_cur[31:24];
605
      end
606
  endcase
607
end
608
 
609
/*assign op1 = ea_rom_sel ? idat_onchip[7:0]   : op1_xt;
610
assign op2 = ea_rom_sel ? idat_onchip[15:8]  : op2_xt;
611
assign op3 = ea_rom_sel ? idat_onchip[23:16] : op3_xt;*/
612
 
613
 
614
always @(dack_ir or ddat_ir or op1_o or iram_out or cdone or cdata)
615 81 simont
  if (dack_ir)
616
    op1_out = ddat_ir;
617 149 simont
  else if (cdone)
618
    op1_out = cdata;
619 81 simont
  else
620
    op1_out = op1_o;
621
 
622
assign op3_out = (rd) ? op3_o : op3_buff;
623
assign op2_out = (rd) ? op2_o : op2_buff;
624
 
625
always @(idat_i or iack_i or idat_ir or rd)
626
begin
627
  if (iack_i) begin
628 128 simont
    op1_xt = idat_i[7:0];
629
    op2_xt = idat_i[15:8];
630
    op3_xt = idat_i[23:16];
631 81 simont
  end else if (!rd) begin
632 128 simont
    op1_xt = idat_ir[7:0];
633 81 simont
    op2_xt = idat_ir[15:8];
634 128 simont
    op3_xt = idat_ir[23:16];
635 81 simont
  end else begin
636
    op1_xt = 8'h00;
637
    op2_xt = 8'h00;
638
    op3_xt = 8'h00;
639
  end
640
end
641
 
642
 
643
//
644
// in case of interrupts
645
always @(op1 or op2 or op3 or int_ack_t or int_vec_buff or iack_i or ea_rom_sel)
646
begin
647
  if (int_ack_t && (iack_i || ea_rom_sel)) begin
648
    op1_o = `OC8051_LCALL;
649
    op2_o = 8'h00;
650
    op3_o = int_vec_buff;
651
  end else begin
652
    op1_o = op1;
653
    op2_o = op2;
654
    op3_o = op3;
655
  end
656
end
657
 
658
//
659
//in case of reti
660
always @(posedge clk or posedge rst)
661
  if (rst) reti <= #1 1'b0;
662 149 simont
  else if ((op1_o==`OC8051_RETI) & rd & !mem_wait) reti <= #1 1'b1;
663 81 simont
  else reti <= #1 1'b0;
664
 
665
//
666
// remember inputs
667
always @(posedge clk or posedge rst)
668
begin
669
  if (rst) begin
670
    op2_buff <= #1 8'h0;
671
    op3_buff <= #1 8'h0;
672
  end else if (rd) begin
673
    op2_buff <= #1 op2_o;
674
    op3_buff <= #1 op3_o;
675
  end
676
end
677
 
678 149 simont
/////////////////////////////
679 81 simont
//
680 149 simont
//  pc
681
//
682
/////////////////////////////
683
 
684
always @(op1_out)
685
begin
686 179 simont
        casex (op1_out) /* synopsys parallel_case */
687 149 simont
          `OC8051_ACALL :  op_length = 2'h2;
688
          `OC8051_AJMP :   op_length = 2'h2;
689
 
690
        //op_code [7:3]
691
          `OC8051_CJNE_R : op_length = 2'h3;
692
          `OC8051_DJNZ_R : op_length = 2'h2;
693
          `OC8051_MOV_DR : op_length = 2'h2;
694
          `OC8051_MOV_CR : op_length = 2'h2;
695
          `OC8051_MOV_RD : op_length = 2'h2;
696
 
697
        //op_code [7:1]
698
          `OC8051_CJNE_I : op_length = 2'h3;
699
          `OC8051_MOV_ID : op_length = 2'h2;
700
          `OC8051_MOV_DI : op_length = 2'h2;
701
          `OC8051_MOV_CI : op_length = 2'h2;
702
 
703
        //op_code [7:0]
704
          `OC8051_ADD_D :  op_length = 2'h2;
705
          `OC8051_ADD_C :  op_length = 2'h2;
706
          `OC8051_ADDC_D : op_length = 2'h2;
707
          `OC8051_ADDC_C : op_length = 2'h2;
708
          `OC8051_ANL_D :  op_length = 2'h2;
709
          `OC8051_ANL_C :  op_length = 2'h2;
710
          `OC8051_ANL_DD : op_length = 2'h2;
711
          `OC8051_ANL_DC : op_length = 2'h3;
712
          `OC8051_ANL_B :  op_length = 2'h2;
713
          `OC8051_ANL_NB : op_length = 2'h2;
714
          `OC8051_CJNE_D : op_length = 2'h3;
715
          `OC8051_CJNE_C : op_length = 2'h3;
716
          `OC8051_CLR_B :  op_length = 2'h2;
717
          `OC8051_CPL_B :  op_length = 2'h2;
718
          `OC8051_DEC_D :  op_length = 2'h2;
719
          `OC8051_DJNZ_D : op_length = 2'h3;
720
          `OC8051_INC_D :  op_length = 2'h2;
721
          `OC8051_JB :     op_length = 2'h3;
722
          `OC8051_JBC :    op_length = 2'h3;
723
          `OC8051_JC :     op_length = 2'h2;
724
          `OC8051_JNB :    op_length = 2'h3;
725
          `OC8051_JNC :    op_length = 2'h2;
726
          `OC8051_JNZ :    op_length = 2'h2;
727
          `OC8051_JZ :     op_length = 2'h2;
728
          `OC8051_LCALL :  op_length = 2'h3;
729
          `OC8051_LJMP :   op_length = 2'h3;
730
          `OC8051_MOV_D :  op_length = 2'h2;
731
          `OC8051_MOV_C :  op_length = 2'h2;
732
          `OC8051_MOV_DA : op_length = 2'h2;
733
          `OC8051_MOV_DD : op_length = 2'h3;
734
          `OC8051_MOV_CD : op_length = 2'h3;
735
          `OC8051_MOV_BC : op_length = 2'h2;
736
          `OC8051_MOV_CB : op_length = 2'h2;
737
          `OC8051_MOV_DP : op_length = 2'h3;
738
          `OC8051_ORL_D :  op_length = 2'h2;
739
          `OC8051_ORL_C :  op_length = 2'h2;
740
          `OC8051_ORL_AD : op_length = 2'h2;
741
          `OC8051_ORL_CD : op_length = 2'h3;
742
          `OC8051_ORL_B :  op_length = 2'h2;
743
          `OC8051_ORL_NB : op_length = 2'h2;
744
          `OC8051_POP :    op_length = 2'h2;
745
          `OC8051_PUSH :   op_length = 2'h2;
746
          `OC8051_SETB_B : op_length = 2'h2;
747
          `OC8051_SJMP :   op_length = 2'h2;
748
          `OC8051_SUBB_D : op_length = 2'h2;
749
          `OC8051_SUBB_C : op_length = 2'h2;
750
          `OC8051_XCH_D :  op_length = 2'h2;
751
          `OC8051_XRL_D :  op_length = 2'h2;
752
          `OC8051_XRL_C :  op_length = 2'h2;
753
          `OC8051_XRL_AD : op_length = 2'h2;
754
          `OC8051_XRL_CD : op_length = 2'h3;
755
          default:         op_length = 2'h1;
756
        endcase
757
end
758
 
759
/*
760
always @(posedge clk or posedge rst)
761
begin
762
    if (rst) begin
763
      op_length = 2'h2;
764
//    end else if (pc_wait) begin
765
    end else begin
766
        casex (op1_out)
767
          `OC8051_ACALL :  op_length <= #1 2'h2;
768
          `OC8051_AJMP :   op_length <= #1 2'h2;
769
 
770
        //op_code [7:3]
771
          `OC8051_CJNE_R : op_length <= #1 2'h3;
772
          `OC8051_DJNZ_R : op_length <= #1 2'h2;
773
          `OC8051_MOV_DR : op_length <= #1 2'h2;
774
          `OC8051_MOV_CR : op_length <= #1 2'h2;
775
          `OC8051_MOV_RD : op_length <= #1 2'h2;
776
 
777
        //op_code [7:1]
778
          `OC8051_CJNE_I : op_length <= #1 2'h3;
779
          `OC8051_MOV_ID : op_length <= #1 2'h2;
780
          `OC8051_MOV_DI : op_length <= #1 2'h2;
781
          `OC8051_MOV_CI : op_length <= #1 2'h2;
782
 
783
        //op_code [7:0]
784
          `OC8051_ADD_D :  op_length <= #1 2'h2;
785
          `OC8051_ADD_C :  op_length <= #1 2'h2;
786
          `OC8051_ADDC_D : op_length <= #1 2'h2;
787
          `OC8051_ADDC_C : op_length <= #1 2'h2;
788
          `OC8051_ANL_D :  op_length <= #1 2'h2;
789
          `OC8051_ANL_C :  op_length <= #1 2'h2;
790
          `OC8051_ANL_DD : op_length <= #1 2'h2;
791
          `OC8051_ANL_DC : op_length <= #1 2'h3;
792
          `OC8051_ANL_B :  op_length <= #1 2'h2;
793
          `OC8051_ANL_NB : op_length <= #1 2'h2;
794
          `OC8051_CJNE_D : op_length <= #1 2'h3;
795
          `OC8051_CJNE_C : op_length <= #1 2'h3;
796
          `OC8051_CLR_B :  op_length <= #1 2'h2;
797
          `OC8051_CPL_B :  op_length <= #1 2'h2;
798
          `OC8051_DEC_D :  op_length <= #1 2'h2;
799
          `OC8051_DJNZ_D : op_length <= #1 2'h3;
800
          `OC8051_INC_D :  op_length <= #1 2'h2;
801
          `OC8051_JB :     op_length <= #1 2'h3;
802
          `OC8051_JBC :    op_length <= #1 2'h3;
803
          `OC8051_JC :     op_length <= #1 2'h2;
804
          `OC8051_JNB :    op_length <= #1 2'h3;
805
          `OC8051_JNC :    op_length <= #1 2'h2;
806
          `OC8051_JNZ :    op_length <= #1 2'h2;
807
          `OC8051_JZ :     op_length <= #1 2'h2;
808
          `OC8051_LCALL :  op_length <= #1 2'h3;
809
          `OC8051_LJMP :   op_length <= #1 2'h3;
810
          `OC8051_MOV_D :  op_length <= #1 2'h2;
811
          `OC8051_MOV_C :  op_length <= #1 2'h2;
812
          `OC8051_MOV_DA : op_length <= #1 2'h2;
813
          `OC8051_MOV_DD : op_length <= #1 2'h3;
814
          `OC8051_MOV_CD : op_length <= #1 2'h3;
815
          `OC8051_MOV_BC : op_length <= #1 2'h2;
816
          `OC8051_MOV_CB : op_length <= #1 2'h2;
817
          `OC8051_MOV_DP : op_length <= #1 2'h3;
818
          `OC8051_ORL_D :  op_length <= #1 2'h2;
819
          `OC8051_ORL_C :  op_length <= #1 2'h2;
820
          `OC8051_ORL_AD : op_length <= #1 2'h2;
821
          `OC8051_ORL_CD : op_length <= #1 2'h3;
822
          `OC8051_ORL_B :  op_length <= #1 2'h2;
823
          `OC8051_ORL_NB : op_length <= #1 2'h2;
824
          `OC8051_POP :    op_length <= #1 2'h2;
825
          `OC8051_PUSH :   op_length <= #1 2'h2;
826
          `OC8051_SETB_B : op_length <= #1 2'h2;
827
          `OC8051_SJMP :   op_length <= #1 2'h2;
828
          `OC8051_SUBB_D : op_length <= #1 2'h2;
829
          `OC8051_SUBB_C : op_length <= #1 2'h2;
830
          `OC8051_XCH_D :  op_length <= #1 2'h2;
831
          `OC8051_XRL_D :  op_length <= #1 2'h2;
832
          `OC8051_XRL_C :  op_length <= #1 2'h2;
833
          `OC8051_XRL_AD : op_length <= #1 2'h2;
834
          `OC8051_XRL_CD : op_length <= #1 2'h3;
835
          default:         op_length <= #1 2'h1;
836
        endcase
837
//
838
//in case of instructions that use more than one clock hold current pc
839
//    end else begin
840
//      pc= pc_buf;
841
   end
842
end
843
*/
844
 
845
assign inc_pc = ((op_pos[2] | (&op_pos[1:0])) & rd) | pc_wr_r2;
846
 
847
always @(posedge rst or posedge clk)
848
begin
849
  if (rst) begin
850
    op_pos <= #1 3'h0;
851
  end else if (pc_wr_r2) begin
852
    op_pos <= #1 3'h4;// - op_length;////****??????????
853
/*  end else if (inc_pc & rd) begin
854
    op_pos[2]   <= #1 op_pos[2] & !op_pos[1] & op_pos[0] & (&op_length);
855
    op_pos[1:0] <= #1 op_pos[1:0] + op_length;
856
//    op_pos   <= #1 {1'b0, op_pos[1:0]} + {1'b0, op_length};
857
  end else if (rd) begin
858
    op_pos <= #1 op_pos + {1'b0, op_length};
859
  end*/
860
  end else if (inc_pc & rd) begin
861
    op_pos[2]   <= #1 op_pos[2] & !op_pos[1] & op_pos[0] & (&op_length);
862
    op_pos[1:0] <= #1 op_pos[1:0] + op_length;
863
//    op_pos   <= #1 {1'b0, op_pos[1:0]} + {1'b0, op_length};
864
//  end else if (istb & rd) begin
865
  end else if (rd) begin
866
    op_pos <= #1 op_pos + {1'b0, op_length};
867
  end
868
end
869
 
870
//
871 81 simont
// remember interrupt
872
// we don't want to interrupt instruction in the middle of execution
873
always @(posedge clk or posedge rst)
874
 if (rst) begin
875
   int_ack_t <= #1 1'b0;
876
   int_vec_buff <= #1 8'h00;
877
 end else if (intr) begin
878
   int_ack_t <= #1 1'b1;
879
   int_vec_buff <= #1 int_v;
880 149 simont
 end else if (rd && (ea_rom_sel || iack_i) && !pc_wr_r2) int_ack_t <= #1 1'b0;
881 81 simont
 
882
always @(posedge clk or posedge rst)
883
  if (rst) int_ack_buff <= #1 1'b0;
884
  else int_ack_buff <= #1 int_ack_t;
885
 
886
always @(posedge clk or posedge rst)
887
  if (rst) int_ack <= #1 1'b0;
888
  else begin
889
    if ((int_ack_buff) & !(int_ack_t))
890
      int_ack <= #1 1'b1;
891
    else int_ack <= #1 1'b0;
892
  end
893
 
894
 
895
//
896 149 simont
//interrupt buffer
897
always @(posedge clk or posedge rst)
898
  if (rst) begin
899
    int_buff1 <= #1 1'b0;
900
  end else begin
901
    int_buff1 <= #1 int_buff;
902
  end
903
 
904
always @(posedge clk or posedge rst)
905
  if (rst) begin
906
    int_buff <= #1 1'b0;
907
  end else if (intr) begin
908
    int_buff <= #1 1'b1;
909
  end else if (pc_wait)
910
    int_buff <= #1 1'b0;
911
 
912
wire [7:0]  pcs_source;
913
reg  [15:0] pcs_result;
914
reg         pcs_cy;
915
 
916
assign pcs_source = pc_wr_sel[0] ? op3_out : op2_out;
917
 
918
always @(pcs_source or pc or pcs_cy)
919
begin
920
  if (pcs_source[7]) begin
921
    {pcs_cy, pcs_result[7:0]} = {1'b0, pc[7:0]} + {1'b0, pcs_source};
922
    pcs_result[15:8] = pc[15:8] - {7'h0, !pcs_cy};
923
  end else pcs_result = pc + {8'h00, pcs_source};
924
end
925
 
926
//assign pc = pc_buf - {13'h0, op_pos[2] | inc_pc_r, op_pos[1:0]}; ////******???
927
//assign pc = pc_buf - 16'h8 + {13'h0, op_pos}; ////******???
928
//assign pc = pc_buf - 16'h8 + {13'h0, op_pos} + {14'h0, op_length};
929
 
930
always @(posedge clk or posedge rst)
931
begin
932
  if (rst)
933
    pc <= #1 16'h0;
934
  else if (pc_wr_r2)
935
    pc <= #1 pc_buf;
936
  else if (rd & !int_ack_t)
937
    pc <= #1 pc_buf - 16'h8 + {13'h0, op_pos} + {14'h0, op_length};
938
end
939
 
940
 
941
always @(posedge clk or posedge rst)
942
begin
943
  if (rst) begin
944
    pc_buf <= #1 `OC8051_RST_PC;
945
  end else if (pc_wr) begin
946 81 simont
//
947 149 simont
//case of writing new value to pc (jupms)
948 179 simont
      case (pc_wr_sel) /* synopsys full_case parallel_case */
949 149 simont
        `OC8051_PIS_ALU: pc_buf        <= #1 alu;
950
        `OC8051_PIS_AL:  pc_buf[7:0]   <= #1 alu[7:0];
951
        `OC8051_PIS_AH:  pc_buf[15:8]  <= #1 alu[7:0];
952
        `OC8051_PIS_I11: pc_buf[10:0]  <= #1 {op1_out[7:5], op2_out};
953
        `OC8051_PIS_I16: pc_buf        <= #1 {op2_out, op3_out};
954
        `OC8051_PIS_SO1: pc_buf        <= #1 pcs_result;
955
        `OC8051_PIS_SO2: pc_buf        <= #1 pcs_result;
956
      endcase
957
//  end else if (inc_pc) begin
958
  end else begin
959
//
960
//or just remember current
961
      pc_buf <= #1 pc_out;
962
  end
963
end
964 81 simont
 
965 149 simont
 
966
assign pc_out = inc_pc ? pc_buf + 16'h4
967
                       : pc_buf ;
968
 
969
 
970
 
971
 
972
 
973
always @(posedge clk or posedge rst)
974
  if (rst)
975
    ddat_ir <= #1 8'h00;
976
  else if (dack_i)
977
    ddat_ir <= #1 ddat_i;
978
 
979
/*
980
 
981 139 simont
always @(pc_buf or op1_out or pc_wait or int_buff or int_buff1 or ea_rom_sel or iack_i)
982 81 simont
begin
983
    if (int_buff || int_buff1) begin
984
//
985
//in case of interrupt hold valut, to be written to stack
986
      pc= pc_buf;
987
//    end else if (pis_l) begin
988
//      pc = {pc_buf[22:8], alu[7:0]};
989
    end else if (pc_wait) begin
990
        casex (op1_out)
991 121 simont
          `OC8051_ACALL :  pc= pc_buf + 16'h2;
992
          `OC8051_AJMP :   pc= pc_buf + 16'h2;
993 81 simont
 
994
        //op_code [7:3]
995 121 simont
          `OC8051_CJNE_R : pc= pc_buf + 16'h3;
996
          `OC8051_DJNZ_R : pc= pc_buf + 16'h2;
997
          `OC8051_MOV_DR : pc= pc_buf + 16'h2;
998
          `OC8051_MOV_CR : pc= pc_buf + 16'h2;
999
          `OC8051_MOV_RD : pc= pc_buf + 16'h2;
1000 81 simont
 
1001
        //op_code [7:1]
1002 121 simont
          `OC8051_CJNE_I : pc= pc_buf + 16'h3;
1003
          `OC8051_MOV_ID : pc= pc_buf + 16'h2;
1004
          `OC8051_MOV_DI : pc= pc_buf + 16'h2;
1005
          `OC8051_MOV_CI : pc= pc_buf + 16'h2;
1006 81 simont
 
1007
        //op_code [7:0]
1008 121 simont
          `OC8051_ADD_D :  pc= pc_buf + 16'h2;
1009
          `OC8051_ADD_C :  pc= pc_buf + 16'h2;
1010
          `OC8051_ADDC_D : pc= pc_buf + 16'h2;
1011
          `OC8051_ADDC_C : pc= pc_buf + 16'h2;
1012
          `OC8051_ANL_D :  pc= pc_buf + 16'h2;
1013
          `OC8051_ANL_C :  pc= pc_buf + 16'h2;
1014
          `OC8051_ANL_DD : pc= pc_buf + 16'h2;
1015
          `OC8051_ANL_DC : pc= pc_buf + 16'h3;
1016
          `OC8051_ANL_B :  pc= pc_buf + 16'h2;
1017
          `OC8051_ANL_NB : pc= pc_buf + 16'h2;
1018
          `OC8051_CJNE_D : pc= pc_buf + 16'h3;
1019
          `OC8051_CJNE_C : pc= pc_buf + 16'h3;
1020
          `OC8051_CLR_B :  pc= pc_buf + 16'h2;
1021
          `OC8051_CPL_B :  pc= pc_buf + 16'h2;
1022
          `OC8051_DEC_D :  pc= pc_buf + 16'h2;
1023
          `OC8051_DJNZ_D : pc= pc_buf + 16'h3;
1024
          `OC8051_INC_D :  pc= pc_buf + 16'h2;
1025
          `OC8051_JB :     pc= pc_buf + 16'h3;
1026
          `OC8051_JBC :    pc= pc_buf + 16'h3;
1027
          `OC8051_JC :     pc= pc_buf + 16'h2;
1028
          `OC8051_JNB :    pc= pc_buf + 16'h3;
1029
          `OC8051_JNC :    pc= pc_buf + 16'h2;
1030
          `OC8051_JNZ :    pc= pc_buf + 16'h2;
1031
          `OC8051_JZ :     pc= pc_buf + 16'h2;
1032
          `OC8051_LCALL :  pc= pc_buf + 16'h3;
1033
          `OC8051_LJMP :   pc= pc_buf + 16'h3;
1034
          `OC8051_MOV_D :  pc= pc_buf + 16'h2;
1035
          `OC8051_MOV_C :  pc= pc_buf + 16'h2;
1036
          `OC8051_MOV_DA : pc= pc_buf + 16'h2;
1037
          `OC8051_MOV_DD : pc= pc_buf + 16'h3;
1038
          `OC8051_MOV_CD : pc= pc_buf + 16'h3;
1039
          `OC8051_MOV_BC : pc= pc_buf + 16'h2;
1040
          `OC8051_MOV_CB : pc= pc_buf + 16'h2;
1041
          `OC8051_MOV_DP : pc= pc_buf + 16'h3;
1042
          `OC8051_ORL_D :  pc= pc_buf + 16'h2;
1043
          `OC8051_ORL_C :  pc= pc_buf + 16'h2;
1044
          `OC8051_ORL_AD : pc= pc_buf + 16'h2;
1045
          `OC8051_ORL_CD : pc= pc_buf + 16'h3;
1046
          `OC8051_ORL_B :  pc= pc_buf + 16'h2;
1047
          `OC8051_ORL_NB : pc= pc_buf + 16'h2;
1048
          `OC8051_POP :    pc= pc_buf + 16'h2;
1049
          `OC8051_PUSH :   pc= pc_buf + 16'h2;
1050
          `OC8051_SETB_B : pc= pc_buf + 16'h2;
1051
          `OC8051_SJMP :   pc= pc_buf + 16'h2;
1052
          `OC8051_SUBB_D : pc= pc_buf + 16'h2;
1053
          `OC8051_SUBB_C : pc= pc_buf + 16'h2;
1054
          `OC8051_XCH_D :  pc= pc_buf + 16'h2;
1055
          `OC8051_XRL_D :  pc= pc_buf + 16'h2;
1056
          `OC8051_XRL_C :  pc= pc_buf + 16'h2;
1057
          `OC8051_XRL_AD : pc= pc_buf + 16'h2;
1058
          `OC8051_XRL_CD : pc= pc_buf + 16'h3;
1059
          default:         pc= pc_buf + 16'h1;
1060 81 simont
        endcase
1061
//
1062
//in case of instructions that use more than one clock hold current pc
1063
    end else begin
1064
      pc= pc_buf;
1065
   end
1066
end
1067
 
1068
 
1069
//
1070
//interrupt buffer
1071
always @(posedge clk or posedge rst)
1072
  if (rst) begin
1073
    int_buff1 <= #1 1'b0;
1074
  end else begin
1075
    int_buff1 <= #1 int_buff;
1076
  end
1077
 
1078
always @(posedge clk or posedge rst)
1079
  if (rst) begin
1080
    int_buff <= #1 1'b0;
1081
  end else if (intr) begin
1082
    int_buff <= #1 1'b1;
1083
  end else if (pc_wait)
1084
    int_buff <= #1 1'b0;
1085
 
1086 132 simont
wire [7:0]  pcs_source;
1087
reg  [15:0] pcs_result;
1088
reg         pcs_cy;
1089 81 simont
 
1090 132 simont
assign pcs_source = pc_wr_sel[0] ? op3_out : op2_out;
1091
 
1092
always @(pcs_source or pc or pcs_cy)
1093
begin
1094
  if (pcs_source[7]) begin
1095
    {pcs_cy, pcs_result[7:0]} = {1'b0, pc[7:0]} + {1'b0, pcs_source};
1096
    pcs_result[15:8] = pc[15:8] - {7'h0, !pcs_cy};
1097
  end else pcs_result = pc + {8'h00, pcs_source};
1098
end
1099
 
1100
 
1101 81 simont
always @(posedge clk or posedge rst)
1102
begin
1103
  if (rst) begin
1104
    pc_buf <= #1 `OC8051_RST_PC;
1105
  end else begin
1106
    if (pc_wr) begin
1107
//
1108
//case of writing new value to pc (jupms)
1109
      case (pc_wr_sel)
1110
        `OC8051_PIS_ALU: pc_buf        <= #1 alu;
1111
        `OC8051_PIS_AL:  pc_buf[7:0]   <= #1 alu[7:0];
1112
        `OC8051_PIS_AH:  pc_buf[15:8]  <= #1 alu[7:0];
1113
        `OC8051_PIS_I11: pc_buf[10:0]  <= #1 {op1_out[7:5], op2_out};
1114
        `OC8051_PIS_I16: pc_buf        <= #1 {op2_out, op3_out};
1115 132 simont
        `OC8051_PIS_SO1: pc_buf        <= #1 pcs_result;
1116
        `OC8051_PIS_SO2: pc_buf        <= #1 pcs_result;
1117 81 simont
      endcase
1118
    end else
1119
//
1120
//or just remember current
1121
      pc_buf <= #1 pc;
1122
  end
1123
end
1124
 
1125
 
1126
always @(posedge clk or posedge rst)
1127
  if (rst)
1128
    ddat_ir <= #1 8'h00;
1129
  else if (dack_i)
1130
    ddat_ir <= #1 ddat_i;
1131 149 simont
*/
1132 81 simont
 
1133
////////////////////////
1134
always @(posedge clk or posedge rst)
1135
  if (rst) begin
1136 149 simont
    rn_r      <= #1 5'd0;
1137
    ri_r      <= #1 8'h00;
1138
    imm_r     <= #1 8'h00;
1139
    imm2_r    <= #1 8'h00;
1140 139 simont
    rd_addr_r <= #1 1'b0;
1141 149 simont
    op1_r     <= #1 8'h0;
1142
    dack_ir   <= #1 1'b0;
1143
    sp_r      <= #1 1'b0;
1144
    pc_wr_r   <= #1 1'b0;
1145
    pc_wr_r2  <= #1 1'b0;
1146 81 simont
  end else begin
1147 149 simont
    rn_r      <= #1 rn;
1148
    ri_r      <= #1 ri;
1149
    imm_r     <= #1 imm;
1150
    imm2_r    <= #1 imm2;
1151 139 simont
    rd_addr_r <= #1 rd_addr[7];
1152 149 simont
    op1_r     <= #1 op1_out;
1153
    dack_ir   <= #1 dack_i;
1154
    sp_r      <= #1 sp;
1155 158 simont
    pc_wr_r   <= #1 pc_wr && (pc_wr_sel != `OC8051_PIS_AH);
1156 149 simont
    pc_wr_r2  <= #1 pc_wr_r;
1157 81 simont
  end
1158
 
1159 149 simont
always @(posedge clk or posedge rst)
1160
  if (rst) begin
1161
    inc_pc_r  <= #1 1'b1;
1162
  end else if (istb) begin
1163
    inc_pc_r  <= #1 inc_pc;
1164
  end
1165 81 simont
 
1166 181 simont
`ifdef OC8051_SIMULATION
1167
 
1168
initial
1169
begin
1170
  wait (!rst)
1171
  if (ea_rom_sel) begin
1172
    $display(" ");
1173
    $display("\t Program running from internal rom !");
1174
    $display(" ");
1175
  end else begin
1176
    $display(" ");
1177
    $display("\t Program running from external rom !");
1178
    $display(" ");
1179
  end
1180
end
1181
`endif
1182
 
1183
 
1184 81 simont
endmodule

powered by: WebSVN 2.1.0

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