/******************************************************************************/
/* */
/* Copyright (c) 1999 Sun Microsystems, Inc. All rights reserved. */
/* */
/* The contents of this file are subject to the current version of the Sun */
/* Community Source License, microSPARCII ("the License"). You may not use */
/* this file except in compliance with the License. You may obtain a copy */
/* of the License by searching for "Sun Community Source License" on the */
/* World Wide Web at http://www.sun.com. See the License for the rights, */
/* obligations, and limitations governing use of the contents of this file. */
/* */
/* Sun Microsystems, Inc. has intellectual property rights relating to the */
/* technology embodied in these files. In particular, and without limitation, */
/* these intellectual property rights may include one or more U.S. patents, */
/* foreign patents, or pending applications. */
/* */
/* Sun, Sun Microsystems, the Sun logo, all Sun-based trademarks and logos, */
/* Solaris, Java and all Java-based trademarks and logos are trademarks or */
/* registered trademarks of Sun Microsystems, Inc. in the United States and */
/* other countries. microSPARC is a trademark or registered trademark of */
/* SPARC International, Inc. All SPARC trademarks are used under license and */
/* are trademarks or registered trademarks of SPARC International, Inc. in */
/* the United States and other countries. Products bearing SPARC trademarks */
/* are based upon an architecture developed by Sun Microsystems, Inc. */
/* */
/******************************************************************************/
//***************************************************************************
// mc_e_tlb.v
//
//
// Description :
// RTL level for TLB megecell emulation
//
// Created: 11/12/91
//
//****************************************************************************
module IOTLB
(RD_OUT27,RD_OUT26,RD_OUT25,RD_OUT24,RD_OUT23,RD_OUT22,RD_OUT21,RD_OUT20,RD_OUT19,RD_OUT18,RD_OUT17,RD_OUT16,RD_OUT15,RD_OUT14,RD_OUT13,RD_OUT12,RD_OUT11,RD_OUT10,RD_OUT9,RD_OUT8,RD_OUT7,RD_OUT6,RD_OUT5,RD_OUT4,RD_OUT3,RD_OUT2,RD_OUT1,RD_OUT0,
CD_OUT41,CD_OUT40,CD_OUT39,CD_OUT38,CD_OUT37,CD_OUT36,CD_OUT35,CD_OUT34,CD_OUT33,CD_OUT32,CD_OUT31,CD_OUT30,CD_OUT29,CD_OUT28,CD_OUT27,CD_OUT26,CD_OUT25,CD_OUT24,CD_OUT23,CD_OUT22,CD_OUT21,CD_OUT20,CD_OUT19,CD_OUT18,CD_OUT17,CD_OUT16,CD_OUT15,CD_OUT14,CD_OUT13,CD_OUT12,CD_OUT11,CD_OUT10,CD_OUT9,CD_OUT8,CD_OUT7,CD_OUT6,CD_OUT5,CD_OUT4,CD_OUT3,CD_OUT2,CD_OUT1,CD_OUT0,
MISS,
ACC_OK,
ERROR,
M_MISS,
RD_IN27,RD_IN26,RD_IN25,RD_IN24,RD_IN23,RD_IN22,RD_IN21,RD_IN20,RD_IN19,RD_IN18,RD_IN17,RD_IN16,RD_IN15,RD_IN14,RD_IN13,RD_IN12,RD_IN11,RD_IN10,RD_IN9,RD_IN8,RD_IN7,RD_IN6,RD_IN5,RD_IN4,RD_IN3,RD_IN2,RD_IN1,RD_IN0,
CD_IN41,CD_IN40,CD_IN39,CD_IN38,CD_IN37,CD_IN36,CD_IN35,CD_IN34,CD_IN33,CD_IN32,CD_IN31,CD_IN30,CD_IN29,CD_IN28,CD_IN27,CD_IN26,CD_IN25,CD_IN24,CD_IN23,CD_IN22,CD_IN21,CD_IN20,CD_IN19,CD_IN18,CD_IN17,CD_IN16,CD_IN15,CD_IN14,CD_IN13,CD_IN12,CD_IN11,CD_IN10,CD_IN9,CD_IN8,CD_IN7,CD_IN6,CD_IN5,CD_IN4,CD_IN3,CD_IN2,CD_IN1,CD_IN0,
FLUSH,
TLB_WE,
ASEL,
ADDR3,ADDR2,ADDR1,ADDR0,
CO_IN,
CR,
CLK,
RST);
// SCM,
// SCN_IN,
// TG_STROBE,
// SCN_OUT,
// PDM,
input RD_IN27
,RD_IN26
,RD_IN25
,RD_IN24
,RD_IN23
,RD_IN22
,RD_IN21
,RD_IN20
,RD_IN19
,RD_IN18
,RD_IN17
,RD_IN16
,RD_IN15
,RD_IN14
,RD_IN13
,RD_IN12
,RD_IN11
,RD_IN10
,RD_IN9
,RD_IN8
,RD_IN7
,RD_IN6
,RD_IN5
,RD_IN4
,RD_IN3
,RD_IN2
,RD_IN1
,RD_IN0
,
CD_IN41
,CD_IN40
,CD_IN39
,CD_IN38
,CD_IN37
,CD_IN36
,CD_IN35
,CD_IN34
,CD_IN33
,CD_IN32
,CD_IN31
,CD_IN30
,CD_IN29
,CD_IN28
,CD_IN27
,CD_IN26
,CD_IN25
,CD_IN24
,CD_IN23
,CD_IN22
,CD_IN21
,CD_IN20
,CD_IN19
,CD_IN18
,CD_IN17
,CD_IN16
,CD_IN15
,CD_IN14
,CD_IN13
,CD_IN12
,CD_IN11
,CD_IN10
,CD_IN9
,CD_IN8
,CD_IN7
,CD_IN6
,CD_IN5
,CD_IN4
,CD_IN3
,CD_IN2
,CD_IN1
,CD_IN0
,
FLUSH
,
TLB_WE
,
ASEL
,
ADDR3
,ADDR2
,ADDR1
,ADDR0
,
CO_IN
,
CR
,
CLK
,
RST
;
output RD_OUT27
,RD_OUT26
,RD_OUT25
,RD_OUT24
,RD_OUT23
,RD_OUT22
,RD_OUT21
,RD_OUT20
,RD_OUT19
,RD_OUT18
,RD_OUT17
,RD_OUT16
,RD_OUT15
,RD_OUT14
,RD_OUT13
,RD_OUT12
,RD_OUT11
,RD_OUT10
,RD_OUT9
,RD_OUT8
,RD_OUT7
,RD_OUT6
,RD_OUT5
,RD_OUT4
,RD_OUT3
,RD_OUT2
,RD_OUT1
,RD_OUT0
,
CD_OUT41
,CD_OUT40
,CD_OUT39
,CD_OUT38
,CD_OUT37
,CD_OUT36
,CD_OUT35
,CD_OUT34
,CD_OUT33
,CD_OUT32
,CD_OUT31
,CD_OUT30
,CD_OUT29
,CD_OUT28
,CD_OUT27
,CD_OUT26
,CD_OUT25
,CD_OUT24
,CD_OUT23
,CD_OUT22
,CD_OUT21
,CD_OUT20
,CD_OUT19
,CD_OUT18
,CD_OUT17
,CD_OUT16
,CD_OUT15
,CD_OUT14
,CD_OUT13
,CD_OUT12
,CD_OUT11
,CD_OUT10
,CD_OUT9
,CD_OUT8
,CD_OUT7
,CD_OUT6
,CD_OUT5
,CD_OUT4
,CD_OUT3
,CD_OUT2
,CD_OUT1
,CD_OUT0
,
MISS
,
ACC_OK
,
ERROR
,
M_MISS
;
// SCM,
// SCN_IN,
// TG_STROBE,
// PDM,
// SCN_OUT;
/********************* internal wiring definition ***********************/
wire [27:0] rd_out
; // TLB RAM output
wire [41:0] cd_out
; // TLB CAM output
wire miss
; // TLB miss output (based on match op)
wire acc_ok
; // protection & modified bits OK & ~miss
wire error
; // protection check failed & ~miss
wire m_miss
; // modified bit from CAM
wire scn_out
; // Scan output of internal registers
wire [27:0] rd_in
; // RAM data input
wire [41:0] cd_in
; // CAM data input
wire flush
; // flush control input
wire tlb_we
; // RAM and CAM write enable
wire asel
; // Address select (1 means use addr)
wire [3:0] addr
; // 4-bit address for writes and reads
wire co_in
; // Compare override for IO and PTP bits
wire cr
; // CAM direct address read control input
wire scm
; // Scan mode control input
wire scn_in
; // Scan input for internal registers
wire tg_strobe
; // Test generation strobe (for scan ops)
wire clk
; // Clock for internal registers
wire pdm
;
wire rst
; // Reset for internal registers
//-----------------------------------------------------------------------
assign RD_OUT27 = rd_out[27];
assign RD_OUT26 = rd_out[26];
assign RD_OUT25 = rd_out[25];
assign RD_OUT24 = rd_out[24];
assign RD_OUT23 = rd_out[23];
assign RD_OUT22 = rd_out[22];
assign RD_OUT21 = rd_out[21];
assign RD_OUT20 = rd_out[20];
assign RD_OUT19 = rd_out[19];
assign RD_OUT18 = rd_out[18];
assign RD_OUT17 = rd_out[17];
assign RD_OUT16 = rd_out[16];
assign RD_OUT15 = rd_out[15];
assign RD_OUT14 = rd_out[14];
assign RD_OUT13 = rd_out[13];
assign RD_OUT12 = rd_out[12];
assign RD_OUT11 = rd_out[11];
assign RD_OUT10 = rd_out[10];
assign RD_OUT9 = rd_out[9];
assign RD_OUT8 = rd_out[8];
assign RD_OUT7 = rd_out[7];
assign RD_OUT6 = rd_out[6];
assign RD_OUT5 = rd_out[5];
assign RD_OUT4 = rd_out[4];
assign RD_OUT3 = rd_out[3];
assign RD_OUT2 = rd_out[2];
assign RD_OUT1 = rd_out[1];
assign RD_OUT0 = rd_out[0];
assign CD_OUT41 = cd_out[41];
assign CD_OUT40 = cd_out[40];
assign CD_OUT39 = cd_out[39];
assign CD_OUT38 = cd_out[38];
assign CD_OUT37 = cd_out[37];
assign CD_OUT36 = cd_out[36];
assign CD_OUT35 = cd_out[35];
assign CD_OUT34 = cd_out[34];
assign CD_OUT33 = cd_out[33];
assign CD_OUT32 = cd_out[32];
assign CD_OUT31 = cd_out[31];
assign CD_OUT30 = cd_out[30];
assign CD_OUT29 = cd_out[29];
assign CD_OUT28 = cd_out[28];
assign CD_OUT27 = cd_out[27];
assign CD_OUT26 = cd_out[26];
assign CD_OUT25 = cd_out[25];
assign CD_OUT24 = cd_out[24];
assign CD_OUT23 = cd_out[23];
assign CD_OUT22 = cd_out[22];
assign CD_OUT21 = cd_out[21];
assign CD_OUT20 = cd_out[20];
assign CD_OUT19 = cd_out[19];
assign CD_OUT18 = cd_out[18];
assign CD_OUT17 = cd_out[17];
assign CD_OUT16 = cd_out[16];
assign CD_OUT15 = cd_out[15];
assign CD_OUT14 = cd_out[14];
assign CD_OUT13 = cd_out[13];
assign CD_OUT12 = cd_out[12];
assign CD_OUT11 = cd_out[11];
assign CD_OUT10 = cd_out[10];
assign CD_OUT9 = cd_out[9];
assign CD_OUT8 = cd_out[8];
assign CD_OUT7 = cd_out[7];
assign CD_OUT6 = cd_out[6];
assign CD_OUT5 = cd_out[5];
assign CD_OUT4 = cd_out[4];
assign CD_OUT3 = cd_out[3];
assign CD_OUT2 = cd_out[2];
assign CD_OUT1 = cd_out[1];
assign CD_OUT0 = cd_out[0];
assign MISS = miss;
assign ACC_OK = acc_ok;
assign ERROR = error;
assign M_MISS = m_miss;
assign rd_in[27] = RD_IN27;
assign rd_in[26] = RD_IN26;
assign rd_in[25] = RD_IN25;
assign rd_in[24] = RD_IN24;
assign rd_in[23] = RD_IN23;
assign rd_in[22] = RD_IN22;
assign rd_in[21] = RD_IN21;
assign rd_in[20] = RD_IN20;
assign rd_in[19] = RD_IN19;
assign rd_in[18] = RD_IN18;
assign rd_in[17] = RD_IN17;
assign rd_in[16] = RD_IN16;
assign rd_in[15] = RD_IN15;
assign rd_in[14] = RD_IN14;
assign rd_in[13] = RD_IN13;
assign rd_in[12] = RD_IN12;
assign rd_in[11] = RD_IN11;
assign rd_in[10] = RD_IN10;
assign rd_in[9] = RD_IN9;
assign rd_in[8] = RD_IN8;
assign rd_in[7] = RD_IN7;
assign rd_in[6] = RD_IN6;
assign rd_in[5] = RD_IN5;
assign rd_in[4] = RD_IN4;
assign rd_in[3] = RD_IN3;
assign rd_in[2] = RD_IN2;
assign rd_in[1] = RD_IN1;
assign rd_in[0] = RD_IN0;
assign cd_in[41] = CD_IN41;
assign cd_in[40] = CD_IN40;
assign cd_in[39] = CD_IN39;
assign cd_in[38] = CD_IN38;
assign cd_in[37] = CD_IN37;
assign cd_in[36] = CD_IN36;
assign cd_in[35] = CD_IN35;
assign cd_in[34] = CD_IN34;
assign cd_in[33] = CD_IN33;
assign cd_in[32] = CD_IN32;
assign cd_in[31] = CD_IN31;
assign cd_in[30] = CD_IN30;
assign cd_in[29] = CD_IN29;
assign cd_in[28] = CD_IN28;
assign cd_in[27] = CD_IN27;
assign cd_in[26] = CD_IN26;
assign cd_in[25] = CD_IN25;
assign cd_in[24] = CD_IN24;
assign cd_in[23] = CD_IN23;
assign cd_in[22] = CD_IN22;
assign cd_in[21] = CD_IN21;
assign cd_in[20] = CD_IN20;
assign cd_in[19] = CD_IN19;
assign cd_in[18] = CD_IN18;
assign cd_in[17] = CD_IN17;
assign cd_in[16] = CD_IN16;
assign cd_in[15] = CD_IN15;
assign cd_in[14] = CD_IN14;
assign cd_in[13] = CD_IN13;
assign cd_in[12] = CD_IN12;
assign cd_in[11] = CD_IN11;
assign cd_in[10] = CD_IN10;
assign cd_in[9] = CD_IN9;
assign cd_in[8] = CD_IN8;
assign cd_in[7] = CD_IN7;
assign cd_in[6] = CD_IN6;
assign cd_in[5] = CD_IN5;
assign cd_in[4] = CD_IN4;
assign cd_in[3] = CD_IN3;
assign cd_in[2] = CD_IN2;
assign cd_in[1] = CD_IN1;
assign cd_in[0] = CD_IN0;
assign flush = FLUSH;
assign tlb_we = TLB_WE;
assign asel = ASEL;
assign addr[3] = ADDR3;
assign addr[2] = ADDR2;
assign addr[1] = ADDR1;
assign addr[0] = ADDR0;
assign co_in = CO_IN;
assign cr = CR;
assign clk = CLK;
assign rst = RST;
assign scm = 1'b0;
assign scn_in = 1'b0;
assign tg_strobe = 1'b1;
// assign scm = SCM;
// assign scn_in = SCN_IN;
// assign tg_strobe = TG_STROBE;
// assign pdm = PDM;
// assign SCN_OUT = scn_out;
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
wire [15:0] ram_address
;
wire [27:0] ram_data_in
;
wire tg_stb_clk
;
// synopsys translate_off
always @(posedge clk) begin
tlbwe_display;
end
task tlbwe_display;
if(tlb_we & ~scm) begin
$display("\nIOTLB write to entry %d TAG = %h RAM = %h\n",addr,cd_in,rd_in);
end
endtask
// synopsys translate_on
iocam IOTLB_cam(.ram_address (ram_address), // TLB RAM address output
.ram_data_in (ram_data_in), // TLB RAM data input ( registered version of rd_in )
.ram_write (ram_write
), // WRITE STROBE from CAM to RAM
.cd_out (cd_out), // TLB CAM output
.miss (miss), // TLB miss output (based on match op)
.flush_op (flush_op
), // TLB flush
.acc_ok (acc_ok), // protection & modified bits OK & ~miss
.error (error), // protection check failed & ~miss
.m_miss (m_miss), // modified bit from CAM
.scn_out (scn_out), // Scan output of internal registers
.rd_in (rd_in), // RAM data input
.cd_in (cd_in), // CAM data input
.flush (flush), // flush control input
.tlb_we (tlb_we), // RAM and CAM write enable
.asel (asel), // Address select (1 means use addr)
.addr (addr), // 4-bit address for writes and reads
.co_in (co_in), // Compare override for IO and PTP bits
.cr (cr), // CAM direct address read control input
.scm (scm), // Scan mode control input
.scn_in (scn_in), // Scan input for internal registers
.tg_strobe (tg_strobe), // Test generation strobe (for scan ops)
.tg_stb_clk (tg_stb_clk), // ouput scan trigger clock to sram
.clk (clk), // Clock for internal registers
.rst (rst)); // Reset for internal registers
iosram IOTLB_ram (
.decoded_addr (ram_address),
.do (rd_out),
.di (ram_data_in),
.we (ram_write),
.flush_op (flush_op),
.miss (miss),
.clk (tg_stb_clk));
endmodule
module iocam
(ram_address, // TLB RAM address output
ram_data_in, // TLB RAM data input ( registered version of rd_in )
ram_write, // WRITE STROBE from CAM to RAM
cd_out, // TLB CAM output
miss, // TLB miss output (based on match op)
flush_op, //
acc_ok, // protection & modified bits OK & ~miss
error, // protection check failed & ~miss
m_miss, // modified bit from CAM
scn_out, // Scan output of internal registers
rd_in, // RAM data input
cd_in, // CAM data input
flush, // flush control input
tlb_we, // RAM and CAM write enable
asel, // Address select (1 means use addr)
addr, // 6-bit address for writes and reads
co_in, // Compare override for IO and PTP bits
cr, // CAM direct address read control input
scm, // Scan mode control input
scn_in, // Scan input for internal registers
tg_strobe, // Test generation strobe (for scan ops)
tg_stb_clk, // output tg scan clock to sram as clock
clk, // Clock for internal registers
rst); // Reset for internal registers
output [15:0] ram_address
;
output [27:0] ram_data_in
;
output ram_write
;
output [41:0] cd_out
; // tlb tag output data
output miss
;
output flush_op
;
output acc_ok
;
output error
;
output m_miss
;
output scn_out
;
input [27:0] rd_in
; // tlb data input
input [41:0] cd_in
; // tlb tag in compare data
input flush
; // flush input for TLB, clears matching
// CAM entry if any
input tlb_we
; // tlb tag write enable from SM
input asel
; // ASI decoded to tlb, selects line
// for direct read or write
// based on addr
input [3:0] addr
; // IOTLBN Address (4-bits), selects
input co_in
; // flush all comp input
input cr
; // CAM read
input scm
,scn_in
,tg_strobe
;
output tg_stb_clk
;
input clk
;
input rst
; // active high reset
/****************************************************************************/
/*** Variable declartions and initialization ***/
/****************************************************************************/
wire [15:0] ram_address;
wire [27:0] ram_data_in;
wire ram_write;
// Input register wire declaraitions
wire tlb_we_reg
, flush_reg
, asel_reg
, co_in_reg
;
wire [3:0] addr_reg
;
wire [`IOTLBTAG_WIDTH-1:0] c_data_in_reg
;
wire [`IOTLBDATA_WIDTH-1:0] r_data_in_reg
;
wire [15:00] hit
;
wire [15:00] err
;
wire [15:00] m_ok
;
// wire definition of cam line output
wire [41:0] tag15_out
;
wire [41:0] tag14_out
;
wire [41:0] tag13_out
;
wire [41:0] tag12_out
;
wire [41:0] tag11_out
;
wire [41:0] tag10_out
;
wire [41:0] tag09_out
;
wire [41:0] tag08_out
;
wire [41:0] tag07_out
;
wire [41:0] tag06_out
;
wire [41:0] tag05_out
;
wire [41:0] tag04_out
;
wire [41:0] tag03_out
;
wire [41:0] tag02_out
;
wire [41:0] tag01_out
;
wire [41:0] tag00_out
;
// Intermediate values used in TLB internals
wire [41:0] tlb_tag
;
wire [15:0] tag_hld
;
/*** Internal Registers ****************************************************/
// Register version of signal tlb_we,flush,addr,asel
// Scan Chain needs to be defined by Megacell design
// TEMPORARY scan chain is connected as follows:
// Scan order ->addr[0:5]->cd_in[23:18]->cd_in[24]
// ->cd_in[30:25]->cd_in[31]->cd_in[39:32]
// ->cd_in[40]->cd_in[17:10]->cd_in[3]
// ->cd_in[2:1]->co_in->asel
// ->flush->tlb_we->rst->cr
// ->cd_in[41]->cd_in[9,8,6,5,7,4]
// ->cd_in[0]->rd_in[0:27]->scn_out
Mflipflop_s rst_ff(rst_reg
,rst,scm,tlb_we_reg,clk);
Mflipflop_s tlb_we_ff(tlb_we_reg,tlb_we,scm,flush_reg,clk);
Mflipflop_s co_in_ff(co_in_reg,co_in,scm,c_data_in_reg[1],clk);
Mflipflop_s c_rd_ff(c_rd_reg
,cr,scm,rst_reg,clk);
Mflipflop_s flush_ff(flush_reg,flush,scm,asel_reg,clk);
Mflipflop_s asel_ff(asel_reg,asel,scm,co_in_reg,clk);
IOMflipflop_s_4_r addr_ff(addr_reg,addr,scm,scn_in,clk);
// group scan order for cd_in
IOMflipflop_s_6_old c_data_in_1_ff(c_data_in_reg[23:18],cd_in[23:18],scm,addr_reg[3],clk);
Mflipflop_s c_data_in_2_ff(c_data_in_reg[24],cd_in[24],scm,c_data_in_reg[18],clk);
IOMflipflop_s_6_old c_data_in_3_ff(c_data_in_reg[30:25],cd_in[30:25],scm,c_data_in_reg[24],clk);
Mflipflop_s c_data_in_4_ff(c_data_in_reg[31],cd_in[31],scm,c_data_in_reg[25],clk);
IOMflipflop_s_8_old c_data_in_5_ff(c_data_in_reg[39:32],cd_in[39:32],scm,c_data_in_reg[31],clk);
Mflipflop_s c_data_in_6_ff(c_data_in_reg[40],cd_in[40],scm,c_data_in_reg[32],clk);
IOMflipflop_s_8_old c_data_in_7_ff(c_data_in_reg[17:10],cd_in[17:10],scm,c_data_in_reg[40],clk);
Mflipflop_s c_data_in_8_ff(c_data_in_reg[3],cd_in[3],scm,c_data_in_reg[10],clk);
IOMflipflop_s_2_old c_data_in_9_ff(c_data_in_reg[2:1],cd_in[2:1],scm,c_data_in_reg[3],clk);
// second group of scan connection
Mflipflop_s c_data_in_10_ff(c_data_in_reg[41],cd_in[41],scm,c_rd_reg,clk);
Mflipflop_s c_data_in_11_ff(c_data_in_reg[9],cd_in[9],scm,c_data_in_reg[41],clk);
Mflipflop_s c_data_in_12_ff(c_data_in_reg[8],cd_in[8],scm,c_data_in_reg[9],clk);
Mflipflop_s c_data_in_13_ff(c_data_in_reg[6],cd_in[6],scm,c_data_in_reg[8],clk);
Mflipflop_s c_data_in_14_ff(c_data_in_reg[5],cd_in[5],scm,c_data_in_reg[6],clk);
Mflipflop_s c_data_in_15_ff(c_data_in_reg[7],cd_in[7],scm,c_data_in_reg[5],clk);
Mflipflop_s c_data_in_16_ff(c_data_in_reg[4],cd_in[4],scm,c_data_in_reg[7],clk);
Mflipflop_s c_data_in_17_ff(c_data_in_reg[0],cd_in[0],scm,c_data_in_reg[4],clk);
// end of second group signal
IOMflipflop_s_28_r r_data_in_ff(r_data_in_reg,rd_in,scm,c_data_in_reg[0],clk);
assign ram_data_in = r_data_in_reg; // output a register verison rd_in to ram
// wire the scan out pin ....
wire scn_out = r_data_in_reg[27];
// clock for tg_strobe or regular clock
wire tg_stb_clk = clk & tg_strobe;
/****************************************************************************/
/*** TLB function decode of control registers ***/
/****************************************************************************/
// register version of tg_cam_read_c1
// In scan , we need to genetare internal cam_read_op at second cam_read cycle
// the tg_cam_read_op is to generate second cam read
wire cam_read_c1
;
wire scm_reg
;
MflipflopR_1 scam_mode_reg(scm_reg,scm,tg_stb_clk,1'b0,1'b0);
// since in this model we use posedge to do operation
// we need to avoid the destruct operation do twice like tlb_write or flush_op
wire scm_reg_2
;
MflipflopR_1 scam_mode_reg_2(scm_reg_2,scm_reg,tg_stb_clk,1'b0,1'b0);
wire tg_cam_read_c1_op
= cam_read_c1 & scm_reg;
// chop second write or flush operation
wire chop_strobe
= ~(scm_reg & scm_reg_2) & scm_reg_2;
wire tg_cam_read_op
;
MflipflopR_1 tg_cam_read_reg(tg_cam_read_op,tg_cam_read_c1_op,tg_stb_clk,1'b0,1'b0);
// since CAM read is a 2 cycle operation, we need to register 1st decode
// decode two cycle pattern for direct cam read
assign cam_read_c1 = (asel_reg & ~tlb_we_reg & c_rd_reg & ~flush_reg ) & ~rst_reg & ~scm & ~tg_cam_read_op;
// register cam_read_c1 operation
wire cam_read_c1_reg
;
MflipflopR_1 cam_read_c1_reg_1(cam_read_c1_reg,cam_read_c1,tg_stb_clk,1'b0,1'b0);
wire cam_read_op
= ((asel_reg & ~tlb_we_reg & ~c_rd_reg &
~flush_reg & cam_read_c1_reg) | tg_cam_read_op ) & ~rst_reg & ~scm;
/************** start operation decode ***********************/
wire ram_read_op
= ((asel_reg & ~tlb_we_reg & ~c_rd_reg &
~flush_reg ) | rst_reg) & ~scm;
wire tlb_write_op
= (asel_reg & tlb_we_reg & ~c_rd_reg &
~flush_reg ) & ~rst_reg & ~scm & ~chop_strobe;
wire match_op
= (~asel_reg & ~tlb_we_reg & ~c_rd_reg &
~flush_reg ) & ~rst_reg & ~scm;
wire flush_op = (~asel_reg & ~tlb_we_reg & ~c_rd_reg &
flush_reg ) & ~rst_reg & ~scm & ~chop_strobe;
// An illegal operation is when no legal operation was decoded.
// This is a strict check to the TLB spec.
wire illegal_op
= ~cam_read_op
& ~cam_read_c1
& ~ram_read_op
& ~tlb_write_op
& ~match_op
& ~flush_op & ~scm & ~chop_strobe;
// synopsys translate_off
`ifdef DEBUG
// for cam_read cycle 1
always @(posedge cam_read_c1) begin #1
force cd_out = `IOTLBTAG_WIDTH'bx;
force miss = 1'bx;
force error = 1'bx;
force acc_ok = 1'bx;
force m_miss = 1'bx;
end
always @(negedge cam_read_c1) begin
release cd_out;
release miss;
release error;
release acc_ok;
release m_miss;
end
// for cam_read cycle 2
always @(posedge cam_read_op) begin #1
force `SSPARC_CORE.ssparc_pcic.afxm.io_tlb.rd_out = `IOTLBDATA_WIDTH'bx;
force miss = 1'bx;
force error = 1'bx;
force acc_ok = 1'bx;
force m_miss = 1'bx;
end
always @(negedge cam_read_op) begin
release `SSPARC_CORE.ssparc_pcic.afxm.io_tlb.rd_out ;
release miss ;
release error ;
release acc_ok ;
release m_miss ;
end
// for direct ram read
always @(posedge ram_read_op) begin #1
force cd_out = `IOTLBTAG_WIDTH'bx;
end
always @(negedge ram_read_op) begin
release cd_out ;
end
// for campare read
// no force for campare read , all output are valid for this cycle
// for direct cam/ram write
always @(posedge tlb_write_op) begin #1
force miss = 1'bx;
force error = 1'bx;
force acc_ok = 1'bx;
force m_miss = 1'bx;
end
always @(negedge tlb_write_op) begin
release miss ;
release error ;
release acc_ok ;
release m_miss ;
end
// for flush entry
always @(posedge flush_op) begin #1
force cd_out = `IOTLBTAG_WIDTH'bx;
force `SSPARC_CORE.ssparc_pcic.afxm.io_tlb.rd_out = `IOTLBDATA_WIDTH'bx;
force miss = 1'bx;
force error = 1'bx;
force acc_ok = 1'bx;
force m_miss = 1'bx;
end
always @(negedge flush_op) begin
release cd_out ;
release `SSPARC_CORE.ssparc_pcic.afxm.io_tlb.rd_out ;
release miss ;
release error ;
release acc_ok ;
release m_miss ;
end
// end of special force procedure
`endif
// 1. Check if illegal CAM read op
// 2. Check if illegal operation
integer i
,hit_no
;
always @(negedge tg_stb_clk) begin
if ( cam_read_c1_reg && ~cam_read_op && ~scm) begin
$display("\n******* ERROR : the control of direct IOCAM read is not correct in two cycles\n");
Mclocks.error_count = Mclocks.error_count + 1 ;
end
if ((illegal_op === 1'b1 | illegal_op === 1'bx) & ~rst_reg & ~scm) begin
$display("\n*** ERROR: undefined IOTLB operation (illegal_op=%b) in cycle (%0d)\n",
illegal_op,Mclocks.cycle_count,
"***\tasel_reg=%b, tlb_we_reg=%b, flush_reg=%b, c_rd_reg=%b, rst=%b\n",
asel_reg, tlb_we_reg, flush_reg, c_rd_reg, rst);
Mclocks.error_count = Mclocks.error_count + 1 ;
end
// if (tlb_write_op & ~rst_reg) begin
// if (^{c_data_in_reg[`VALIDBIT],
// c_data_in_reg[`PTP_BIT],
// c_data_in_reg[`IO_PTE],
// c_data_in_reg[`SUPERVISOR],
// c_data_in_reg[`IMASK0],
// c_data_in_reg[`IMASK1],
// c_data_in_reg[`IMASK2]} === 1'bx) begin
// $display("\n*** ERROR: IOTLB control bits in c_data_in are unknown\n",
// "***\tvalid=%b ptp=%b io_pte=%b sup=%b imask0=%b imask1=%b imask2=%b\n",
// c_data_in_reg[`VALIDBIT], c_data_in_reg[`PTP_BIT],
// c_data_in_reg[`IO_PTE], c_data_in_reg[`SUPERVISOR],
// c_data_in_reg[`IMASK0], c_data_in_reg[`IMASK1],
// c_data_in_reg[`IMASK2]);
// Mclocks.error_count = Mclocks.error_count + 1 ;
// end
// end
if ((match_op === 1'b1 ) & ~rst_reg & ~scm) begin
hit_no = 0;
for ( i=0 ; i <= 63; i=i+1) begin
if (hit[i] === 1'b1)
hit_no = hit_no+1;
end
if (hit_no > 1) begin
$display("\n*** ERROR (SMOKE DETECT IOTLB!!): more than 1",
" (%0d) TLB CAM line matched in cycle %0d = %h ",hit_no,Mclocks.cycle_count,Mclocks.cycle_count);
$display(" 3210987654321098765432109876543210987654321098765432109876543210 ");
$display("matching entries: %b",hit);
Mclocks.error_count = Mclocks.error_count + 1 ;
end
end
end
`ifdef MMU_GATE_LEVEL
`else
// monitor tlb writes for smoke detect.
//
always @(posedge tlb_write_op & c_data_in_reg[41]) begin #16
hit_no = 0;
for ( i=0 ; i <= 15; i=i+1) begin
if (hit[i] === 1'b1)
hit_no = hit_no+1;
end
if (hit_no > 1) begin
$display("\n*** ERROR (SMOKE DETECT IO): more than 1",
" (%0d) TLB CAM line matched in cycle %0d = %h ",hit_no,Mclocks.cycle_count,Mclocks.cycle_count);
$display(" 3210987654321098765432109876543210987654321098765432109876543210 ");
$display("matching entries: %b",hit);
Mclocks.error_count = Mclocks.error_count + 1 ;
end
end
// monitor for flush context,region,segment and all operation
// register flush_done first
reg r_flush_done
;
reg [`IOTLBTAG_WIDTH-1:0] tlb_t_tag
;
always @(posedge tg_stb_clk) begin
r_flush_done = `SSPARC_CORE.ssparc_mmu.MMU_cntl.tw_sm.flush_done;
end
// connect the external wire here
reg flush_t_ioall
;
always @(posedge clk) begin
flush_t_ioall = `SSPARC_CORE.ssparc_mmu.MMU_cntl.tw_sm.flush_ioall;
end
wire flush_t_seg
= `SSPARC_CORE.ssparc_mmu.MMU_cntl.tw_sm.flush_tlb_seg;
wire flush_t_reg
= `SSPARC_CORE.ssparc_mmu.MMU_cntl.tw_sm.flush_tlb_reg;
wire flush_t_ctx
= `SSPARC_CORE.ssparc_mmu.MMU_cntl.tw_sm.flush_tlb_ctx;
wire flush_t_all
= `SSPARC_CORE.ssparc_mmu.MMU_cntl.tw_sm.flush_tlb_all;
wire vptp_mode
= `SSPARC_CORE.ssparc_mmu.MMU_cntl.tw_sm.virt_ptp2;
wire flush_t_iopte
= `SSPARC_CORE.ssparc_mmu.MMU_cntl.tw_sm.flush_iopte;
always @(negedge tg_stb_clk) begin
if ( r_flush_done ) begin
if ( flush_t_seg | flush_t_reg | flush_t_ctx ) begin
for(i=0; i<`IOTLBENTRIES ; i=i+1) begin : ptp_check
case(i)
0: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag00_out;
1: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag01_out;
2: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag02_out;
3: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag03_out;
4: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag04_out;
5: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag05_out;
6: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag06_out;
7: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag07_out;
8: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag08_out;
9: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag09_out;
10: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag10_out;
11: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag11_out;
12: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag12_out;
13: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag13_out;
14: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag14_out;
15: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag15_out;
endcase
if (tlb_t_tag[`PTP_BIT] && tlb_t_tag[`VALIDBIT] && tlb_t_tag[`IO_PTE]) begin
$display("**iovptp entry left at %0d : after cntx, reg, or seg flush ",i);
$display("%h",tlb_t_tag);
Mclocks.error_count = Mclocks.error_count + 1 ;
disable ptp_check;
end
else if (tlb_t_tag[`PTP_BIT] && tlb_t_tag[`VALIDBIT]) begin
$display("**ioptp entry left at %0d : after cntx, reg, or seg flush ",i);
$display("%h",tlb_t_tag);
Mclocks.error_count = Mclocks.error_count + 1 ;
disable ptp_check;
end
end
end
if ( flush_t_all ) begin
for(i=0; i<`TLBENTRIES ; i=i+1) begin : valid_check
case(i)
0: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag00_out;
1: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag01_out;
2: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag02_out;
3: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag03_out;
4: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag04_out;
5: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag05_out;
6: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag06_out;
7: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag07_out;
8: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag08_out;
9: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag09_out;
10: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag10_out;
11: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag11_out;
12: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag12_out;
13: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag13_out;
14: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag14_out;
15: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag15_out;
endcase
if ( tlb_t_tag[`VALIDBIT] ) begin
$display("*** first iovalid left at %0d : after flush all ",i);
Mclocks.error_count = Mclocks.error_count + 1 ;
disable valid_check;
end
end
end
end
end
wire flush_ioall_cycle
= flush_op & flush_t_ioall;
reg flush_ioall_cycle_reg
;
always @(posedge tg_stb_clk) begin
flush_ioall_cycle_reg = flush_ioall_cycle;
end
always @(negedge tg_stb_clk) begin
if (flush_ioall_cycle_reg) begin
for(i=0; i<`IOTLBENTRIES ; i=i+1) begin : iopte_check
case(i)
0: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag00_out;
1: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag01_out;
2: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag02_out;
3: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag03_out;
4: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag04_out;
5: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag05_out;
6: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag06_out;
7: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag07_out;
8: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag08_out;
9: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag09_out;
10: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag10_out;
11: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag11_out;
12: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag12_out;
13: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag13_out;
14: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag14_out;
15: tlb_t_tag = `MMU.MMU_tlb.TLB_cam.tag15_out;
endcase
if (tlb_t_tag[`VALIDBIT] && tlb_t_tag[`IO_PTE]) begin
$display("*** ioiopte entry left at %0d : after iopte flush all",i);
$display("%h",tlb_t_tag);
Mclocks.error_count = Mclocks.error_count + 1 ;
disable iopte_check;
end
end
end
end
`endif
// synopsys translate_on
/**************** ram write addres decode and WE cntrol **************/
// if direct read or write , we put ram address as decode address .
// if not , we put is to default address which is 00
assign ram_address = ( asel_reg ) ? decode(addr_reg) :
((match_op | flush_op) & ~rst_reg ) ? hit : 16'h0000;
/*****************************************************************************/
// Direct write operation
// tag write is asserted directly from tag_hld to cam line input
// switch ram write control off if this is not a write operation
// tag_hld assert when tlb_write-op is true , in order to finish write
// in clk = 0 cycle. I use the ~clk to be the cam cell clk
assign ram_write = tlb_write_op;
/****************************************************************************/
// Direct addressed cam read.
// If clk is low and cam_read_op is decode .
// emulation cam pre-charge high
//
wire [41:0] cd_out = (cam_read_op) ? tlb_tag :
(~cam_read_c1) ? c_data_in_reg : 42'h3ffffffffff;
/****************************************************************************/
// Direct addressed ram read.and compare read & flush status output
//
// if none of ram_read_op or match_op , we set it to o.k. in 1 for synopsys
// DIRECT ram read equation
// if (ram_read_op) begin
// acc_ok_reg = 1'b1;
// error_reg = 1'b0;
// miss_reg = 1'b0;
// m_miss_reg = 1'b0;
// end
/******************************************************************************/
// CAM match detect. Could be doing either a content-addressed read,
// or a flush. In either case, first see if we get a tag match.
// if ((match_op | flush_op) & ~rst_reg) begin
// miss_reg = ~(|(hit[63:0])) ;
// error_reg = |(err[63:0]) ;
// m_ok_reg = |(m_ok[63:0]) ;
// m_miss_reg = miss_reg | ~m_ok_reg;
// acc_ok_reg = m_ok_reg & ~error_reg & ~miss_reg ;
// end
wire miss = ((match_op | flush_op) & ~rst_reg) & ~(|(hit[15:0]));
wire error = ((match_op | flush_op) & ~rst_reg) & (|(err[15:0]));
wire m_ok_reg
= ~((match_op | flush_op) & ~rst_reg) | (|(m_ok[15:0]));
wire acc_ok = ~((match_op | flush_op) & ~rst_reg) | (m_ok_reg & ~error & ~miss);
wire m_miss = ((match_op | flush_op) & ~rst_reg) & (miss | ~m_ok_reg);
///////////////////////////////////////////////////////////////////////////////
// decoder ( 4-16 decoder )
function [15:0] decode;
input [3:0] input_addr;
reg [15:0] count;
integer k;
begin
count = 0;
for (k=0; k <= 15; k=k+1)
if (k == input_addr)
count[k] = 1'b1;
decode = count;
end
endfunction
/********************** start cam block **************************/
/****************************************************************************/
/*** Instantiate CAM lines ***/
wire flush_real
= flush_reg & ~scm;
wire co_in_real
= co_in_reg & ~scm;
IOCAM_LINE tag00(hit[00],err[00],m_ok[00],tag00_out,
c_data_in_reg,tg_stb_clk,tag_hld[00],flush_real,co_in_real) ;
IOCAM_LINE tag01(hit[01],err[01],m_ok[01],tag01_out,
c_data_in_reg,tg_stb_clk,tag_hld[01],flush_real,co_in_real) ;
IOCAM_LINE tag02(hit[02],err[02],m_ok[02],tag02_out,
c_data_in_reg,tg_stb_clk,tag_hld[02],flush_real,co_in_real) ;
IOCAM_LINE tag03(hit[03],err[03],m_ok[03],tag03_out,
c_data_in_reg,tg_stb_clk,tag_hld[03],flush_real,co_in_real) ;
IOCAM_LINE tag04(hit[04],err[04],m_ok[04],tag04_out,
c_data_in_reg,tg_stb_clk,tag_hld[04],flush_real,co_in_real) ;
IOCAM_LINE tag05(hit[05],err[05],m_ok[05],tag05_out,
c_data_in_reg,tg_stb_clk,tag_hld[05],flush_real,co_in_real) ;
IOCAM_LINE tag06(hit[06],err[06],m_ok[06],tag06_out,
c_data_in_reg,tg_stb_clk,tag_hld[06],flush_real,co_in_real) ;
IOCAM_LINE tag07(hit[07],err[07],m_ok[07],tag07_out,
c_data_in_reg,tg_stb_clk,tag_hld[07],flush_real,co_in_real) ;
IOCAM_LINE tag08(hit[08],err[08],m_ok[08],tag08_out,
c_data_in_reg,tg_stb_clk,tag_hld[08],flush_real,co_in_real) ;
This page: |
Created: | Thu Aug 19 11:56:43 1999 |
| From: |
../../../sparc_v8/ssparc/pcic/afxmaster/rtl/io_e_tlb.v
|