source: XOpenSparcT1/trunk/T1-common/srams/bw_r_l2d_32k.v @ 6

Revision 6, 14.2 KB checked in by pntsvt00, 14 years ago (diff)

versione iniziale opensparc

Line 
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T1 Processor File: bw_r_l2d_32k.v
4// Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21//FPGA_SYN enables all FPGA related modifications
22`ifdef FPGA_SYN 
23`define FPGA_SYN_RED
24`endif
25
26module bw_r_l2d_32k (/*AUTOARG*/
27   // Outputs
28   decc_out, so, l2d_fuse_data_out, 
29   // Inputs
30   decc_in_l, decc_read_in, word_en_l, way_sel_l, set_l, 
31   col_offset_l, wr_en_l, rclk, arst_l, mem_write_disable, 
32   sehold, se, si, fuse_l2d_wren, fuse_l2d_rden, 
33   fuse_l2d_rid, fuse_clk1, fuse_clk2, 
34   fuse_l2d_data_in, fuse_read_data_in
35   );
36
37   input [155:0]        decc_in_l;
38   input [155:0]        decc_read_in;
39   input [3:0]          word_en_l;
40   input [1:0]          way_sel_l;
41   input [9:0]          set_l;
42   input                col_offset_l;
43   input                wr_en_l;
44   input                rclk;
45   input                arst_l;
46   
47   // Test signals
48   input                mem_write_disable;
49   input                sehold;
50   input                se;
51   input                si;
52   
53
54   // Efuse inputs
55   input                fuse_l2d_wren;
56   input                fuse_l2d_rden;
57   input [2:0]          fuse_l2d_rid;
58   input                fuse_clk1;
59   input                fuse_clk2;
60   input                fuse_l2d_data_in;
61   input                fuse_read_data_in;
62
63
64   output [155:0]       decc_out ;
65   output               so;
66
67   // Efuse outputs
68   output               l2d_fuse_data_out;
69     
70   reg [155:0]          tmp_decc_out;
71   reg [155:0]          decc_out_tmp;
72   reg [155:0]          reg_decc_in;   
73
74`ifdef DEFINE_0IN
75`else
76   reg [155:0]          way0_decc[1023:0] ;
77   reg [155:0]          way1_decc[1023:0] ;
78`endif
79   
80   wire                 acc_en_d1;
81   reg [1:0]            way_sel_d1;
82   reg [9:0]            set_d1;
83   reg [3:0]            word_en_d1;
84   reg                  wr_en_d1;
85   reg [155:0]          decc_in_d1;
86   reg [155:0]          decc_out_d1;
87   reg                  col_offset_d1;
88   
89   wire [1:0]           way_sel_sehold;
90   wire [9:0]           set_sehold;
91   wire [3:0]           word_en_sehold;
92   wire                 wr_en_sehold;
93   wire [155:0]         decc_in_sehold;
94   wire                 col_offset;
95   
96   wire [155:0]         decc_out ;
97
98// JC begin
99// Because of this 2 cycle block,
100// The following codes are just helping me for Innologic verification
101// stop_1_cyc: when col_offset = 1, the next cycle will be ignore
102// keep_rd_out: The output data will be kept for another cycle
103   reg                  keep_rd_out;
104   reg                  stop_1_cyc;
105   always @(posedge rclk) begin
106      if (col_offset && (|way_sel_sehold)) begin
107         stop_1_cyc <= 1'b1;
108      end
109      else stop_1_cyc <= 1'b0;
110      if (acc_en_d1 & ~wr_en_d1) begin
111         keep_rd_out <= 1'b1;
112      end
113      else keep_rd_out <= 1'b0;
114   end
115// JC end 
116
117
118   assign               wr_en_sehold = (sehold) ? wr_en_d1 : ~wr_en_l;
119   assign               set_sehold = (sehold) ? set_d1 : ~set_l;
120   assign               way_sel_sehold = (sehold) ? way_sel_d1 : ~way_sel_l;
121   assign               word_en_sehold = (sehold) ? word_en_d1 : ~word_en_l;
122// In Circuits, we use se to disable write, however, I modified testbench as following
123// to verify write disable:
124//     force inno_tb_top.xtor.xcnt.se_l = ~mem_write_disable ;
125
126   assign               col_offset = (stop_1_cyc || mem_write_disable ) ? (1'b0) : ~col_offset_l ;
127 
128   assign acc_en_d1 = col_offset_d1 & (|way_sel_d1);   
129
130   always @(posedge rclk) begin
131      col_offset_d1 <= col_offset;
132      way_sel_d1  <= way_sel_sehold;
133      set_d1  <= set_sehold;
134      word_en_d1 <= word_en_sehold;
135      wr_en_d1  <= wr_en_sehold;
136// JC
137// EVEN THOUGH We don't have any write data latch,
138// Our write-data drivers act like latch which gating by
139// Worden signals.
140      decc_in_d1 <= ~decc_in_l;
141// JC
142//This is NOT output flops, but we can keep read outs for
143// 2 cycles.     
144      decc_out_d1 <= decc_out_tmp;
145   end     
146 
147
148`ifdef DEFINE_0IN
149   wire [155:0] decc_out0, decc_out1;
150
151   wire [155:0] wm  = { {39{word_en_d1[3]}}, {39{word_en_d1[2]}}, {39{word_en_d1[1]}}, {39{word_en_d1[0]}} };
152   wire         we0 = acc_en_d1 & wr_en_d1 & way_sel_d1[0];
153   wire         we1 = acc_en_d1 & wr_en_d1 & way_sel_d1[1];
154
155l2data_axis     data_array0 (.data_out  (decc_out0[155:0]),
156                             .rclk      (rclk),
157                             .adr       (set_d1[9:0]),
158                             .data_in   (decc_in_d1[155:0]),
159                             .we        (we0),
160                             .wm        (wm[155:0]) );
161l2data_axis     data_array1 (.data_out  (decc_out1[155:0]),
162                             .rclk      (rclk),
163                             .adr       (set_d1[9:0]),
164                             .data_in   (decc_in_d1[155:0]),
165                             .we        (we1),
166                             .wm        (wm[155:0]) );
167
168   always @(/*AUTOSENSE*/acc_en_d1 or decc_in_d1 or decc_out0
169            or decc_out1 or way_sel_d1 or word_en_d1 or wr_en_d1) begin
170        if (acc_en_d1 & ~wr_en_d1) begin
171           //////////////////////////
172           // 16 or 64B byte read
173           //////////////////////////
174           decc_out_tmp = way_sel_d1[0] ? decc_out0[155:0] : decc_out1[155:0];
175        end
176
177        if (acc_en_d1 & wr_en_d1) begin
178           //////////////////////////
179           // Store word/dword OR 64B store
180           //////////////////////////
181           tmp_decc_out = way_sel_d1[0] ? decc_out0[155:0] : decc_out1[155:0];
182
183           //////////////////////////////////////
184           // Write data based on Word enables.
185           //////////////////////////////////////
186
187           reg_decc_in[155:117] = (decc_in_d1[155:117] & {39{word_en_d1[3]}} |
188                                   tmp_decc_out[155:117] & {39{~word_en_d1[3]}});
189           reg_decc_in[116:78] = (decc_in_d1[116:78] & {39{word_en_d1[2]}} |
190                                  tmp_decc_out[116:78] & {39{~word_en_d1[2]}});
191           reg_decc_in[77:39] = (decc_in_d1[77:39] & {39{word_en_d1[1]}} |
192                                 tmp_decc_out[77:39] & {39{~word_en_d1[1]}});
193           reg_decc_in[38:0] = (decc_in_d1[38:0] & {39{word_en_d1[0]}} |
194                                tmp_decc_out[38:0] & {39{~word_en_d1[0]}});
195         
196           //////////////////////////////////////////////////////////
197           // the store data gets reflected onto the read output bus
198           //////////////////////////////////////////////////////////
199         
200//           decc_out_tmp[155:0] = reg_decc_in[155:0];
201// Store data is *not* reflected onto the read output bus in the physical implementation
202             decc_out_tmp[155:0] = 156'b0;
203         
204        end // of write operation
205
206      if (~acc_en_d1) begin
207        // no access
208         decc_out_tmp[155:0] = 156'b0;
209      end
210
211   end // of always block
212
213`else
214
215   always @(/*AUTOSENSE*/acc_en_d1 or decc_in_d1 or set_d1
216            or way_sel_d1 or word_en_d1 or wr_en_d1) begin
217     
218`ifdef  INNO_MUXEX
219`else
220//----- PURELY FOR VERIFICATION -----------------------
221      if(wr_en_d1==1'bx) begin
222        `ifdef MODELSIM
223         $display("L2_DATA_ERR"," wr en error %b ", wr_en_d1);
224        `else
225         $error("L2_DATA_ERR"," wr en error %b ", wr_en_d1);
226        `endif 
227      end
228//----- PURELY FOR VERIFICATION -----------------------
229`endif
230
231
232//////////////////
233// MEMORY ACCESS
234//////////////////
235
236      if (acc_en_d1) begin
237
238`ifdef  INNO_MUXEX
239`else
240//----- PURELY FOR VERIFICATION -----------------------
241         if(set_d1==10'bx) begin
242        `ifdef MODELSIM 
243            $error("L2_DATA_ERR"," index error %h ", set_d1[9:0]);
244        `else
245            $display("L2_DATA_ERR"," index error %h ", set_d1[9:0]);
246        `endif
247         end
248//----- PURELY FOR VERIFICATION -----------------------
249`endif
250
251
252        if (~wr_en_d1) begin
253           //////////////////////////
254           // 16 or 64B byte read
255           //////////////////////////
256           decc_out_tmp = way_sel_d1[0] ? way0_decc[set_d1] : way1_decc[set_d1];
257//JC: For keeping data for 2 cycle
258//         keep_rd_out = 2'b01;   
259        end
260
261        else begin
262           //////////////////////////
263           // Store word/dword OR 64B store
264           //////////////////////////
265           tmp_decc_out = way_sel_d1[0] ? way0_decc[set_d1] : way1_decc[set_d1];
266           
267//         keep_rd_out = 2'b00;   
268           //////////////////////////////////////
269           // Write data based on Word enables.
270           //////////////////////////////////////
271           
272           reg_decc_in[155:117] = (decc_in_d1[155:117] & {39{word_en_d1[3]}} |
273                                   tmp_decc_out[155:117] & {39{~word_en_d1[3]}});
274           reg_decc_in[116:78] = (decc_in_d1[116:78] & {39{word_en_d1[2]}} |
275                                  tmp_decc_out[116:78] & {39{~word_en_d1[2]}});
276           reg_decc_in[77:39] = (decc_in_d1[77:39] & {39{word_en_d1[1]}} |
277                                 tmp_decc_out[77:39] & {39{~word_en_d1[1]}});
278           reg_decc_in[38:0] = (decc_in_d1[38:0] & {39{word_en_d1[0]}} |
279                                tmp_decc_out[38:0] & {39{~word_en_d1[0]}});
280           
281           if (way_sel_d1[0]) way0_decc[set_d1] =  reg_decc_in;
282           if (way_sel_d1[1]) way1_decc[set_d1] =  reg_decc_in;
283           
284           //////////////////////////////////////////////////////////
285           // the store data gets reflected onto the read output bus
286           //////////////////////////////////////////////////////////
287
288//           decc_out_tmp[155:0] = reg_decc_in[155:0];
289// Store data is *not* reflected onto the read output bus in the physical implementation
290
291             decc_out_tmp[155:0] = 156'b0;
292           
293        end // of write operation
294
295      end
296     
297      else begin
298        // no access
299         decc_out_tmp[155:0] = 156'b0;
300      end
301     
302   end // of always block
303`endif
304   // Modeling wired-OR
305
306// JC we don't have any flop in this level
307//   assign decc_out[155:0] = decc_out_d1[155:0] | decc_read_in[155:0];   
308
309   assign decc_out[155:0] = (acc_en_d1 & ~wr_en_d1) ? 156'bX : (keep_rd_out) ? 
310                            (decc_out_d1[155:0] | decc_read_in[155:0]) : 
311                            (decc_out_tmp[155:0] | decc_read_in[155:0]);
312   
313/////////////////////////////////////////////////////////////////////
314// Redundancy Registers
315/////////////////////////////////////////////////////////////////////
316
317   reg [8:0]    s_red_reg0;
318   reg [8:0]    s_red_reg1;
319   reg [8:0]    s_red_reg2;
320   reg [8:0]    s_red_reg3;
321   reg [8:0]    s_red_reg4;
322   reg [8:0]    s_red_reg5;
323               
324   reg [8:0]    m_red_reg0;
325   reg [8:0]    m_red_reg1;
326   reg [8:0]    m_red_reg2;
327   reg [8:0]    m_red_reg3;
328   reg [8:0]    m_red_reg4;
329   reg [8:0]    m_red_reg5;
330                   
331   wire      l2d_fuse_data_out;
332   
333assign l2d_fuse_data_out = s_red_reg5[8];
334   
335   always @(arst_l or fuse_clk1 or fuse_l2d_rid or fuse_l2d_wren or fuse_l2d_rden
336            or fuse_l2d_data_in or fuse_read_data_in
337            or s_red_reg0 or s_red_reg1 or s_red_reg2
338            or s_red_reg3 or s_red_reg4 or s_red_reg5) begin
339
340      if (!arst_l) begin
341         m_red_reg0[8:0] = 9'b0;
342         m_red_reg1[8:0] = 9'b0;
343         m_red_reg2[8:0] = 9'b0;
344         m_red_reg3[8:0] = 9'b0;
345         m_red_reg4[8:0] = 9'b0;
346         m_red_reg5[8:0] = 9'b0;
347      end
348
349      if (arst_l && fuse_clk1) begin
350     
351      /////////////////////////////////
352      // Write operation
353      /////////////////////////////////
354     
355         if (fuse_l2d_wren) begin
356            case (fuse_l2d_rid) //selecting among the six registers
357              3'b101: m_red_reg0[8:0] = {s_red_reg0[7:0], fuse_l2d_data_in};// bottom odd row
358              3'b011: m_red_reg1[8:0] = {s_red_reg1[7:0], fuse_l2d_data_in};// bottom even row
359              3'b010: m_red_reg2[8:0] = {s_red_reg2[7:0], fuse_l2d_data_in};// bottom column
360              3'b100: m_red_reg3[8:0] = {s_red_reg3[7:0], fuse_l2d_data_in};// top odd row
361              3'b001: m_red_reg4[8:0] = {s_red_reg4[7:0], fuse_l2d_data_in};// top even row
362              3'b000: m_red_reg5[8:0] = {s_red_reg5[7:0], fuse_l2d_data_in};// top column
363              default: ;
364            endcase // case(fuse_l2d_rid)
365         end // if (fuse_l2d_wren)
366     
367      /////////////////////////////////
368      // Read operation
369      /////////////////////////////////
370     
371//JC This is just temporary fix for read operation, rid = 3'b111 will turn on everything
372         else if (fuse_l2d_rden) begin
373                      m_red_reg0[8:0] = {s_red_reg0[7:0], fuse_read_data_in};
374                      m_red_reg1[8:0] = {s_red_reg1[7:0], s_red_reg0[8]};
375                      m_red_reg2[8:0] = {s_red_reg2[7:0], s_red_reg1[8]};
376                      m_red_reg3[8:0] = {s_red_reg3[7:0], s_red_reg2[8]};
377                      m_red_reg4[8:0] = {s_red_reg4[7:0], s_red_reg3[8]};
378                      m_red_reg5[8:0] = {s_red_reg5[7:0], s_red_reg4[8]};
379              end // if (fuse_l2d_rden)
380
381      end // if (fuse_clk1)
382
383   end // always @ (fuse_clk1 or...
384
385//   always @(posedge efc_scdata_fuse_clk1) begin
386
387   always @(arst_l or fuse_clk2 or fuse_l2d_rid or fuse_l2d_wren or fuse_l2d_rden
388            or m_red_reg0 or m_red_reg1 or m_red_reg2
389            or m_red_reg3 or m_red_reg4 or m_red_reg5) begin
390
391`ifdef DEFINE_0IN
392`else
393  `ifdef FPGA_SYN_RED
394  `else
395      if (!arst_l) begin
396         m_red_reg0[8:0] = 9'b0;
397         m_red_reg1[8:0] = 9'b0;
398         m_red_reg2[8:0] = 9'b0;
399         m_red_reg3[8:0] = 9'b0;
400         m_red_reg4[8:0] = 9'b0;
401         m_red_reg5[8:0] = 9'b0;
402      end
403  `endif
404`endif
405
406      if (fuse_clk2) begin
407     
408         if (fuse_l2d_wren) begin
409            case (fuse_l2d_rid) //selecting among the six registers
410              3'b101: s_red_reg0[8:0] = m_red_reg0[8:0];// bottom odd row
411              3'b011: s_red_reg1[8:0] = m_red_reg1[8:0];// bottom even row
412              3'b010: s_red_reg2[8:0] = m_red_reg2[8:0];// bottom column
413              3'b100: s_red_reg3[8:0] = m_red_reg3[8:0];// top odd row
414              3'b001: s_red_reg4[8:0] = m_red_reg4[8:0];// top even row
415              3'b000: s_red_reg5[8:0] = m_red_reg5[8:0];// top column
416             default: ;
417            endcase // case(fuse_l2d_rid)
418         end // if (fuse_l2d_wren)
419         else if (fuse_l2d_rden) begin
420                s_red_reg0[8:0] = m_red_reg0[8:0];// bottom odd row
421                s_red_reg1[8:0] = m_red_reg1[8:0];// bottom even row
422                s_red_reg2[8:0] = m_red_reg2[8:0];// bottom column
423                s_red_reg3[8:0] = m_red_reg3[8:0];// top odd row
424                s_red_reg4[8:0] = m_red_reg4[8:0];// top even row
425                s_red_reg5[8:0] = m_red_reg5[8:0];// top column
426              end // if (fuse_l2d_rden)
427
428      end // if (fuse_clk2)
429
430   end // always @ (fuse_clk2 or...
431   
432endmodule // bw_r_l2d_32k
433
Note: See TracBrowser for help on using the repository browser.