Line 1... |
Line 1... |
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// This file is part of the M32632 project
|
// This file is part of the M32632 project
|
// http://opencores.org/project,m32632
|
// http://opencores.org/project,m32632
|
//
|
//
|
// Filename: CACHE_LOGIK.v
|
// Filename: CACHE_LOGIK.v
|
// Version: 2.0
|
// Version: 3.0
|
// History: 1.1 bug fix of 7 October 2015
|
// History: 2.0 of 11 August 2016
|
|
// 1.1 bug fix of 7 October 2015
|
// 1.0 first release of 30 Mai 2015
|
// 1.0 first release of 30 Mai 2015
|
// Date: 14 August 2016
|
// Date: 2 December 2018
|
//
|
//
|
// Copyright (C) 2016 Udo Moeller
|
// Copyright (C) 2018 Udo Moeller
|
//
|
//
|
// This source file may be used and distributed without
|
// This source file may be used and distributed without
|
// restriction provided that this copyright statement is not
|
// restriction provided that this copyright statement is not
|
// removed from the file and that any derivative work contains
|
// removed from the file and that any derivative work contains
|
// the original copyright notice and the associated disclaimer.
|
// the original copyright notice and the associated disclaimer.
|
Line 30... |
Line 31... |
//
|
//
|
// You should have received a copy of the GNU Lesser General
|
// You should have received a copy of the GNU Lesser General
|
// Public License along with this source; if not, download it
|
// Public License along with this source; if not, download it
|
// from http://www.opencores.org/lgpl.shtml
|
// from http://www.opencores.org/lgpl.shtml
|
//
|
//
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// Modules contained in this file:
|
// Modules contained in this file:
|
// 1. NEU_VALID Cache Valid RAM
|
// 1. WRPORT Write Port
|
// 2. DEBUG_AE Debug unit for address compare in data cache
|
// 2. NEU_VALID Cache Valid RAM
|
// 3. MMU_UP MMU memory update and initalization controller
|
// 3. DEBUG_AE Debug unit for address compare in data cache
|
// 4. DCA_CONTROL Data cache valid memory update and initalization controller
|
// 4. MMU_UP MMU memory update and initalization controller
|
// 5. MMU_MATCH MMU virtual address match detector
|
// 5. DCA_CONTROL Data cache valid memory update and initalization controller
|
// 6. CA_MATCH Cache tag match detector
|
// 6. MMU_MATCH MMU virtual address match detector
|
// 7. FILTCMP Address Filter and Comparator
|
// 7. CA_MATCH Cache tag match detector
|
// 8. DCACHE_SM Data cache state machine
|
// 8. FILTCMP Address Filter and Comparator
|
|
// 9. DCACHE_SM Data cache state machine
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 1. NEU_VALID Cache Valid RAM
|
// 1. WRPORT Write Port
|
|
//
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
module WRPORT ( WRITE, DRAM_Q, WRDATA, ENBYTE, VADDR, DADDR, WDAT, CAP_Q, ENB );
|
|
|
|
input WRITE;
|
|
input [127:0] DRAM_Q;
|
|
input [31:0] WRDATA;
|
|
input [3:0] ENBYTE;
|
|
input [3:2] VADDR;
|
|
input [3:2] DADDR;
|
|
|
|
output [127:0] WDAT;
|
|
|
|
output reg [31:0] CAP_Q;
|
|
output reg [15:0] ENB;
|
|
|
|
assign WDAT = WRITE ? {WRDATA,WRDATA,WRDATA,WRDATA} : DRAM_Q;
|
|
|
|
always @(DADDR or DRAM_Q)
|
|
case (DADDR)
|
|
2'b00 : CAP_Q = DRAM_Q[31:0];
|
|
2'b01 : CAP_Q = DRAM_Q[63:32];
|
|
2'b10 : CAP_Q = DRAM_Q[95:64];
|
|
2'b11 : CAP_Q = DRAM_Q[127:96];
|
|
endcase
|
|
|
|
always @(WRITE or VADDR or ENBYTE)
|
|
case ({WRITE,VADDR})
|
|
3'b100 : ENB = {4'd0 ,4'd0 ,4'd0 ,ENBYTE};
|
|
3'b101 : ENB = {4'd0 ,4'd0 ,ENBYTE,4'd0 };
|
|
3'b110 : ENB = {4'd0 ,ENBYTE,4'd0 ,4'd0 };
|
|
3'b111 : ENB = {ENBYTE,4'd0 ,4'd0 ,4'd0 };
|
|
default : ENB = 16'hFFFF;
|
|
endcase
|
|
|
|
endmodule
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// 2. NEU_VALID Cache Valid RAM
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module NEU_VALID ( BCLK, VALIN, WADR, WREN, RADR, VALOUT );
|
module NEU_VALID ( BCLK, VALIN, WADR, WREN, RADR, VALOUT );
|
|
|
input BCLK;
|
input BCLK;
|
Line 76... |
Line 118... |
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 2. DEBUG_AE Debug unit for address compare in data cache
|
// 3. DEBUG_AE Debug unit for address compare in data cache
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DEBUG_AE ( DBG_IN, READ, WRITE, USER, VIRTUELL, ACC_OK, VADR_R, MMU_Q, ENBYTE, DBG_HIT );
|
module DEBUG_AE ( DBG_IN, READ, WRITE, USER, VIRTUELL, ACC_OK, VADR_R, MMU_Q, ENBYTE, DBG_HIT );
|
|
|
input [40:2] DBG_IN;
|
input [40:2] DBG_IN;
|
Line 123... |
Line 165... |
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 3. MMU_UP MMU memory update and initalization controller
|
// 4. MMU_UP MMU memory update and initalization controller
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module MMU_UP ( BCLK, BRESET, NEW_PTB, PTB1, IVAR, WR_MRAM, VADR, VADR_R, MVALID, UPDATE,
|
module MMU_UP ( BCLK, BRESET, NEW_PTB, PTB1, IVAR, WR_MRAM, VADR, VADR_R, MVALID, UPDATE,
|
WE_MV, WADR_MV, RADR_MV, DAT_MV, NEW_PTB_RUN );
|
WE_MV, WADR_MV, RADR_MV, DAT_MV, NEW_PTB_RUN );
|
|
|
Line 174... |
Line 216... |
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 4. DCA_CONTROL Data cache valid memory update and initalization controller
|
// 5. DCA_CONTROL Data cache valid memory update and initalization controller
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DCA_CONTROL ( BCLK, MCLK, BRESET, CUPDATE, DRAM_ACC, CA_SET, HIT_ALL, WRCFG, VADR_R, UPDATE, INVAL_A, WRITE,
|
module DCA_CONTROL ( BCLK, BRESET, CUPDATE, DRAM_ACC, CA_SET, HIT_ALL, VADR_R, UPDATE, INVAL_A, WRITE, MDONE, USE_CA,
|
WCTRL, KILL, WRCRAM0, WRCRAM1, WE_CV, WADR_CV, DAT_CV, INIT_CA_RUN, WRSET0, WRSET1 );
|
INHIBIT, KILL, WRCRAM0, WRCRAM1, WE_CV, WADR_CV, DAT_CV, INIT_CA_RUN, WRSET0, WRSET1 );
|
|
|
input BCLK;
|
input BCLK;
|
input MCLK;
|
|
input BRESET;
|
input BRESET;
|
input CUPDATE; // State CUPDATE : Cache is filled from DRAM
|
input CUPDATE; // State CUPDATE : Cache is filled from DRAM
|
input DRAM_ACC;
|
input DRAM_ACC;
|
input CA_SET;
|
input CA_SET;
|
input HIT_ALL; // a complete cache hit !
|
input HIT_ALL; // a complete cache hit !
|
input WRCFG; // static signal : GND or VDD
|
|
input [11:7] VADR_R;
|
input [11:7] VADR_R;
|
input [23:0] UPDATE;
|
input [23:0] UPDATE;
|
input INVAL_A;
|
input INVAL_A;
|
input WRITE;
|
input WRITE;
|
input [1:0] WCTRL; // [1] : Read Burst Signal from DRAM controller, MCLK aligned. [0] : Cache inhibit
|
input MDONE; // Signal from DRAM : Access Done
|
|
input USE_CA; // Signal use cache
|
|
input INHIBIT; // Signal cache inhibit - no write in cache
|
input KILL; // valid Ram must be updated because of collision ... or CINV
|
input KILL; // valid Ram must be updated because of collision ... or CINV
|
|
|
output WRCRAM0,WRCRAM1;
|
output WRCRAM0,WRCRAM1;
|
output WE_CV;
|
output WE_CV;
|
output [4:0] WADR_CV;
|
output [4:0] WADR_CV;
|
Line 206... |
Line 248... |
|
|
reg [1:0] state;
|
reg [1:0] state;
|
reg [4:0] acount;
|
reg [4:0] acount;
|
reg ca_set_d;
|
reg ca_set_d;
|
|
|
reg dly_bclk,zero,wr_puls;
|
|
reg [2:0] count,refer;
|
|
|
|
wire countf;
|
wire countf;
|
|
|
always @(posedge BCLK) if (DRAM_ACC) ca_set_d <= CA_SET; // Store for whole access
|
always @(posedge BCLK) if (DRAM_ACC) ca_set_d <= CA_SET; // Store for whole access
|
|
|
// physical address is stored in TAG-RAM
|
// physical address is stored in TAG-RAM
|
|
|
assign WRCRAM0 = (CUPDATE & ~WCTRL[0]) & ~ca_set_d;
|
assign WRCRAM0 = (CUPDATE & ~INHIBIT) & ~ca_set_d;
|
assign WRCRAM1 = (CUPDATE & ~WCTRL[0]) & ca_set_d;
|
assign WRCRAM1 = (CUPDATE & ~INHIBIT) & ca_set_d;
|
|
|
// Load Valid RAM :
|
// Load Valid RAM :
|
|
|
assign WE_CV = state[1] | HIT_ALL | (CUPDATE & ~WCTRL[0]) | KILL; // Hit All for "Last" Update
|
assign WE_CV = state[1] | HIT_ALL | (CUPDATE & ~INHIBIT) | KILL; // Hit All for "Last" Update
|
assign WADR_CV = state[1] ? acount : VADR_R;
|
assign WADR_CV = state[1] ? acount : VADR_R;
|
assign DAT_CV = state[1] ? 24'h0 : UPDATE;
|
assign DAT_CV = state[1] ? 24'h0 : UPDATE;
|
|
|
// Clear of Cache-Valid RAMs : 32 clocks of BCLK
|
// Clear of Cache-Valid RAMs : 32 clocks of BCLK
|
|
|
Line 244... |
Line 283... |
always @(posedge BCLK) if (!state[1]) acount <= 5'h0; else acount <= acount + 5'h01;
|
always @(posedge BCLK) if (!state[1]) acount <= 5'h0; else acount <= acount + 5'h01;
|
|
|
assign INIT_CA_RUN = state[1];
|
assign INIT_CA_RUN = state[1];
|
|
|
// WRITE Control in data RAMs
|
// WRITE Control in data RAMs
|
assign WRSET0 = ( ~CA_SET & WRITE & HIT_ALL & wr_puls) | (WCTRL[1] & ~ca_set_d);
|
assign WRSET0 = ( ~CA_SET & WRITE & HIT_ALL) | (MDONE & USE_CA & ~ca_set_d);
|
assign WRSET1 = ( CA_SET & WRITE & HIT_ALL & wr_puls) | (WCTRL[1] & ca_set_d);
|
assign WRSET1 = ( CA_SET & WRITE & HIT_ALL) | (MDONE & USE_CA & ca_set_d);
|
|
|
// ++++++++++++ Special circuit for Timing of write pulse for data RAM of data cache +++++++++
|
|
|
|
always @(negedge MCLK) dly_bclk <= BCLK;
|
|
|
|
always @(negedge MCLK) zero <= BCLK & ~dly_bclk;
|
|
|
|
always @(posedge MCLK) if (zero) count <= 3'd0; else count <= count + 3'd1;
|
|
|
|
// count at zero , ref Wert
|
|
// 1 : --- always on 5 : 100 001
|
|
// 2 : 001 000 6 : 101 010
|
|
// 3 : 010 010 7 : 110 011
|
|
// 4 : 011 000 8 : 111 100
|
|
always @(posedge MCLK) if (zero) refer <= {(count == 3'd7),((count == 3'd5) | (count[1:0] == 2'b10)),(count[2] & ~count[0])};
|
|
|
|
always @(posedge MCLK) wr_puls <= (count == refer) | WRCFG;
|
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 5. MMU_MATCH MMU virtual address match detector
|
// 6. MMU_MATCH MMU virtual address match detector
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module MMU_MATCH ( USER, READ, WRITE, RMW, MCR_FLAGS, MVALID, VADR_R, MMU_VA, IVAR,
|
module MMU_MATCH ( USER, READ, WRITE, RMW, MCR_FLAGS, MVALID, VADR_R, MMU_VA, IVAR,
|
VIRTUELL, MMU_HIT , UPDATE, PROT_ERROR, CI, SEL_PTB1 );
|
VIRTUELL, MMU_HIT , UPDATE, PROT_ERROR, CI, SEL_PTB1 );
|
|
|
Line 355... |
Line 377... |
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 6. CA_MATCH Cache tag match detector
|
// 7. CA_MATCH Cache tag match detector
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module CA_MATCH ( CVALID, DRAMSZ, ADDR, TAG0, TAG1, CFG, WRITE, MMU_HIT, CI, INVAL_L, KDET, ENDRAM, DC_ILO,
|
module CA_MATCH ( CVALID, DRAMSZ, ADDR, TAG0, TAG1, CFG, WRITE, MMU_HIT, CI, INVAL_L, KDET, ENDRAM, DC_ILO,
|
CA_HIT, CA_SET, UPDATE, IO_SPACE, USE_CA, WB_ACC, KILL );
|
CA_HIT, CA_SET, UPDATE, IO_SPACE, USE_CA, WB_ACC, KILL );
|
|
|
input [23:0] CVALID;
|
input [23:0] CVALID;
|
input [2:0] DRAMSZ;
|
input [2:0] DRAMSZ;
|
input [31:4] ADDR;
|
input [31:4] ADDR;
|
input [27:12] TAG0,TAG1;
|
input [28:12] TAG0,TAG1;
|
input [1:0] CFG; // LDC , DC
|
input [1:0] CFG; // LDC , DC
|
input WRITE;
|
input WRITE;
|
input MMU_HIT;
|
input MMU_HIT;
|
input CI;
|
input CI;
|
input INVAL_L; // invalid cache line
|
input INVAL_L; // invalid cache line
|
Line 383... |
Line 405... |
output USE_CA;
|
output USE_CA;
|
output WB_ACC;
|
output WB_ACC;
|
output KILL;
|
output KILL;
|
|
|
reg [7:0] maske;
|
reg [7:0] maske;
|
reg [4:0] szmaske;
|
reg acc_dram;
|
|
|
wire match_0,match_1;
|
wire match_0,match_1;
|
wire valid_0,valid_1;
|
wire valid_0,valid_1;
|
wire select;
|
wire select;
|
wire clear;
|
wire clear;
|
wire [7:0] update_0,update_1,lastinfo;
|
wire [7:0] update_0,update_1,lastinfo;
|
wire sel_dram,filter;
|
wire sel_dram;
|
|
|
always @(ADDR)
|
always @(ADDR)
|
case (ADDR[6:4])
|
case (ADDR[6:4])
|
3'h0 : maske = 8'h01;
|
3'h0 : maske = 8'h01;
|
3'h1 : maske = 8'h02;
|
3'h1 : maske = 8'h02;
|
Line 407... |
Line 429... |
endcase
|
endcase
|
|
|
assign valid_0 = (( CVALID[7:0] & maske) != 8'h00);
|
assign valid_0 = (( CVALID[7:0] & maske) != 8'h00);
|
assign valid_1 = ((CVALID[15:8] & maske) != 8'h00);
|
assign valid_1 = ((CVALID[15:8] & maske) != 8'h00);
|
|
|
assign match_0 = ( TAG0 == ADDR[27:12] ); // 4KB
|
assign match_0 = ( TAG0 == ADDR[28:12] ); // 4KB
|
assign match_1 = ( TAG1 == ADDR[27:12] ); // 4KB
|
assign match_1 = ( TAG1 == ADDR[28:12] ); // 4KB
|
|
|
assign CA_HIT = ((valid_0 & match_0) | (valid_1 & match_1)) & ~DC_ILO & CFG[0];
|
assign CA_HIT = ((valid_0 & match_0) | (valid_1 & match_1)) & ~DC_ILO & CFG[0] & (sel_dram | KDET);
|
|
|
// which SET is written in cache miss ? If both are valid the last used is not taken
|
// which SET is written in cache miss ? If both are valid the last used is not taken
|
assign select = (valid_1 & valid_0) ? ~((CVALID[23:16] & maske) != 8'h00) : valid_0; // Last-used field = CVALID[23:16]
|
assign select = (valid_1 & valid_0) ? ~((CVALID[23:16] & maske) != 8'h00) : valid_0; // Last-used field = CVALID[23:16]
|
|
|
assign CA_SET = CA_HIT ? (valid_1 & match_1) : select;
|
assign CA_SET = CA_HIT ? (valid_1 & match_1) : select;
|
Line 428... |
Line 450... |
|
|
assign UPDATE = {lastinfo,update_1,update_0};
|
assign UPDATE = {lastinfo,update_1,update_0};
|
|
|
assign KILL = clear & CA_HIT & ~CFG[1]; // only if cache is not locked
|
assign KILL = clear & CA_HIT & ~CFG[1]; // only if cache is not locked
|
|
|
always @(DRAMSZ) // Size of DRAM
|
always @(DRAMSZ or ADDR) // Size of DRAM
|
casex (DRAMSZ)
|
case (DRAMSZ)
|
3'b00x : szmaske = 5'h1F; // 8 MB 32016 Second Processor
|
3'b000 : acc_dram = (ADDR[28:23] == 6'd0); // 8 MB 32016 Second Processor
|
// 3'b001 reserved for Ceres III
|
3'b001 : acc_dram = (ADDR[28:24] == 5'd0); // 16 MB
|
3'b01x : szmaske = 5'h10; // 128 MB MCUBE
|
3'b010 : acc_dram = (ADDR[28:25] == 4'd0); // 32 MB
|
default : szmaske = 5'h00; // 256 MB NetBSD
|
3'b011 : acc_dram = (ADDR[28:26] == 3'd0); // 64 MB
|
|
3'b100 : acc_dram = (ADDR[28:27] == 2'd0); // 128 MB
|
|
3'b101 : acc_dram = ~ADDR[28]; // 256 MB
|
|
3'b110 : acc_dram = 1'b1; // 512 MB
|
|
3'b111 : acc_dram = ~(ADDR[28:27] == 2'b10); // 256 MB NetBSD + 128 MB
|
endcase
|
endcase
|
|
|
assign filter = ((ADDR[27:23] & szmaske) == 5'd0);
|
assign sel_dram = (ADDR[31:29] == 3'd0) & acc_dram & ENDRAM;
|
assign sel_dram = (ADDR[31:28] == 4'd0) & filter & ENDRAM;
|
|
assign IO_SPACE = ~sel_dram; // not DRAM or DRAM ist off
|
assign IO_SPACE = ~sel_dram; // not DRAM or DRAM ist off
|
|
|
assign USE_CA = ~CI & ~DC_ILO & CFG[0] & ~CFG[1]; // CI ? ILO ? Cache on ? Locked Cache ?
|
assign USE_CA = ~CI & ~DC_ILO & CFG[0] & ~CFG[1]; // CI ? ILO ? Cache on ? Locked Cache ?
|
assign WB_ACC = WRITE & MMU_HIT & sel_dram;
|
assign WB_ACC = WRITE & MMU_HIT & sel_dram;
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 7. FILTCMP Address Filter and Comparator
|
// 8. FILTCMP Address Filter and Comparator
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module FILTCMP ( DRAMSZ, RADR, DRAM_A, ADR_EQU, TAGDAT );
|
module FILTCMP ( DRAMSZ, RADR, DRAM_A, ADR_EQU, TAGDAT );
|
|
|
input [2:0] DRAMSZ;
|
input [2:0] DRAMSZ;
|
input [27:4] RADR,DRAM_A;
|
input [28:4] RADR,DRAM_A;
|
|
|
output ADR_EQU;
|
output ADR_EQU;
|
output reg [27:12] TAGDAT;
|
output reg [28:12] TAGDAT;
|
|
|
reg [27:23] adram;
|
reg [28:23] adram;
|
|
|
always @(DRAMSZ or RADR)
|
always @(DRAMSZ or RADR)
|
casex (DRAMSZ)
|
casex (DRAMSZ)
|
3'b00x : TAGDAT = {5'd0,RADR[22:12]}; // 8 MB
|
3'b000 : TAGDAT = {6'd0,RADR[22:12]}; // 8 MB
|
3'bx10 : TAGDAT = {3'd0,RADR[24:12]}; // 32 MB
|
3'b001 : TAGDAT = {5'd0,RADR[23:12]}; // 16 MB
|
3'bx11 : TAGDAT = {2'd0,RADR[25:12]}; // 64 MB
|
3'b010 : TAGDAT = {4'd0,RADR[24:12]}; // 32 MB
|
3'b100 : TAGDAT = {1'd0,RADR[26:12]}; // 128 MB
|
3'b011 : TAGDAT = {3'd0,RADR[25:12]}; // 64 MB
|
3'b101 : TAGDAT = RADR[27:12] ; // 256 MB
|
3'b100 : TAGDAT = {2'd0,RADR[26:12]}; // 128 MB
|
|
3'b101 : TAGDAT = {1'b0,RADR[27:12]}; // 256 MB
|
|
3'b11x : TAGDAT = RADR[28:12] ; // 512 MB
|
endcase
|
endcase
|
|
|
always @(DRAMSZ or DRAM_A) // The address comparator is only used in the data cache.
|
always @(DRAMSZ or DRAM_A) // The address comparator is only used in the data cache.
|
casex (DRAMSZ)
|
casex (DRAMSZ)
|
3'b00x : adram = 5'd0; // 8 MB
|
3'b000 : adram = 6'd0; // 8 MB
|
3'bx10 : adram = {3'd0,DRAM_A[24:23]}; // 32 MB
|
3'b001 : adram = {5'd0,DRAM_A[23]}; // 16 MB
|
3'bx11 : adram = {2'd0,DRAM_A[25:23]}; // 64 MB
|
3'b010 : adram = {4'd0,DRAM_A[24:23]}; // 32 MB
|
3'b100 : adram = {1'd0,DRAM_A[26:23]}; // 128 MB
|
3'b011 : adram = {3'd0,DRAM_A[25:23]}; // 64 MB
|
3'b101 : adram = DRAM_A[27:23] ; // 256 MB
|
3'b100 : adram = {2'd0,DRAM_A[26:23]}; // 128 MB
|
|
3'b101 : adram = {1'd0,DRAM_A[27:23]}; // 256 MB
|
|
3'b11x : adram = DRAM_A[28:23] ; // 512 MB
|
endcase
|
endcase
|
|
|
assign ADR_EQU = {TAGDAT,RADR[11:4]} == {adram,DRAM_A[22:4]};
|
assign ADR_EQU = {TAGDAT,RADR[11:4]} == {adram,DRAM_A[22:4]};
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 8. DCACHE_SM Data cache state machine
|
// 9. DCACHE_SM Data cache state machine
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DCACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, WRITE, ZTEST, RMW, CAPDAT, VADR_R, IC_VA,
|
module DCACHE_SM ( BCLK, BRESET, IO_SPACE, MDONE, IO_READY, MMU_HIT, CA_HIT, READ, WRITE, ZTEST, RMW, CAPDAT, VADR_R, IC_VA,
|
USE_CA, PTB_WR, PTB_SEL, SEL_PTB1, CPU_OUT, USER, PROT_ERROR, WB_ACC, ENWR, ADR_EQU, IC_PREQ, DMA_CHK, ICTODC,
|
USE_CA, PTB_WR, PTB_SEL, SEL_PTB1, CPU_OUT, USER, PROT_ERROR, WB_ACC, ENWR, ADR_EQU, IC_PREQ, DMA_CHK, ICTODC,
|
RWVAL, VIRTUELL, QWATWO,
|
RWVAL, VIRTUELL, QWATWO,
|
Line 506... |
Line 535... |
input [31:0] CAPDAT;
|
input [31:0] CAPDAT;
|
input [31:12] VADR_R,IC_VA;
|
input [31:12] VADR_R,IC_VA;
|
input USE_CA;
|
input USE_CA;
|
input PTB_WR,PTB_SEL;
|
input PTB_WR,PTB_SEL;
|
input SEL_PTB1;
|
input SEL_PTB1;
|
input [27:12] CPU_OUT; // used for PTB0/1
|
input [28:12] CPU_OUT; // used for PTB0/1
|
input USER;
|
input USER;
|
input PROT_ERROR;
|
input PROT_ERROR;
|
input WB_ACC;
|
input WB_ACC;
|
input ENWR; // Enable WRITE from DRAM
|
input ENWR; // Enable WRITE from DRAM
|
input ADR_EQU;
|
input ADR_EQU;
|
Line 522... |
Line 551... |
input QWATWO;
|
input QWATWO;
|
|
|
output reg DRAM_ACC,DRAM_WR;
|
output reg DRAM_ACC,DRAM_WR;
|
output IO_ACC,IO_RD,IO_WR;
|
output IO_ACC,IO_RD,IO_WR;
|
output PTE_MUX,PD_MUX,PKEEP;
|
output PTE_MUX,PD_MUX,PKEEP;
|
output [27:0] PTE_ADR;
|
output [28:0] PTE_ADR;
|
output [19:0] PTE_DAT;
|
output [19:0] PTE_DAT;
|
output HIT_ALL;
|
output HIT_ALL;
|
output ACC_OK;
|
output ACC_OK;
|
output ABORT,PROTECT;
|
output ABORT,PROTECT;
|
output [3:1] IACC_STAT;
|
output [3:1] IACC_STAT;
|
Line 546... |
Line 575... |
output [1:0] PTE_STAT;
|
output [1:0] PTE_STAT;
|
|
|
reg IO_WR,IO_RD;
|
reg IO_WR,IO_RD;
|
reg [1:0] pl_dat;
|
reg [1:0] pl_dat;
|
reg [6:0] new_state;
|
reg [6:0] new_state;
|
reg [2:0] cap_dat; // only for analyse of timing
|
|
reg mem_done;
|
reg mem_done;
|
reg rd_done;
|
reg rd_done;
|
reg [2:0] pstate;
|
reg [2:0] pstate;
|
reg pte_run_wr;
|
reg pte_run_wr;
|
reg [1:0] prot_level1;
|
reg [1:0] prot_level1;
|
reg card_flag;
|
reg card_flag;
|
reg [27:12] ptb0,ptb1;
|
reg [28:12] ptb0,ptb1;
|
reg write_ok;
|
reg write_ok;
|
reg icp_acc;
|
reg icp_acc;
|
reg pte_modi;
|
|
reg [2:0] ko_state;
|
reg [2:0] ko_state;
|
reg dma_run;
|
reg dma_run;
|
reg dma_kdet;
|
reg dma_kdet;
|
reg rwv_bit;
|
reg rwv_bit;
|
reg prot_i;
|
reg prot_i;
|
reg rd_rdy;
|
reg rd_rdy;
|
|
|
wire [27:12] ptb10;
|
wire [28:12] ptb10;
|
wire [31:12] virtual_adr;
|
wire [31:12] virtual_adr;
|
wire io_busy;
|
wire io_busy;
|
wire dram_go;
|
wire dram_go;
|
wire pte_sel;
|
wire pte_sel;
|
wire pte_acc;
|
wire pte_acc;
|
Line 592... |
Line 619... |
wire zt_ok;
|
wire zt_ok;
|
wire [1:0] acc_level;
|
wire [1:0] acc_level;
|
wire user_ptw,wr_ptw;
|
wire user_ptw,wr_ptw;
|
wire pte_puls;
|
wire pte_puls;
|
|
|
always @(posedge BCLK) cap_dat <= CAPDAT[2:0];
|
|
|
|
// if USER not virtual then ZTEST is quickly done
|
// if USER not virtual then ZTEST is quickly done
|
assign zugriff = READ | WRITE | (ZTEST & VIRTUELL);
|
assign zugriff = READ | WRITE | (ZTEST & VIRTUELL);
|
assign mmu_hit_i = MMU_HIT & ~ZTEST;
|
assign mmu_hit_i = MMU_HIT & ~ZTEST;
|
|
|
// WB_ACC is a successful WRITE access, ICTODC[0] is coherent Logik release : >=3 entries in FIFO
|
// WB_ACC is a successful WRITE access, ICTODC[0] is coherent Logik release : >=3 entries in FIFO
|
Line 652... |
Line 677... |
// ZTEST logic is for the special case when a write access is crossing page boundaries
|
// ZTEST logic is for the special case when a write access is crossing page boundaries
|
|
|
assign do_zt = ZTEST & ~icp_acc;
|
assign do_zt = ZTEST & ~icp_acc;
|
|
|
// 0 is pass , 1 is blocked. RWVAL[0] is 1 if WRVAL. Level 1 can only be blocked, otherwise ABORT or Level 2 is following.
|
// 0 is pass , 1 is blocked. RWVAL[0] is 1 if WRVAL. Level 1 can only be blocked, otherwise ABORT or Level 2 is following.
|
always @(posedge BCLK) if (mem_done) rwv_bit <= level2 ? ~(cap_dat[2] & (~RWVAL[0] | cap_dat[1])) : 1'b1;
|
always @(posedge BCLK) if (mem_done) rwv_bit <= level2 ? ~(CAPDAT[2] & (~RWVAL[0] | CAPDAT[1])) : 1'b1;
|
|
|
assign RWVFLAG = VIRTUELL & rwv_bit;
|
assign RWVFLAG = VIRTUELL & rwv_bit;
|
|
|
assign zt_ok = mem_done & (RWVAL[1] ? (~cap_dat[2] | (RWVAL[0] & ~cap_dat[1]) | level2) // Level 2 always ok
|
assign zt_ok = mem_done & (RWVAL[1] ? (~CAPDAT[2] | (RWVAL[0] & ~CAPDAT[1]) | level2) // Level 2 always ok
|
: (cap_dat[0] & ~prot_i & level2) ); // "normal" access
|
: (CAPDAT[0] & ~prot_i & level2) ); // "normal" access
|
|
|
// PTE access logic, normal state machine
|
// PTE access logic, normal state machine
|
// Updates to the PTEs are normal WRITE request to DRAM, therefore no MDONE at Write
|
// Updates to the PTEs are normal WRITE request to DRAM, therefore no MDONE at Write
|
|
|
assign modi = ~CAPDAT[8] & WRITE & write_ok & ~icp_acc; // is "1" if the Modified Bit must be set
|
assign modi = ~CAPDAT[8] & WRITE & write_ok & ~icp_acc; // is "1" if the Modified Bit must be set
|
assign refer = CAPDAT[7] | do_zt; // Assumption "R" Bit is set if RDVAL/WRVAL and page border test
|
assign refer = CAPDAT[7] | do_zt; // Assumption "R" Bit is set if RDVAL/WRVAL and page border test
|
assign valid = (do_zt & RWVAL[1]) ? (cap_dat[2] & (cap_dat[1] | ~RWVAL[0]) & cap_dat[0] & level1)
|
assign valid = (do_zt & RWVAL[1]) ? (CAPDAT[2] & (CAPDAT[1] | ~RWVAL[0]) & CAPDAT[0] & level1)
|
: (cap_dat[0] & ~prot_i);
|
: (CAPDAT[0] & ~prot_i);
|
|
|
always @(posedge BCLK) mem_done <= MDONE & pte_acc;
|
always @(posedge BCLK) mem_done <= MDONE & pte_acc;
|
|
|
always @(posedge BCLK or negedge BRESET)
|
always @(posedge BCLK or negedge BRESET)
|
if (!BRESET) pstate <= 3'h0;
|
if (!BRESET) pstate <= 3'h0;
|
Line 695... |
Line 720... |
|
|
assign pte_acc = pstate[2];
|
assign pte_acc = pstate[2];
|
assign level1 = ~pstate[1];
|
assign level1 = ~pstate[1];
|
assign level2 = pstate[1];
|
assign level2 = pstate[1];
|
|
|
assign valid_a = (ZTEST & RWVAL[1]) ? (cap_dat[2] & (cap_dat[1] | ~RWVAL[0]) & ~cap_dat[0] & level1)
|
assign valid_a = (ZTEST & RWVAL[1]) ? (CAPDAT[2] & (CAPDAT[1] | ~RWVAL[0]) & ~CAPDAT[0] & level1)
|
: ~cap_dat[0]; // not do_zt because of icp_acc in ABORT
|
: ~CAPDAT[0]; // not do_zt because of icp_acc in ABORT
|
|
|
assign ABORT = mem_done & valid_a & ~icp_acc;
|
assign ABORT = mem_done & valid_a & ~icp_acc;
|
assign PROTECT = ((mem_done & prot_i & ~icp_acc) | PROT_ERROR) & ~(ZTEST & RWVAL[1]); // no Protection-Error at RDVAL/WRVAL
|
assign PROTECT = ((mem_done & prot_i & ~icp_acc) | PROT_ERROR) & ~(ZTEST & RWVAL[1]); // no Protection-Error at RDVAL/WRVAL
|
|
|
assign IACC_STAT[1] = mem_done & ~cap_dat[0] & icp_acc;
|
assign IACC_STAT[1] = mem_done & ~CAPDAT[0] & icp_acc;
|
assign IACC_STAT[2] = level1;
|
assign IACC_STAT[2] = level1;
|
assign IACC_STAT[3] = mem_done & prot_i & icp_acc;
|
assign IACC_STAT[3] = mem_done & prot_i & icp_acc;
|
|
|
assign ABO_LEVEL1 = level1; // is stored in case of ABORT in ADDR_UNIT
|
assign ABO_LEVEL1 = level1; // is stored in case of ABORT in ADDR_UNIT
|
|
|
Line 799... |
Line 824... |
assign ACC_OK = ZTEST ? (~VIRTUELL | zt_ok)
|
assign ACC_OK = ZTEST ? (~VIRTUELL | zt_ok)
|
: (IO_SPACE ? ((IO_ACC & WRITE) | rd_done) : (wr_dram | (READ & MMU_HIT & rd_ende & run_dc)) );
|
: (IO_SPACE ? ((IO_ACC & WRITE) | rd_done) : (wr_dram | (READ & MMU_HIT & rd_ende & run_dc)) );
|
|
|
// PTB1 and PTB0
|
// PTB1 and PTB0
|
|
|
always @(posedge BCLK) if (PTB_WR && !PTB_SEL) ptb0 <= CPU_OUT[27:12];
|
always @(posedge BCLK) if (PTB_WR && !PTB_SEL) ptb0 <= CPU_OUT;
|
always @(posedge BCLK) if (PTB_WR && PTB_SEL) ptb1 <= CPU_OUT[27:12];
|
always @(posedge BCLK) if (PTB_WR && PTB_SEL) ptb1 <= CPU_OUT;
|
|
|
always @(posedge BCLK) NEW_PTB <= PTB_WR; // to MMU Update Block
|
always @(posedge BCLK) NEW_PTB <= PTB_WR; // to MMU Update Block
|
always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL;
|
always @(posedge BCLK) if (PTB_WR) PTB_ONE <= PTB_SEL;
|
|
|
assign ptb10 = SEL_PTB1 ? ptb1 : ptb0;
|
assign ptb10 = SEL_PTB1 ? ptb1 : ptb0;
|
Line 815... |
Line 840... |
assign pte_sel = pte_go ? do_ic_p : icp_acc;
|
assign pte_sel = pte_go ? do_ic_p : icp_acc;
|
|
|
assign virtual_adr = pte_sel ? IC_VA : VADR_R;
|
assign virtual_adr = pte_sel ? IC_VA : VADR_R;
|
|
|
// The 2 Address-LSB's : no full access : USE_CA = 0
|
// The 2 Address-LSB's : no full access : USE_CA = 0
|
assign PTE_ADR = rd_level2 ? {CAPDAT[27:12],virtual_adr[21:12],2'b00} : {ptb10,virtual_adr[31:22],2'b00};
|
assign PTE_ADR = rd_level2 ? {CAPDAT[28:12],virtual_adr[21:12],2'b00} : {ptb10,virtual_adr[31:22],2'b00};
|
|
|
// PTE_DAT[8] is used for update of MMU_RAM.
|
// PTE_DAT[8] is used for update of MMU_RAM.
|
assign pte_dat_8 = (level2 & WRITE & write_ok & ~icp_acc) | CAPDAT[8];
|
assign pte_dat_8 = (level2 & WRITE & write_ok & ~icp_acc) | CAPDAT[8];
|
always @(posedge BCLK) pte_modi = pte_dat_8;
|
assign PTE_DAT = {4'h3,CAPDAT[15:9],pte_dat_8,1'b1,CAPDAT[6:0]}; // the top 4 bits are Byte-Enable
|
assign PTE_DAT = {4'h3,CAPDAT[15:9],pte_modi,1'b1,CAPDAT[6:0]}; // the top 4 bits are Byte-Enable
|
|
|
|
// The data for the MMU-RAM : 24 Bits , [6]=Cache Inhibit
|
// The data for the MMU-RAM : 24 Bits , [6]=Cache Inhibit
|
assign MMU_DIN = {pl_dat,pte_dat_8,CAPDAT[6],CAPDAT[31:12]};
|
assign MMU_DIN = {pl_dat,pte_dat_8,CAPDAT[6],CAPDAT[31:12]};
|
|
|
// Protection field
|
// Protection field
|
|
|
always @(posedge BCLK) if (mem_done && (pstate[2:0] == 3'd4)) prot_level1 <= cap_dat[2:1];
|
always @(posedge BCLK) if (mem_done && (pstate[2:0] == 3'd4)) prot_level1 <= CAPDAT[2:1];
|
|
|
always @(prot_level1 or cap_dat)
|
always @(prot_level1 or CAPDAT)
|
casex ({prot_level1,cap_dat[2]})
|
casex ({prot_level1,CAPDAT[2]})
|
3'b11_x : pl_dat = cap_dat[2:1];
|
3'b11_x : pl_dat = CAPDAT[2:1];
|
3'b10_1 : pl_dat = 2'b10;
|
3'b10_1 : pl_dat = 2'b10;
|
3'b10_0 : pl_dat = cap_dat[2:1];
|
3'b10_0 : pl_dat = CAPDAT[2:1];
|
3'b01_1 : pl_dat = 2'b01;
|
3'b01_1 : pl_dat = 2'b01;
|
3'b01_0 : pl_dat = cap_dat[2:1];
|
3'b01_0 : pl_dat = CAPDAT[2:1];
|
3'b00_x : pl_dat = 2'b00;
|
3'b00_x : pl_dat = 2'b00;
|
endcase
|
endcase
|
|
|
always @(USER or pl_dat) // is used if no PTE update is neccesary for M-Bit if writing is not allowed
|
always @(USER or pl_dat) // is used if no PTE update is neccesary for M-Bit if writing is not allowed
|
casex ({USER,pl_dat})
|
casex ({USER,pl_dat})
|
Line 847... |
Line 871... |
3'b0_1x : write_ok = 1'b1;
|
3'b0_1x : write_ok = 1'b1;
|
3'b0_01 : write_ok = 1'b1;
|
3'b0_01 : write_ok = 1'b1;
|
default : write_ok = 1'b0;
|
default : write_ok = 1'b0;
|
endcase
|
endcase
|
|
|
assign acc_level = level2 ? pl_dat : cap_dat[2:1];
|
assign acc_level = level2 ? pl_dat : CAPDAT[2:1];
|
assign user_ptw = icp_acc ? ICTODC[3] : USER;
|
assign user_ptw = icp_acc ? ICTODC[3] : USER;
|
assign wr_ptw = ~icp_acc & (WRITE | RMW | (ZTEST & ~RWVAL[1])); // only data cache can write
|
assign wr_ptw = ~icp_acc & (WRITE | RMW | (ZTEST & ~RWVAL[1])); // only data cache can write
|
|
|
always @(acc_level or user_ptw or wr_ptw)
|
always @(acc_level or user_ptw or wr_ptw)
|
case (acc_level)
|
case (acc_level)
|