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

Subversion Repositories sparc64soc

[/] [sparc64soc/] [trunk/] [os2wb/] [l1ddir.v] - Rev 8

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

module l1ddir(
   input clk,
   input reset,
 
   input [ 6:0] index,
   input [ 1:0] way,
   input [28:0] tag,
	input        strobe,
   input        query,
   input        allocate,   //tag->{way,index}
   input        deallocate, //if({way,index}==tag) {way,index}<-FFFFFF
   input        dualdealloc,
   input        invalidate, //all ways
 
   output reg [2:0] hit0,
   output reg [2:0] hit1,
 
   output reg       ready // directory init completed
);
 
`define INVAL_TAG 29'h10000000
 
reg [28:0] tag_d;
reg [ 6:0] addr0;
reg [ 5:0] addr1;
reg [ 3:0] we0;
reg [ 3:0] we1;
reg [ 3:0] re;
reg [28:0] di;
reg        dualdealloc_d;
wire [28:0] do0_0;
wire [28:0] do1_0;
wire [28:0] do2_0;
wire [28:0] do3_0;
wire [28:0] do0_1;
wire [28:0] do1_1;
wire [28:0] do2_1;
wire [28:0] do3_1;
reg query_d;
reg deallocate_d;
reg query_d1;
reg deallocate_d1;
 
always @(posedge clk)
   if(strobe)
      if(query || deallocate)
         begin
            tag_d<=tag;
            dualdealloc_d<=dualdealloc;
         end
 
always @(posedge clk)
   begin
      query_d<=query && strobe;
      deallocate_d<=deallocate && strobe;
      query_d1<=query_d;
      deallocate_d1<=deallocate_d;
   end
 
cachedir dcache0 (
   .clock(clk),
   .enable(we0[0] || we1[0] || re[0]),
   .wren_a(we0[0]),
   .address_a({1'b0,addr0}),
   .data_a(di),
   .q_a(do0_0),
 
   .wren_b(we1[0]),
   .address_b({1'b0,addr1,1'b1}),
   .data_b(`INVAL_TAG),
   .q_b(do0_1) 
);
 
cachedir dcache1 (
   .clock(clk),
   .enable(we0[1] || we1[1] || re[1]),
   .wren_a(we0[1]),
   .address_a({1'b0,addr0}),
   .data_a(di),
   .q_a(do1_0),
 
   .wren_b(we1[1]),
   .address_b({1'b0,addr1,1'b1}),
   .data_b(`INVAL_TAG),
   .q_b(do1_1) 
);
 
cachedir dcache2 (
   .clock(clk),
   .enable(we0[2] || we1[2] || re[2]),
   .wren_a(we0[2]),
   .address_a({1'b0,addr0}),
   .data_a(di),
   .q_a(do2_0),
 
   .wren_b(we1[2]),
   .address_b({1'b0,addr1,1'b1}),
   .data_b(`INVAL_TAG),
   .q_b(do2_1) 
);
 
cachedir dcache3 (
   .clock(clk),
   .enable(we0[3] || we1[3] || re[3]),
   .wren_a(we0[3]),
   .address_a({1'b0,addr0}),
   .data_a(di),
   .q_a(do3_0),
 
   .wren_b(we1[3]),
   .address_b({1'b0,addr1,1'b1}),
   .data_b(`INVAL_TAG),
   .q_b(do3_1) 
);
 
wire [3:0] hitvect0={(do3_0==tag_d),(do2_0==tag_d),(do1_0==tag_d),(do0_0==tag_d)};
wire [3:0] hitvect1={(do3_1==tag_d),(do2_1==tag_d),(do1_1==tag_d),(do0_1==tag_d)};
 
`define L1DDIR_RESET   3'b000
`define L1DDIR_INIT    3'b001
`define L1DDIR_IDLE    3'b010
`define L1DDIR_READ    3'b011
`define L1DDIR_DEALLOC 3'b100
 
reg [2:0] state;
 
always @(posedge clk or posedge reset)
   if(reset)
      begin
         state<=`L1DDIR_RESET;
         ready<=0;
      end
   else
      case(state)
         `L1DDIR_RESET:
            begin
               addr0<=7'b0;
               addr1<=6'b0;
               di<=`INVAL_TAG;
               we0<=4'b1111;
               we1<=4'b1111;
               state<=`L1DDIR_INIT;
            end
         `L1DDIR_INIT:
            begin
               addr0<=addr0+2;
               addr1<=addr1+1;
               if(addr0==7'b1111110)
                  begin
                     we0<=4'b0;
                     we1<=4'b0;
                     ready<=1;
                     state<=`L1DDIR_IDLE;
                  end
            end
         `L1DDIR_IDLE:
			   if(strobe)
            if(invalidate)
               begin
                  we0<=4'b1111;
                  we1<=0;
                  addr0<=index;
                  di<=`INVAL_TAG;
               end
            else
				if(allocate)
				   begin
					  case(way)
						 2'b00:we0<=4'b0001;
						 2'b01:we0<=4'b0010;
						 2'b10:we0<=4'b0100;
						 2'b11:we0<=4'b1000;
					  endcase
					  we1<=0;
					  addr0<=index;
					  di<=tag;
				   end
				else
				   if(deallocate)
					  begin
						 re<=4'b1111;
						 we0<=0;
						 we1<=0;
						 if(dualdealloc)
							begin
							   addr0<={index[6:1],1'b0};
							   addr1<=index[6:1];
							end
						 else
							addr0<=index;
						 state<=`L1DDIR_READ;
					  end
				   else
                     if(query)
                        begin
                           addr0<=index;
                           re<=4'b1111;
                           we0<=0;
                           we1<=0;
                        end
                     else
                        begin
                           we0<=0;
                           we1<=0;
                           re<=0;
                        end
			`L1DDIR_READ:
			   state<=`L1DDIR_DEALLOC;
         `L1DDIR_DEALLOC:
            begin
               re<=0;
               di<=`INVAL_TAG;
               we0<=hitvect0;
               if(dualdealloc_d)
                  we1<=hitvect1;
               else
                  we1<=0;
               state<=`L1DDIR_IDLE;
            end
      endcase
 
always @(posedge clk)
   if(query_d1 || deallocate_d1)
      begin
         case(hitvect0)
            4'b0001:hit0<=3'b100;
            4'b0010:hit0<=3'b101;
            4'b0100:hit0<=3'b110;
            4'b1000:hit0<=3'b111;
            default:hit0<=3'b000; // Hits will be ORed then
         endcase
         if(dualdealloc_d && deallocate_d1)
			 case(hitvect1)
				4'b0001:hit1<=3'b100;
				4'b0010:hit1<=3'b101;
				4'b0100:hit1<=3'b110;
				4'b1000:hit1<=3'b111;
				default:hit1<=3'b000;
			 endcase
	     else
	        hit1<=3'b000;
      end
   else
      if(strobe)
         begin
            hit0<=3'b000;
            hit1<=3'b000;
         end
 
endmodule
 

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

powered by: WebSVN 2.1.0

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