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

Subversion Repositories m32632

[/] [m32632/] [trunk/] [rtl/] [ADDR_UNIT.v] - Blame information for rev 30

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

Line No. Rev Author Line
1 29 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 9 ns32kum
//
3
// This file is part of the M32632 project
4
// http://opencores.org/project,m32632
5
//
6 23 ns32kum
//      Filename:       ADDR_UNIT.v
7 29 ns32kum
//      Version:        3.0
8
//      History:        2.0 of 11 August 2016
9
//                              1.1 bug fix of 7 October 2015
10 23 ns32kum
//                              1.0 first release of 30 Mai 2015
11 29 ns32kum
//      Date:           2 December 2018
12 9 ns32kum
//
13 29 ns32kum
// Copyright (C) 2018 Udo Moeller
14 9 ns32kum
// 
15
// This source file may be used and distributed without 
16
// restriction provided that this copyright statement is not 
17
// removed from the file and that any derivative work contains 
18
// the original copyright notice and the associated disclaimer.
19
// 
20
// This source file is free software; you can redistribute it 
21
// and/or modify it under the terms of the GNU Lesser General 
22
// Public License as published by the Free Software Foundation;
23
// either version 2.1 of the License, or (at your option) any 
24
// later version. 
25
// 
26
// This source is distributed in the hope that it will be 
27
// useful, but WITHOUT ANY WARRANTY; without even the implied 
28
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
29
// PURPOSE. See the GNU Lesser General Public License for more 
30
// details. 
31
// 
32
// You should have received a copy of the GNU Lesser General 
33
// Public License along with this source; if not, download it 
34
// from http://www.opencores.org/lgpl.shtml 
35
// 
36 29 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
37 9 ns32kum
//
38
//      Modules contained in this file:
39
//      ADDR_UNIT       generates data access addresses and controls data cache operation
40
//
41 11 ns32kum
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
42 9 ns32kum
 
43 11 ns32kum
module ADDR_UNIT ( BCLK, BRESET, READ, WRITE, LDEA, NEWACC, CLRMSW, POST, DISP_OK, FULLACC, SRC2SEL, INDEX, ASIZE, SRC1, SRC2, BWD,
44
                                   DISP, PC_ARCHI, PC_ICACHE, IO_READY, ACC_STAT, MMU_UPDATE, IC_TEX, ABO_STAT, ADIVAR, RWVAL_1, OP_RMW, PHASE_17,
45 29 ns32kum
                                   NO_TRAP, FPU_TRAP, READ_OUT, WRITE_OUT, ZTEST, RMW, VADR, ADDR, SIZE, PACKET, ACC_DONE, ABORT, CTRL_QW, BITSEL,
46 12 ns32kum
                                   QWATWO );
47 9 ns32kum
 
48
        input                   BCLK,BRESET;
49
        input                   READ,WRITE,LDEA;
50
        input                   NEWACC;
51
        input                   CLRMSW,POST,FULLACC;
52
        input    [1:0]   SRC2SEL;
53
        input    [3:0]   INDEX;
54
        input    [1:0]   ASIZE;
55
        input   [31:0]   SRC1,SRC2;
56
        input    [1:0]   BWD;
57
        input   [31:0]   DISP;
58
        input   [31:0]   PC_ARCHI,PC_ICACHE;
59
        input                   DISP_OK;
60
        input                   IO_READY;
61
        input    [5:0]   ACC_STAT;       // Feedback from data cache about the running access
62
        input    [1:0]   MMU_UPDATE;
63
        input    [2:0]   IC_TEX;
64
        input    [1:0]   ABO_STAT;
65
        input                   ADIVAR;
66
        input                   RWVAL_1;        // special access for RDVAL + WRVAL
67
        input                   OP_RMW;
68
        input                   PHASE_17;
69
        input                   NO_TRAP;
70
        input                   FPU_TRAP;
71
 
72
        output                  READ_OUT,WRITE_OUT,ZTEST,RMW;
73
        output  [31:0]   VADR;
74
        output  [31:0]   ADDR;
75
        output   [1:0]   SIZE;
76
        output   [3:0]   PACKET;
77
        output                  ACC_DONE;
78
        output                  ABORT;
79 29 ns32kum
        output   [1:0]   CTRL_QW;
80 9 ns32kum
        output   [2:0]   BITSEL;
81 12 ns32kum
        output  reg             QWATWO;
82 9 ns32kum
 
83
        reg             [31:0]   VADR;
84
        reg                             READ_OUT,write_reg,ZTEST,RMW;
85
        reg              [1:0]   SIZE;
86
        reg              [3:0]   PACKET;
87
        reg              [2:0]   BITSEL;
88
        reg             [31:0]   source2;
89
        reg             [31:0]   index_val;
90
        reg             [31:0]   vadr_reg;
91
        reg             [31:0]   ea_reg;
92
        reg             [31:0]   tos_offset;
93
        reg             [31:0]   icache_adr;
94
        reg             [31:0]   sign_ext_src1;
95
        reg        [31:12]      pg_areg;
96
        reg                             reg_out_i,next_reg;
97
        reg                             ld_ea_reg;
98
        reg                             acc_run,acc_ende,acc_step;
99
        reg                             qwa_flag;
100
        reg                             no_done;
101
        reg                             frueh_ok;
102
        reg                             io_rdy;
103
        reg                             ABORT;
104
        reg              [1:0]   tex_feld;
105
        reg              [2:0]   u_ddt;
106
        reg                             pg_op;
107
        reg                             do_wr;
108 29 ns32kum
        reg                             irdy_flag;
109 9 ns32kum
 
110
        wire                    acc_ok,acc_err,io_acc;
111
        wire                    acc_pass;
112
        wire                    ca_hit;
113
        wire    [31:0]   reg_adder;
114
        wire    [31:0]   next_vadr;
115
        wire    [31:0]   final_addr;
116
        wire    [31:0]   pg_addr;
117
        wire     [1:0]   inc_pack;
118
        wire     [3:0]   index_sel;
119
        wire                    ld_ea_i;
120
        wire                    ea_ok;
121
        wire                    qw_align;
122
        wire                    init_acc;
123
        wire                    in_page;
124
        wire                    all_ok;
125
        wire                    fa_out;
126
        wire                    pg_test;
127
 
128
        // ++++++++++++++++++++  Decoding ACC_STAT from data cache  ++++++++++++++++++++++++++++
129
 
130
        // ACC_STAT[5:0] : CA_HIT, IO_ACC, PROT_ERROR , ABO_LEVEL1 , ABORT , ACC_OK
131
 
132
        assign ca_hit   = ACC_STAT[5];
133
        assign io_acc   = ACC_STAT[4];
134
        assign acc_err  = ACC_STAT[3] | ACC_STAT[1];    // Abort or Protection Error
135
        assign acc_ok   = ACC_STAT[0] & ~pg_op;
136
        assign acc_pass = ACC_STAT[0] & ZTEST;
137
 
138
        always @(posedge BCLK) ABORT <= acc_err;        // Signal to Steuerung - only a pulse
139
 
140 11 ns32kum
        always @(posedge BCLK) if (acc_err) tex_feld <= ACC_STAT[3] ? 2'b11 : {~ACC_STAT[2],ACC_STAT[2]};       // for MSR
141 9 ns32kum
        always @(posedge BCLK) if (acc_err) u_ddt        <= {RMW,ABO_STAT[1],(WRITE_OUT | ZTEST)};
142
 
143
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
144
 
145
        always @(SRC2SEL or CLRMSW or SRC2 or PC_ARCHI or ea_reg)
146
                case (SRC2SEL)
147 11 ns32kum
                  2'b00 : source2 = {(CLRMSW ? 16'h0000 : SRC2[31:16]),SRC2[15:0]};      // base reg, External Addressing with MOD 
148 9 ns32kum
                  2'b01 : source2 = PC_ARCHI;           // PC relative
149
                  2'b10 : source2 = 32'h0;                      // Absolute Addressing
150
                  2'b11 : source2 = ea_reg;                     // REUSE : 2. TOS
151
                endcase
152
 
153 11 ns32kum
        assign index_sel = POST ? 4'h0 : INDEX; // Alternative application of Index for POST Adder : POP from Stack
154 9 ns32kum
 
155
        always @(BWD or SRC1)
156
                casex (BWD)
157
                        2'b00 : sign_ext_src1 = {{24{SRC1[7]}}, SRC1[7:0]};              // Byte
158
                        2'b01 : sign_ext_src1 = {{16{SRC1[15]}},SRC1[15:0]};     // Word
159
                  default : sign_ext_src1 = SRC1;
160
                endcase
161
 
162
        always @(index_sel or sign_ext_src1 or SRC1)
163
                casex (index_sel)
164 29 ns32kum
                  4'b1_0xx : index_val = sign_ext_src1; // f�r CASE
165 9 ns32kum
                  4'b1_1xx : index_val = {{ 3{sign_ext_src1[31]}},sign_ext_src1[31:3]}; // for Bit Opcodes
166
                  4'b0_100 : index_val = SRC1;
167
                  4'b0_101 : index_val = {SRC1[30:0],1'b0};
168
                  4'b0_110 : index_val = {SRC1[29:0],2'b00};
169
                  4'b0_111 : index_val = {SRC1[28:0],3'b000};
170
                  default  : index_val = 32'h0;
171
                endcase
172
 
173
        assign reg_adder = source2 + index_val; // SRC2 allows simple MOV with SRC1
174
 
175
        assign final_addr = reg_adder + DISP;   // That's the final access address
176
 
177 11 ns32kum
        always @(posedge BCLK) if (LDEA && (index_sel[3:2] == 2'b11)) BITSEL <= SRC1[2:0];       // for Bit Opcodes in I_PFAD
178 9 ns32kum
 
179
        always @(INDEX) // SP POP Operation & String Backward
180
                case (INDEX[2:0])
181
                  3'b000 : tos_offset = 32'h0000_0001;
182
                  3'b001 : tos_offset = 32'h0000_0002;
183
                  3'b010 : tos_offset = 32'h0000_0004;
184
                  3'b011 : tos_offset = 32'h0000_0008;
185
                  3'b100 : tos_offset = 32'hFFFF_FFFF;
186
                  3'b101 : tos_offset = 32'hFFFF_FFFE;
187
                  3'b110 : tos_offset = 32'hFFFF_FFFC;
188
                  3'b111 : tos_offset = 32'hFFFF_FFF8;
189
                endcase
190
 
191
        always @(posedge BCLK or negedge BRESET)
192
                if (!BRESET) ld_ea_reg <= 1'b0;
193
                  else ld_ea_reg <= (LDEA | ld_ea_reg) & ~DISP_OK;
194
 
195
        assign ld_ea_i = (LDEA | ld_ea_reg) & DISP_OK;
196
 
197
        assign ea_ok = (READ | WRITE | LDEA | ld_ea_reg) & ~FULLACC & DISP_OK;
198
 
199
        always @(posedge BCLK) icache_adr <= PC_ICACHE;
200
 
201
        // Memory for the calculated address for reuse and Register for POST modified addresses : 
202
        always @(posedge BCLK)
203
                if (ld_ea_i)
204
                  begin
205
                        casex ({MMU_UPDATE[1],INDEX[0],POST})
206
                          3'b10x : ea_reg <= MMU_UPDATE[0] ? vadr_reg : icache_adr;              // TEAR
207
                          3'b11x : ea_reg <= MMU_UPDATE[0] ?
208
                                                                  {24'h0000_00,3'b101,          u_ddt,                   tex_feld}              // MSR
209
                                                                : {24'h0000_00,3'b100,IC_TEX[2],ABO_STAT[0],1'b0,IC_TEX[1:0]};    // only READ from ICACHE
210
                          3'b0x1 : ea_reg <= source2 + tos_offset ;
211
                          3'b0x0 : ea_reg <= final_addr;
212
                        endcase
213
                  end
214
 
215
        assign ADDR = ea_reg;   // used for ADDR opcode and TOS Addressing
216
 
217
        // This pulse stores all parameters of access
218 11 ns32kum
        assign init_acc = ((FULLACC ? (NEWACC & acc_ende) : acc_ende) | ~acc_run) & DISP_OK & (READ | WRITE) & ~ABORT & NO_TRAP;
219 9 ns32kum
 
220
        assign fa_out = init_acc | ADIVAR;      // special case for LMR IVAR,...
221
 
222
        always @(fa_out or acc_ok or final_addr or qw_align or pg_op or pg_areg or vadr_reg or next_vadr)
223
                casex ({fa_out,acc_ok})
224
                  2'b1x : VADR = {final_addr[31:3],(final_addr[2] | qw_align),final_addr[1:0]};
225
                  2'b00 : VADR = pg_op ? {pg_areg,12'h0} : vadr_reg;
226
                  2'b01 : VADR = next_vadr;
227
                endcase
228
 
229
        always @(posedge BCLK)
230
                if (init_acc) vadr_reg <= {final_addr[31:3],(final_addr[2] | qw_align),final_addr[1:0]};
231
                  else
232
                        if (pg_op && ZTEST && acc_err) vadr_reg <= {pg_areg,12'h0};     // for TEAR !
233
                          else
234
                                if (acc_ok) vadr_reg <= next_vadr;
235
 
236
        assign next_vadr = qwa_flag ? {vadr_reg[31:3],3'b000} : ({vadr_reg[31:2],2'b00} + 32'h0000_0004);
237
 
238
        // Logic for Page border WRITE Test
239
        assign pg_addr = final_addr + {29'h0,(ASIZE[1] & ASIZE[0]),ASIZE[1],(ASIZE[1] | ASIZE[0])};
240
        always @(posedge BCLK) if (init_acc) pg_areg <= pg_addr[31:12];
241
        assign pg_test = (final_addr[12] != pg_addr[12]) & ~OP_RMW;     // At RMW no Test necessary
242
 
243
        always @(posedge BCLK or negedge BRESET)
244
                if (!BRESET) pg_op <= 1'b0;
245
                  else
246
                        pg_op <= init_acc ? (WRITE & ~RWVAL_1 & pg_test) : (pg_op & ~acc_pass & ~acc_err);
247
 
248
        always @(posedge BCLK) do_wr <= pg_op & ZTEST & acc_pass;       // All ok, Page exists => continue
249
 
250
        always @(posedge BCLK or negedge BRESET)
251
                if (!BRESET) READ_OUT <= 1'b0;
252
                  else
253
                        READ_OUT  <= init_acc ? (READ & ~RWVAL_1) : (READ_OUT  & ~acc_ende & ~acc_err);
254
 
255
        always @(posedge BCLK or negedge BRESET)
256
                if (!BRESET) write_reg <= 1'b0;
257
                  else
258 11 ns32kum
                        write_reg <= (init_acc ? (WRITE & ~RWVAL_1 & ~pg_test) : (write_reg & ~acc_ende & ~acc_err & ~FPU_TRAP)) | do_wr;
259 9 ns32kum
 
260
        assign WRITE_OUT = write_reg & ~FPU_TRAP;
261
 
262
        // Special case for RDVAL and WRVAL
263
        always @(posedge BCLK or negedge BRESET)
264
                if (!BRESET) ZTEST <= 1'b0;
265
                  else
266 11 ns32kum
                        ZTEST <= pg_op ? (~ZTEST | (~acc_pass & ~acc_err)) : (init_acc ? RWVAL_1  : (ZTEST  & ~acc_ende & ~acc_err));
267 9 ns32kum
 
268
        always @(posedge BCLK or negedge BRESET)
269
                if (!BRESET) RMW <= 1'b0;
270
                  else
271
                        RMW <= init_acc ? (OP_RMW & PHASE_17) : (RMW  & ~acc_ende & ~acc_err);
272
 
273
        // Special case : first MSD access by aligned QWORD READ
274
        assign qw_align = (final_addr[2:0] == 3'b000) & READ & (ASIZE == 2'b11);
275
 
276
        always @(posedge BCLK) if (init_acc) qwa_flag <= qw_align;
277
 
278
        always @(posedge BCLK or negedge BRESET)        // central flag that shows the ADDR_UNIT is busy
279
                if (!BRESET) acc_run <= 1'b0;
280
                  else
281
                        acc_run <= init_acc | (acc_run & ~acc_ende & ~acc_err & ~FPU_TRAP);
282
 
283
        always @(posedge BCLK) if (init_acc) SIZE <= ASIZE;
284
 
285
        assign inc_pack = (PACKET[1:0] == 2'b00) ? 2'b10 : {(SIZE[1] ^ SIZE[0]),(SIZE[1] & SIZE[0])};
286
 
287 11 ns32kum
        // Counter for data packets 1 to 3 : special case aligned QWORD : only 2 packets. Additionally start address in bits 1 und 0.
288 9 ns32kum
        // special coding (00) -> [01] -> (10) , [01] optional by QWORD and (10) shows always the end
289
        always @(posedge BCLK)
290
                if (init_acc) PACKET <= {2'b00,final_addr[1:0]};
291
                  else
292
                        if (acc_ok) PACKET <= PACKET + {inc_pack,2'b00};
293
 
294
        // This signal is the End signal for the ADDR_UNIT internally.
295
        always @(SIZE or PACKET or acc_ok)
296
                casex ({SIZE,PACKET[3],PACKET[1:0]})
297
                  5'b00_x_xx : acc_ende = acc_ok;       // Byte
298
                  5'b01_0_0x : acc_ende = acc_ok;       // Word         1 packet
299
                  5'b01_0_10 : acc_ende = acc_ok;       //                      1 packet
300
                  5'b01_1_xx : acc_ende = acc_ok;       //                      2 packets
301
                  5'b10_0_00 : acc_ende = acc_ok;       // DWord        1 packet
302
                  5'b10_1_xx : acc_ende = acc_ok;       //                      2 packets
303
                  5'b11_1_xx : acc_ende = acc_ok;       // QWord        at least 2 packets
304
                  default    : acc_ende = 1'b0;
305
                endcase
306
 
307 11 ns32kum
        assign in_page = (vadr_reg[11:3] != 9'h1FF);    // Access inside a page ? During WRITE address is increasing : 1. LSD 2. MSD
308 9 ns32kum
 
309
        always @(SIZE or vadr_reg or in_page or PACKET)
310
                casex (SIZE)
311
                  2'b01 : frueh_ok = (vadr_reg[3:2] != 2'b11);  //Word
312
                  2'b10 : frueh_ok = (vadr_reg[3:2] != 2'b11);  //DWord
313 11 ns32kum
                  2'b11 : frueh_ok = (PACKET[1:0] == 2'b00) ? (~vadr_reg[3] | ~vadr_reg[2]) : ((PACKET[3:2] == 2'b01) & (vadr_reg[3:2] != 2'b11));
314 9 ns32kum
                default : frueh_ok = 1'b1;                                              // Byte don't case
315
                endcase
316
 
317
        assign all_ok = SIZE[1] ? (PACKET[1:0] == 2'b00) : (PACKET[1:0] != 2'b11);        // for DWord : Word
318
 
319 11 ns32kum
        always @(SIZE or READ_OUT or frueh_ok or PACKET or all_ok or io_acc or acc_ok or qwa_flag or io_rdy or ca_hit)
320 9 ns32kum
                casex ({SIZE,READ_OUT,frueh_ok,PACKET[3],io_acc,all_ok})
321
                  7'b00_xxxx_x : acc_step = acc_ok;     // Byte, all ok
322
                //
323
                  7'b01_xxxx_1 : acc_step = acc_ok;     // Word :       aligned access , only 1 packet
324
                  7'b01_1x1x_0 : acc_step = acc_ok;     //                      READ must wait for all data
325 23 ns32kum
                  7'b01_0x1x_0 : acc_step = acc_ok;     //                      WRITE Adr. ist not perfect and waits for last packet
326
                  7'b01_0100_0 : acc_step = acc_ok;     //                      WRITE Adr. perfect - acc_step after 1. packet
327 9 ns32kum
                //
328
                  7'b10_xxxx_1 : acc_step = acc_ok;     // DWord :      aligned access , only 1 packet
329
                  7'b10_1x1x_0 : acc_step = acc_ok;     //                      READ must wait for all data
330 23 ns32kum
                  7'b10_0x1x_0 : acc_step = acc_ok;     //                      WRITE Adr. ist not perfect and waits for last packet
331
                  7'b10_0100_0 : acc_step = acc_ok;     //                      WRITE Adr. perfect - acc_step after 1. packet
332 9 ns32kum
                // fast QWord READ : there would be a 2. acc_step if not ~PACK... 
333
                  7'b11_1xxx_x : acc_step = acc_ok & ( (qwa_flag & ~io_rdy & ca_hit) ? ~PACKET[3] : PACKET[3] );
334
                  7'b11_0x1x_x : acc_step = acc_ok;
335 11 ns32kum
                  7'b11_0100_x : acc_step = acc_ok;     //                      WRITE Adr. perfect - acc_step after 1. packet if not io_acc
336 9 ns32kum
                  default      : acc_step = 1'b0;
337
                endcase
338
 
339
        // There is a 2. acc_step if packet (10) - this must be suppressed
340
        always @(posedge BCLK or negedge BRESET)
341
                if (!BRESET) no_done <= 1'b0;
342
                  else no_done <= (~acc_ende & acc_step) | (no_done & ~(acc_run & acc_ende));
343
 
344
        // The final DONE Multiplexer
345
        assign ACC_DONE = acc_run ? (acc_step & ~no_done) : ea_ok;
346
 
347 12 ns32kum
        // Bugfix of 7.October 2015
348
        always @(posedge BCLK) QWATWO <= acc_run & acc_ok & qwa_flag & ~io_rdy & ca_hit & ~PACKET[3] & (SIZE == 2'b11) & READ_OUT & ~no_done;
349
 
350 29 ns32kum
        always @(posedge BCLK) reg_out_i <= ~acc_step & BRESET & ((qwa_flag & ~io_rdy & ~ca_hit & acc_ok) | reg_out_i);
351 9 ns32kum
 
352 29 ns32kum
        always @(posedge BCLK) irdy_flag <= (READ_OUT & io_acc) | (irdy_flag & ~IO_READY);      // new 25.6.2018
353
        always @(posedge BCLK) io_rdy  <= IO_READY & irdy_flag;
354 9 ns32kum
 
355 29 ns32kum
        always @(posedge BCLK) next_reg <= acc_step & (qwa_flag ? io_rdy : 1'b1) & (SIZE == 2'b11);
356
        assign CTRL_QW = {qwa_flag,(reg_out_i | next_reg)};
357 9 ns32kum
 
358
endmodule

powered by: WebSVN 2.1.0

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