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

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [examples/] [memfifo/] [fpga-2.13/] [memfifo.srcs/] [sources_1/] [ip/] [mig_7series_0/] [mig_7series_0/] [user_design/] [rtl/] [ui/] [mig_7series_v2_3_ui_wr_data.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ZTEX
//*****************************************************************************
2
// (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
3
//
4
// This file contains confidential and proprietary information
5
// of Xilinx, Inc. and is protected under U.S. and
6
// international copyright and other intellectual property
7
// laws.
8
//
9
// DISCLAIMER
10
// This disclaimer is not a license and does not grant any
11
// rights to the materials distributed herewith. Except as
12
// otherwise provided in a valid license issued to you by
13
// Xilinx, and to the maximum extent permitted by applicable
14
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
15
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
16
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
17
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
18
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
19
// (2) Xilinx shall not be liable (whether in contract or tort,
20
// including negligence, or under any other theory of
21
// liability) for any loss or damage of any kind or nature
22
// related to, arising under or in connection with these
23
// materials, including for any direct, or any indirect,
24
// special, incidental, or consequential loss or damage
25
// (including loss of data, profits, goodwill, or any type of
26
// loss or damage suffered as a result of any action brought
27
// by a third party) even if such damage or loss was
28
// reasonably foreseeable or Xilinx had been advised of the
29
// possibility of the same.
30
//
31
// CRITICAL APPLICATIONS
32
// Xilinx products are not designed or intended to be fail-
33
// safe, or for use in any application requiring fail-safe
34
// performance, such as life-support or safety devices or
35
// systems, Class III medical devices, nuclear facilities,
36
// applications related to the deployment of airbags, or any
37
// other applications that could lead to death, personal
38
// injury, or severe property or environmental damage
39
// (individually and collectively, "Critical
40
// Applications"). Customer assumes the sole risk and
41
// liability of any use of Xilinx products in Critical
42
// Applications, subject only to applicable laws and
43
// regulations governing limitations on product liability.
44
//
45
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
46
// PART OF THIS FILE AT ALL TIMES.
47
//
48
//*****************************************************************************
49
//   ____  ____
50
//  /   /\/   /
51
// /___/  \  /    Vendor                : Xilinx
52
// \   \   \/     Version               : %version
53
//  \   \         Application           : MIG
54
//  /   /         Filename              : ui_wr_data.v
55
// /___/   /\     Date Last Modified    : $date$
56
// \   \  /  \    Date Created          : Tue Jun 30 2009
57
//  \___\/\___\
58
//
59
//Device            : 7-Series
60
//Design Name       : DDR3 SDRAM
61
//Purpose           :
62
//Reference         :
63
//Revision History  :
64
//*****************************************************************************
65
 
66
// User interface write data buffer.  Consists of four counters,
67
// a pointer RAM and the write data storage RAM.
68
//
69
// All RAMs are implemented with distributed RAM.
70
//
71
// Whe ordering is set to STRICT or NORM, data moves through
72
// the write data buffer in strictly FIFO order.  In RELAXED
73
// mode, data may be retired from the write data RAM in any
74
// order relative to the input order.  This implementation
75
// supports all ordering modes.
76
//
77
// The pointer RAM stores a list of pointers to the write data storage RAM.
78
// This is a list of vacant entries.  As data is written into the RAM, a
79
// pointer is pulled from the pointer RAM and used to index the write
80
// operation.  In a semi autonomously manner, pointers are also pulled, in
81
// the same order, and provided to the command port as the data_buf_addr.
82
//
83
// When the MC reads data from the write data buffer, it uses the
84
// data_buf_addr provided with the command to extract the data from the
85
// write data buffer.  It also writes this pointer into the end
86
// of the pointer RAM.
87
//
88
// The occupancy counter keeps track of how many entries are valid
89
// in the write data storage RAM.  app_wdf_rdy and app_rdy will be
90
// de-asserted when there is no more storage in the write data buffer.
91
//
92
// Three sequentially incrementing counters/indexes are used to maintain
93
// and use the contents of the pointer RAM.
94
//
95
// The write buffer write data address index generates the pointer
96
// used to extract the write data address from the pointer RAM.  It
97
// is incremented with each buffer write.  The counter is actually one
98
// ahead of the current write address so that the actual data buffer
99
// write address can be registered to give a full state to propagate to
100
// the write data distributed RAMs.
101
//
102
// The data_buf_addr counter is used to extract the data_buf_addr for
103
// the command port.  It is incremented as each command is written
104
// into the MC.
105
//
106
// The read data index points to the end of the list of free
107
// buffers.  When the MC fetches data from the write data buffer, it
108
// provides the buffer address.  The buffer address is used to fetch
109
// the data, but is also written into the pointer at the location indicated
110
// by the read data index.
111
//
112
// Enter and exiting a buffer full condition generates corner cases.  Upon
113
// entering a full condition, incrementing the write buffer write data
114
// address index must be inhibited.  When exiting the full condition,
115
// the just arrived pointer must propagate through the pointer RAM, then
116
// indexed by the current value of the write buffer write data
117
// address counter, the value is registered in the write buffer write
118
// data address register, then the counter can be advanced.
119
//
120
// The pointer RAM must be initialized with valid data after reset.  This is
121
// accomplished by stepping through each pointer RAM entry and writing
122
// the locations address into the pointer RAM.  For the FIFO modes, this means
123
// that buffer address will always proceed in a sequential order.  In the
124
// RELAXED mode, the original write traversal will be in sequential
125
// order, but once the MC begins to retire out of order, the entries in
126
// the pointer RAM will become randomized.  The ui_rd_data module provides
127
// the control information for the initialization process.
128
 
129
`timescale 1 ps / 1 ps
130
 
131
module mig_7series_v2_3_ui_wr_data #
132
  (
133
   parameter TCQ = 100,
134
   parameter APP_DATA_WIDTH       = 256,
135
   parameter APP_MASK_WIDTH       = 32,
136
   parameter ECC                  = "OFF",
137
   parameter nCK_PER_CLK          = 2 ,
138
   parameter ECC_TEST             = "OFF",
139
   parameter CWL                  = 5
140
  )
141
  (/*AUTOARG*/
142
  // Outputs
143
  app_wdf_rdy, wr_req_16, wr_data_buf_addr, wr_data, wr_data_mask,
144
  raw_not_ecc,
145
  // Inputs
146
  rst, clk, app_wdf_data, app_wdf_mask, app_raw_not_ecc, app_wdf_wren,
147
  app_wdf_end, wr_data_offset, wr_data_addr, wr_data_en, wr_accepted,
148
  ram_init_done_r, ram_init_addr
149
  );
150
 
151
  input rst;
152
  input clk;
153
 
154
  input [APP_DATA_WIDTH-1:0] app_wdf_data;
155
  input [APP_MASK_WIDTH-1:0] app_wdf_mask;
156
  input [2*nCK_PER_CLK-1:0] app_raw_not_ecc;
157
  input app_wdf_wren;
158
  input app_wdf_end;
159
 
160
  reg [APP_DATA_WIDTH-1:0] app_wdf_data_r1;
161
  reg [APP_MASK_WIDTH-1:0] app_wdf_mask_r1;
162
  reg [2*nCK_PER_CLK-1:0] app_raw_not_ecc_r1 = 4'b0;
163
  reg app_wdf_wren_r1;
164
  reg app_wdf_end_r1;
165
 
166
  reg app_wdf_rdy_r;
167
 
168
  //Adding few copies of the app_wdf_rdy_r signal in order to meet
169
  //timing. This is signal has a very high fanout. So grouped into
170
  //few functional groups and alloted one copy per group.
171
  (* equivalent_register_removal = "no" *)
172
  reg app_wdf_rdy_r_copy1;
173
  (* equivalent_register_removal = "no" *)
174
  reg app_wdf_rdy_r_copy2;
175
  (* equivalent_register_removal = "no" *)
176
  reg app_wdf_rdy_r_copy3;
177
  (* equivalent_register_removal = "no" *)
178
  reg app_wdf_rdy_r_copy4;
179
 
180
  wire [APP_DATA_WIDTH-1:0] app_wdf_data_ns1 =
181
         ~app_wdf_rdy_r_copy2 ? app_wdf_data_r1 : app_wdf_data;
182
  wire [APP_MASK_WIDTH-1:0] app_wdf_mask_ns1 =
183
         ~app_wdf_rdy_r_copy2 ? app_wdf_mask_r1 : app_wdf_mask;
184
  wire app_wdf_wren_ns1 =
185
         ~rst && (~app_wdf_rdy_r_copy2 ? app_wdf_wren_r1 : app_wdf_wren);
186
  wire app_wdf_end_ns1 =
187
         ~rst && (~app_wdf_rdy_r_copy2 ? app_wdf_end_r1 : app_wdf_end);
188
 
189
  generate
190
    if (ECC_TEST != "OFF") begin : ecc_on
191
        always @(app_raw_not_ecc) app_raw_not_ecc_r1 = app_raw_not_ecc;
192
    end
193
  endgenerate
194
 
195
// Be explicit about the latch enable on these registers.
196
  always @(posedge clk) begin
197
      app_wdf_data_r1 <= #TCQ app_wdf_data_ns1;
198
      app_wdf_mask_r1 <= #TCQ app_wdf_mask_ns1;
199
      app_wdf_wren_r1 <= #TCQ app_wdf_wren_ns1;
200
      app_wdf_end_r1 <= #TCQ app_wdf_end_ns1;
201
  end
202
 
203
// The signals wr_data_addr and wr_data_offset come at different
204
// times depending on ECC and the value of CWL.  The data portion
205
// always needs to look a the raw wires, the control portion needs
206
// to look at a delayed version when ECC is on and CWL != 8. The
207
// currently supported write data delays do not require this
208
// functionality, but preserve for future use.
209
  input wr_data_offset;
210
  input [3:0] wr_data_addr;
211
  reg wr_data_offset_r;
212
  reg [3:0] wr_data_addr_r;
213
  generate
214
    if (ECC == "OFF" || CWL >= 0) begin : pass_wr_addr
215
      always @(wr_data_offset) wr_data_offset_r = wr_data_offset;
216
      always @(wr_data_addr) wr_data_addr_r = wr_data_addr;
217
    end
218
    else begin : delay_wr_addr
219
      always @(posedge clk) wr_data_offset_r <= #TCQ wr_data_offset;
220
      always @(posedge clk) wr_data_addr_r <= #TCQ wr_data_addr;
221
    end
222
  endgenerate
223
 
224
// rd_data_cnt is the pointer RAM index for data read from the write data
225
// buffer.  Ie, its the data on its way out to the DRAM.
226
  input wr_data_en;
227
  wire new_rd_data = wr_data_en && ~wr_data_offset_r;
228
  reg [3:0] rd_data_indx_r;
229
  reg rd_data_upd_indx_r;
230
  generate begin : read_data_indx
231
      reg [3:0] rd_data_indx_ns;
232
      always @(/*AS*/new_rd_data or rd_data_indx_r or rst) begin
233
        rd_data_indx_ns = rd_data_indx_r;
234
        if (rst) rd_data_indx_ns = 5'b0;
235
        else if (new_rd_data) rd_data_indx_ns = rd_data_indx_r + 5'h1;
236
      end
237
      always @(posedge clk) rd_data_indx_r <= #TCQ rd_data_indx_ns;
238
      always @(posedge clk) rd_data_upd_indx_r <= #TCQ new_rd_data;
239
    end
240
  endgenerate
241
 
242
// data_buf_addr_cnt generates the pointer for the pointer RAM on behalf
243
// of data buf address that comes with the wr_data_en.
244
// The data buf address is written into the memory
245
// controller along with the command and address.
246
  input wr_accepted;
247
  reg [3:0] data_buf_addr_cnt_r;
248
  generate begin : data_buf_address_counter
249
 
250
      reg [3:0] data_buf_addr_cnt_ns;
251
      always @(/*AS*/data_buf_addr_cnt_r or rst or wr_accepted) begin
252
        data_buf_addr_cnt_ns = data_buf_addr_cnt_r;
253
        if (rst) data_buf_addr_cnt_ns = 4'b0;
254
        else if (wr_accepted) data_buf_addr_cnt_ns =
255
                                data_buf_addr_cnt_r + 4'h1;
256
      end
257
      always @(posedge clk) data_buf_addr_cnt_r <= #TCQ data_buf_addr_cnt_ns;
258
 
259
    end
260
  endgenerate
261
 
262
// Control writing data into the write data buffer.
263
  wire wdf_rdy_ns;
264
  always @( posedge clk ) begin
265
        app_wdf_rdy_r_copy1 <= #TCQ wdf_rdy_ns;
266
        app_wdf_rdy_r_copy2 <= #TCQ wdf_rdy_ns;
267
        app_wdf_rdy_r_copy3 <= #TCQ wdf_rdy_ns;
268
        app_wdf_rdy_r_copy4 <= #TCQ wdf_rdy_ns;
269
  end
270
  wire wr_data_end = app_wdf_end_r1 && app_wdf_rdy_r_copy1 && app_wdf_wren_r1;
271
  wire [3:0] wr_data_pntr;
272
  wire [4:0] wb_wr_data_addr;
273
  wire [4:0] wb_wr_data_addr_w;
274
  reg [3:0] wr_data_indx_r;
275
  generate begin : write_data_control
276
 
277
      wire wr_data_addr_le = (wr_data_end && wdf_rdy_ns) ||
278
                             (rd_data_upd_indx_r && ~app_wdf_rdy_r_copy1);
279
 
280
// For pointer RAM.  Initialize to one since this is one ahead of
281
// what's being registered in wb_wr_data_addr.  Assumes pointer RAM
282
// has been initialized such that address equals contents.
283
      reg [3:0] wr_data_indx_ns;
284
      always @(/*AS*/rst or wr_data_addr_le or wr_data_indx_r) begin
285
        wr_data_indx_ns = wr_data_indx_r;
286
        if (rst) wr_data_indx_ns = 4'b1;
287
        else if (wr_data_addr_le) wr_data_indx_ns = wr_data_indx_r + 4'h1;
288
      end
289
      always @(posedge clk) wr_data_indx_r <= #TCQ wr_data_indx_ns;
290
 
291
// Take pointer from pointer RAM and set into the write data address.
292
// Needs to be split into zeroth bit and everything else because synthesis
293
// tools don't always allow assigning bit vectors seperately.  Bit zero of the
294
// address is computed via an entirely different algorithm.
295
      reg [4:1] wb_wr_data_addr_ns;
296
      reg [4:1] wb_wr_data_addr_r;
297
      always @(/*AS*/rst or wb_wr_data_addr_r or wr_data_addr_le
298
               or wr_data_pntr) begin
299
        wb_wr_data_addr_ns = wb_wr_data_addr_r;
300
        if (rst) wb_wr_data_addr_ns = 4'b0;
301
        else if (wr_data_addr_le) wb_wr_data_addr_ns = wr_data_pntr;
302
      end
303
      always @(posedge clk) wb_wr_data_addr_r <= #TCQ wb_wr_data_addr_ns;
304
 
305
// If we see the first getting accepted, then
306
// second half is unconditionally accepted.
307
      reg wb_wr_data_addr0_r;
308
      wire wb_wr_data_addr0_ns = ~rst &&
309
                     ((app_wdf_rdy_r_copy3 && app_wdf_wren_r1 && ~app_wdf_end_r1) ||
310
                      (wb_wr_data_addr0_r && ~app_wdf_wren_r1));
311
      always @(posedge clk) wb_wr_data_addr0_r <= #TCQ wb_wr_data_addr0_ns;
312
 
313
      assign wb_wr_data_addr = {wb_wr_data_addr_r, wb_wr_data_addr0_r};
314
      assign wb_wr_data_addr_w = {wb_wr_data_addr_ns, wb_wr_data_addr0_ns};
315
 
316
    end
317
  endgenerate
318
 
319
// Keep track of how many entries in the queue hold data.
320
  input ram_init_done_r;
321
  output wire app_wdf_rdy;
322
  generate begin : occupied_counter
323
      //reg [4:0] occ_cnt_ns;
324
      //reg [4:0] occ_cnt_r;
325
      //always @(/*AS*/occ_cnt_r or rd_data_upd_indx_r or rst
326
      //         or wr_data_end) begin
327
      //  occ_cnt_ns = occ_cnt_r;
328
      //  if (rst) occ_cnt_ns = 5'b0;
329
      //  else case ({wr_data_end, rd_data_upd_indx_r})
330
      //         2'b01 : occ_cnt_ns = occ_cnt_r - 5'b1;
331
      //         2'b10 : occ_cnt_ns = occ_cnt_r + 5'b1;
332
      //       endcase // case ({wr_data_end, rd_data_upd_indx_r})
333
      //end
334
      //always @(posedge clk) occ_cnt_r <= #TCQ occ_cnt_ns;
335
      //assign wdf_rdy_ns = !(rst || ~ram_init_done_r || occ_cnt_ns[4]);
336
      //always @(posedge clk) app_wdf_rdy_r <= #TCQ wdf_rdy_ns;
337
      //assign app_wdf_rdy = app_wdf_rdy_r;
338
      reg [15:0] occ_cnt;
339
      always @(posedge clk) begin
340
        if ( rst )
341
           occ_cnt <= #TCQ 16'h0000;
342
        else case ({wr_data_end, rd_data_upd_indx_r})
343
              2'b01 : occ_cnt <= #TCQ {1'b0,occ_cnt[15:1]};
344
              2'b10 : occ_cnt <= #TCQ {occ_cnt[14:0],1'b1};
345
             endcase // case ({wr_data_end, rd_data_upd_indx_r})
346
      end
347
      assign wdf_rdy_ns = !(rst || ~ram_init_done_r || (occ_cnt[14] && wr_data_end && ~rd_data_upd_indx_r) || (occ_cnt[15] && ~rd_data_upd_indx_r));
348
      always @(posedge clk) app_wdf_rdy_r <= #TCQ wdf_rdy_ns;
349
      assign app_wdf_rdy = app_wdf_rdy_r;
350
 
351
`ifdef MC_SVA
352
  wr_data_buffer_full: cover property (@(posedge clk)
353
         (~rst && ~app_wdf_rdy_r));
354
//  wr_data_buffer_inc_dec_15: cover property (@(posedge clk)
355
//         (~rst && wr_data_end && rd_data_upd_indx_r && (occ_cnt_r == 5'hf)));
356
//  wr_data_underflow: assert property (@(posedge clk)
357
//         (rst || !((occ_cnt_r == 5'b0) && (occ_cnt_ns == 5'h1f))));
358
//  wr_data_overflow: assert property (@(posedge clk)
359
//         (rst || !((occ_cnt_r == 5'h10) && (occ_cnt_ns == 5'h11))));
360
`endif
361
    end // block: occupied_counter
362
  endgenerate
363
 
364
// Keep track of how many write requests are in the memory controller.  We
365
// must limit this to 16 because we only have that many data_buf_addrs to
366
// hand out.  Since the memory controller queue and the write data buffer
367
// queue are distinct, the number of valid entries can be different.
368
// Throttle request acceptance once there are sixteen write requests in
369
// the memory controller.  Note that there is still a requirement
370
// for a write reqeusts corresponding write data to be written into the
371
// write data queue with two states of the request.
372
  output wire wr_req_16;
373
  generate begin : wr_req_counter
374
      reg [4:0] wr_req_cnt_ns;
375
      reg [4:0] wr_req_cnt_r;
376
      always @(/*AS*/rd_data_upd_indx_r or rst or wr_accepted
377
               or wr_req_cnt_r) begin
378
        wr_req_cnt_ns = wr_req_cnt_r;
379
        if (rst) wr_req_cnt_ns = 5'b0;
380
        else case ({wr_accepted, rd_data_upd_indx_r})
381
               2'b01 : wr_req_cnt_ns = wr_req_cnt_r - 5'b1;
382
               2'b10 : wr_req_cnt_ns = wr_req_cnt_r + 5'b1;
383
             endcase // case ({wr_accepted, rd_data_upd_indx_r})
384
      end
385
      always @(posedge clk) wr_req_cnt_r <= #TCQ wr_req_cnt_ns;
386
      assign wr_req_16 = (wr_req_cnt_ns == 5'h10);
387
 
388
`ifdef MC_SVA
389
  wr_req_mc_full: cover property (@(posedge clk) (~rst && wr_req_16));
390
  wr_req_mc_full_inc_dec_15: cover property (@(posedge clk)
391
       (~rst && wr_accepted && rd_data_upd_indx_r && (wr_req_cnt_r == 5'hf)));
392
  wr_req_underflow: assert property (@(posedge clk)
393
         (rst || !((wr_req_cnt_r == 5'b0) && (wr_req_cnt_ns == 5'h1f))));
394
  wr_req_overflow: assert property (@(posedge clk)
395
         (rst || !((wr_req_cnt_r == 5'h10) && (wr_req_cnt_ns == 5'h11))));
396
`endif
397
    end // block: wr_req_counter
398
  endgenerate
399
 
400
 
401
 
402
// Instantiate pointer RAM.  Made up of RAM32M in single write, two read
403
// port mode, 2 bit wide mode.
404
  input [3:0] ram_init_addr;
405
  output wire [3:0] wr_data_buf_addr;
406
  localparam PNTR_RAM_CNT = 2;
407
  generate begin : pointer_ram
408
      wire pointer_we = new_rd_data || ~ram_init_done_r;
409
      wire [3:0] pointer_wr_data = ram_init_done_r
410
                                    ? wr_data_addr_r
411
                                    : ram_init_addr;
412
      wire [3:0] pointer_wr_addr = ram_init_done_r
413
                                    ? rd_data_indx_r
414
                                    : ram_init_addr;
415
      genvar i;
416
      for (i=0; i<PNTR_RAM_CNT; i=i+1) begin : rams
417
        RAM32M
418
          #(.INIT_A(64'h0000000000000000),
419
            .INIT_B(64'h0000000000000000),
420
            .INIT_C(64'h0000000000000000),
421
            .INIT_D(64'h0000000000000000)
422
          ) RAM32M0 (
423
            .DOA(),
424
            .DOB(wr_data_buf_addr[i*2+:2]),
425
            .DOC(wr_data_pntr[i*2+:2]),
426
            .DOD(),
427
            .DIA(2'b0),
428
            .DIB(pointer_wr_data[i*2+:2]),
429
            .DIC(pointer_wr_data[i*2+:2]),
430
            .DID(2'b0),
431
            .ADDRA(5'b0),
432
            .ADDRB({1'b0, data_buf_addr_cnt_r}),
433
            .ADDRC({1'b0, wr_data_indx_r}),
434
            .ADDRD({1'b0, pointer_wr_addr}),
435
            .WE(pointer_we),
436
            .WCLK(clk)
437
           );
438
      end // block : rams
439
    end // block: pointer_ram
440
  endgenerate
441
 
442
 
443
// Instantiate write data buffer.  Depending on width of DQ bus and
444
// DRAM CK to fabric ratio, number of RAM32Ms is variable.  RAM32Ms are
445
// used in single write, single read, 6 bit wide mode.
446
  localparam WR_BUF_WIDTH =
447
               APP_DATA_WIDTH + APP_MASK_WIDTH + (ECC_TEST == "OFF" ? 0 : 2*nCK_PER_CLK);
448
  localparam FULL_RAM_CNT = (WR_BUF_WIDTH/6);
449
  localparam REMAINDER = WR_BUF_WIDTH % 6;
450
  localparam RAM_CNT = FULL_RAM_CNT + ((REMAINDER == 0 ) ? 0 : 1);
451
  localparam RAM_WIDTH = (RAM_CNT*6);
452
  wire [RAM_WIDTH-1:0] wr_buf_out_data_w;
453
  reg [RAM_WIDTH-1:0] wr_buf_out_data;
454
  generate
455
    begin : write_buffer
456
      wire [RAM_WIDTH-1:0] wr_buf_in_data;
457
      if (REMAINDER == 0)
458
        if (ECC_TEST == "OFF")
459
          assign wr_buf_in_data = {app_wdf_mask_ns1, app_wdf_data_ns1};
460
        else
461
          assign wr_buf_in_data =
462
                   {app_raw_not_ecc_r1, app_wdf_mask_ns1, app_wdf_data_ns1};
463
      else
464
        if (ECC_TEST == "OFF")
465
          assign wr_buf_in_data =
466
               {{6-REMAINDER{1'b0}}, app_wdf_mask_ns1, app_wdf_data_ns1};
467
        else
468
          assign wr_buf_in_data = {{6-REMAINDER{1'b0}}, app_raw_not_ecc_r1,//app_raw_not_ecc_r1 is not ff 
469
                                   app_wdf_mask_ns1, app_wdf_data_ns1};
470
 
471
      wire [4:0] rd_addr_w;
472
 
473
assign rd_addr_w = {wr_data_addr, wr_data_offset};
474
      always @(posedge clk) wr_buf_out_data <= #TCQ  wr_buf_out_data_w;
475
      genvar i;
476
      for (i=0; i<RAM_CNT; i=i+1) begin : wr_buffer_ram
477
        RAM32M
478
          #(.INIT_A(64'h0000000000000000),
479
            .INIT_B(64'h0000000000000000),
480
            .INIT_C(64'h0000000000000000),
481
            .INIT_D(64'h0000000000000000)
482
          ) RAM32M0 (
483
            .DOA(wr_buf_out_data_w[((i*6)+4)+:2]),
484
            .DOB(wr_buf_out_data_w[((i*6)+2)+:2]),
485
            .DOC(wr_buf_out_data_w[((i*6)+0)+:2]),
486
            .DOD(),
487
            .DIA(wr_buf_in_data[((i*6)+4)+:2]),
488
            .DIB(wr_buf_in_data[((i*6)+2)+:2]),
489
            .DIC(wr_buf_in_data[((i*6)+0)+:2]),
490
            .DID(2'b0),
491
            .ADDRA(rd_addr_w),
492
            .ADDRB(rd_addr_w),
493
            .ADDRC(rd_addr_w),
494
            .ADDRD(wb_wr_data_addr_w),
495
            .WE(wdf_rdy_ns),
496
            .WCLK(clk)
497
           );
498
      end // block: wr_buffer_ram
499
    end
500
  endgenerate
501
 
502
  output [APP_DATA_WIDTH-1:0] wr_data;
503
  output [APP_MASK_WIDTH-1:0] wr_data_mask;
504
  assign {wr_data_mask, wr_data} = wr_buf_out_data[WR_BUF_WIDTH-1:0];
505
  output [2*nCK_PER_CLK-1:0] raw_not_ecc;
506
  generate
507
    if (ECC_TEST == "OFF") assign raw_not_ecc = {2*nCK_PER_CLK{1'b0}};
508
    else assign raw_not_ecc = wr_buf_out_data[WR_BUF_WIDTH-1-:(2*nCK_PER_CLK)];
509
  endgenerate
510
 
511
endmodule // ui_wr_data
512
 
513
// Local Variables:
514
// verilog-library-directories:(".")
515
// End:

powered by: WebSVN 2.1.0

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