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

Subversion Repositories pcie_sg_dma

[/] [pcie_sg_dma/] [branches/] [Virtex6/] [ML605_ISE13.3/] [ipcore_dir_ISE13.3/] [v6_pcie_v1_6/] [example_design/] [PIO_EP_MEM_ACCESS.v] - Blame information for rev 13

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 13 barabba
 
2
//-----------------------------------------------------------------------------
3
//
4
// (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved.
5
//
6
// This file contains confidential and proprietary information
7
// of Xilinx, Inc. and is protected under U.S. and
8
// international copyright and other intellectual property
9
// laws.
10
//
11
// DISCLAIMER
12
// This disclaimer is not a license and does not grant any
13
// rights to the materials distributed herewith. Except as
14
// otherwise provided in a valid license issued to you by
15
// Xilinx, and to the maximum extent permitted by applicable
16
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
17
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
18
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
19
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
20
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
21
// (2) Xilinx shall not be liable (whether in contract or tort,
22
// including negligence, or under any other theory of
23
// liability) for any loss or damage of any kind or nature
24
// related to, arising under or in connection with these
25
// materials, including for any direct, or any indirect,
26
// special, incidental, or consequential loss or damage
27
// (including loss of data, profits, goodwill, or any type of
28
// loss or damage suffered as a result of any action brought
29
// by a third party) even if such damage or loss was
30
// reasonably foreseeable or Xilinx had been advised of the
31
// possibility of the same.
32
//
33
// CRITICAL APPLICATIONS
34
// Xilinx products are not designed or intended to be fail-
35
// safe, or for use in any application requiring fail-safe
36
// performance, such as life-support or safety devices or
37
// systems, Class III medical devices, nuclear facilities,
38
// applications related to the deployment of airbags, or any
39
// other applications that could lead to death, personal
40
// injury, or severe property or environmental damage
41
// (individually and collectively, "Critical
42
// Applications"). Customer assumes the sole risk and
43
// liability of any use of Xilinx products in Critical
44
// Applications, subject only to applicable laws and
45
// regulations governing limitations on product liability.
46
//
47
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
48
// PART OF THIS FILE AT ALL TIMES.
49
//
50
//-----------------------------------------------------------------------------
51
// Project    : Virtex-6 Integrated Block for PCI Express
52
// File       : PIO_EP_MEM_ACCESS.v
53
// Version    : 1.7
54
//--
55
//-- Description: Endpoint Memory Access Unit. This module provides access functions
56
//--              to the Endpoint memory aperture.
57
//--
58
//--              Read Access: Module returns data for the specifed address and
59
//--              byte enables selected. 
60
//-- 
61
//--              Write Access: Module accepts data, byte enables and updates
62
//--              data when write enable is asserted. Modules signals write busy 
63
//--              when data write is in progress. 
64
//--
65
//--------------------------------------------------------------------------------
66
 
67
`timescale 1ns/1ns
68
 
69
`define TCQ 1
70
 
71
`define PIO_MEM_ACCESS_WR_RST     3'b000
72
`define PIO_MEM_ACCESS_WR_WAIT    3'b001
73
`define PIO_MEM_ACCESS_WR_READ    3'b010
74
`define PIO_MEM_ACCESS_WR_WRITE   3'b100
75
 
76
 
77
 
78
module PIO_EP_MEM_ACCESS (
79
 
80
                     clk,
81
                     rst_n,
82
 
83
                     // Read Access
84
 
85
                     rd_addr_i,     // I [10:0]
86
                     rd_be_i,       // I [3:0]
87
                     rd_data_o,     // O [31:0]
88
 
89
                     // Write Access
90
 
91
                     wr_addr_i,     // I [10:0]
92
                     wr_be_i,       // I [7:0]
93
                     wr_data_i,     // I [31:0]
94
                     wr_en_i,       // I
95
                     wr_busy_o      // O
96
 
97
                     );
98
 
99
    input            clk;
100
    input            rst_n;
101
 
102
    // *  Read Port
103
 
104
    input  [10:0]    rd_addr_i;
105
    input  [3:0]     rd_be_i;
106
    output [31:0]    rd_data_o;
107
 
108
    // *  Write Port
109
 
110
    input  [10:0]    wr_addr_i;
111
    input  [7:0]     wr_be_i;
112
    input  [31:0]    wr_data_i;
113
    input            wr_en_i;
114
    output           wr_busy_o;
115
 
116
    wire   [31:0]     rd_data_o;
117
 
118
    reg   [31:0]      rd_data_raw_o;
119
 
120
    wire  [31:0]     rd_data0_o, rd_data1_o, rd_data2_o, rd_data3_o;
121
 
122
    wire             wr_busy_o;
123
    reg              write_en;
124
    reg   [31:0]     post_wr_data;
125
    reg   [31:0]     w_pre_wr_data;
126
 
127
    reg   [2:0]      wr_mem_state;
128
 
129
    reg   [31:0]     pre_wr_data;
130
    wire  [31:0]     w_pre_wr_data0;
131
    wire  [31:0]     w_pre_wr_data1;
132
    wire  [31:0]     w_pre_wr_data2;
133
    wire  [31:0]     w_pre_wr_data3;
134
 
135
    reg   [31:0]     pre_wr_data0_q, pre_wr_data1_q, pre_wr_data2_q, pre_wr_data3_q;
136
 
137
    reg   [31:0]     DW0, DW1, DW2;
138
 
139
    // ** Memory Write Process
140
 
141
    // *  Extract current data bytes. These need to be swizzled
142
    // *  BRAM storage format :
143
    // *    data[31:0] = { byte[3], byte[2], byte[1], byte[0] (lowest addr) }
144
 
145
    wire  [7:0]      w_pre_wr_data_b3 = pre_wr_data[31:24];
146
    wire  [7:0]      w_pre_wr_data_b2 = pre_wr_data[23:16];
147
    wire  [7:0]      w_pre_wr_data_b1 = pre_wr_data[15:08];
148
    wire  [7:0]      w_pre_wr_data_b0 = pre_wr_data[07:00];
149
 
150
    // *  Extract new data bytes from payload
151
    // *  TLP Payload format :
152
    // *    data[31:0] = { byte[0] (lowest addr), byte[2], byte[1], byte[3] }  
153
 
154
    wire  [7:0]      w_wr_data_b3 = wr_data_i[07:00];
155
    wire  [7:0]      w_wr_data_b2 = wr_data_i[15:08];
156
    wire  [7:0]      w_wr_data_b1 = wr_data_i[23:16];
157
    wire  [7:0]      w_wr_data_b0 = wr_data_i[31:24];
158
 
159
 
160
    always @(posedge clk or negedge rst_n) begin
161
 
162
        if ( !rst_n ) begin
163
 
164
          pre_wr_data <= 32'b0;
165
          post_wr_data <= 32'b0;
166
          pre_wr_data <= 32'b0;
167
          write_en   <= 1'b0;
168
          pre_wr_data0_q <= 32'b0;
169
          pre_wr_data1_q <= 32'b0;
170
          pre_wr_data2_q <= 32'b0;
171
          pre_wr_data3_q <= 32'b0;
172
 
173
          wr_mem_state <= `PIO_MEM_ACCESS_WR_RST;
174
 
175
        end else begin
176
 
177
          case ( wr_mem_state )
178
 
179
            `PIO_MEM_ACCESS_WR_RST : begin
180
 
181
              if (wr_en_i) begin // read state
182
 
183
                wr_mem_state <= `PIO_MEM_ACCESS_WR_WAIT; //Pipelining happens in RAM's internal output reg.
184
 
185
              end else begin
186
 
187
                write_en <= 1'b0;
188
 
189
                wr_mem_state <= `PIO_MEM_ACCESS_WR_RST;
190
 
191
              end
192
 
193
            end
194
 
195
            `PIO_MEM_ACCESS_WR_WAIT : begin
196
 
197
              // * Pipeline B port data before processing. Virtex 5 Block RAMs have internal
198
              //   output register enabled.
199
 
200
              //pre_wr_data0_q <= w_pre_wr_data0;
201
             // pre_wr_data1_q <= w_pre_wr_data1;
202
             // pre_wr_data2_q <= w_pre_wr_data2;
203
             // pre_wr_data3_q <= w_pre_wr_data3;
204
 
205
              write_en <= 1'b0;
206
 
207
              wr_mem_state <= `PIO_MEM_ACCESS_WR_READ ;
208
 
209
            end
210
 
211
            `PIO_MEM_ACCESS_WR_READ : begin
212
 
213
               //  * Now save the selected BRAM B port data out
214
 
215
                pre_wr_data <= w_pre_wr_data;
216
                write_en <= 1'b0;
217
 
218
                wr_mem_state <= `PIO_MEM_ACCESS_WR_WRITE;
219
 
220
            end
221
 
222
            `PIO_MEM_ACCESS_WR_WRITE : begin
223
 
224
              // * Merge new enabled data and write target BlockRAM location
225
 
226
              post_wr_data <= {{wr_be_i[3] ? w_wr_data_b3 : w_pre_wr_data_b3},
227
                               {wr_be_i[2] ? w_wr_data_b2 : w_pre_wr_data_b2},
228
                               {wr_be_i[1] ? w_wr_data_b1 : w_pre_wr_data_b1},
229
                               {wr_be_i[0] ? w_wr_data_b0 : w_pre_wr_data_b0}};
230
              write_en     <= 1'b1;
231
 
232
              wr_mem_state <= `PIO_MEM_ACCESS_WR_RST;
233
 
234
            end
235
 
236
          endcase
237
 
238
        end
239
 
240
    end
241
 
242
    // * Write controller busy 
243
 
244
    assign wr_busy_o = wr_en_i | (wr_mem_state != `PIO_MEM_ACCESS_WR_RST);
245
 
246
    // *  Select BlockRAM output based on higher 2 address bits
247
 
248
    always @* // (wr_addr_i or pre_wr_data0_q or pre_wr_data1_q or pre_wr_data2_q or pre_wr_data3_q) begin
249
     begin
250
      case ({wr_addr_i[10:9]}) // synthesis parallel_case full_case
251
 
252
        2'b00 : w_pre_wr_data = w_pre_wr_data0;
253
        2'b01 : w_pre_wr_data = w_pre_wr_data1;
254
        2'b10 : w_pre_wr_data = w_pre_wr_data2;
255
        2'b11 : w_pre_wr_data = w_pre_wr_data3;
256
 
257
      endcase
258
 
259
    end
260
 
261
    // *  Memory Read Controller
262
 
263
    wire        rd_data0_en = {rd_addr_i[10:9]  == 2'b00};
264
    wire        rd_data1_en = {rd_addr_i[10:9]  == 2'b01};
265
    wire        rd_data2_en = {rd_addr_i[10:9]  == 2'b10};
266
    wire        rd_data3_en = {rd_addr_i[10:9]  == 2'b11};
267
 
268
 
269
    always @(rd_addr_i or rd_data0_o or rd_data1_o or rd_data2_o or rd_data3_o)
270
      begin
271
 
272
      case ({rd_addr_i[10:9]}) // synthesis parallel_case full_case
273
 
274
        2'b00 : rd_data_raw_o = rd_data0_o;
275
        2'b01 : rd_data_raw_o = rd_data1_o;
276
        2'b10 : rd_data_raw_o = rd_data2_o;
277
        2'b11 : rd_data_raw_o = rd_data3_o;
278
 
279
      endcase
280
 
281
    end
282
 
283
   // Handle Read byte enables
284
 
285
    assign rd_data_o = {{rd_be_i[0] ? rd_data_raw_o[07:00] : 8'h0},
286
                        {rd_be_i[1] ? rd_data_raw_o[15:08] : 8'h0},
287
                        {rd_be_i[2] ? rd_data_raw_o[23:16] : 8'h0},
288
                        {rd_be_i[3] ? rd_data_raw_o[31:24] : 8'h0}};
289
 
290
    EP_MEM EP_MEM    (
291
 
292
                      .clk_i(clk),
293
 
294
                      .a_rd_a_i_0(rd_addr_i[8:0]),              // I [8:0]
295
                      .a_rd_en_i_0(rd_data0_en),                // I [1:0]
296
                      .a_rd_d_o_0(rd_data0_o),                  // O [31:0]
297
 
298
                      .b_wr_a_i_0(wr_addr_i[8:0]),              // I [8:0]
299
                      .b_wr_d_i_0(post_wr_data),                // I [31:0]
300
                      .b_wr_en_i_0({write_en & (wr_addr_i[10:9] == 2'b00)}), // I
301
                      .b_rd_d_o_0(w_pre_wr_data0[31:0]),        // O [31:0]
302
                      .b_rd_en_i_0({wr_addr_i[10:9] == 2'b00}), // I
303
 
304
                      .a_rd_a_i_1(rd_addr_i[8:0]),              // I [8:0]
305
                      .a_rd_en_i_1(rd_data1_en),                // I [1:0]
306
                      .a_rd_d_o_1(rd_data1_o),                  // O [31:0]
307
 
308
                      .b_wr_a_i_1(wr_addr_i[8:0]),              // [8:0]
309
                      .b_wr_d_i_1(post_wr_data),                // [31:0]
310
                      .b_wr_en_i_1({write_en & (wr_addr_i[10:9] == 2'b01)}), // I
311
                      .b_rd_d_o_1(w_pre_wr_data1[31:0]),        // [31:0]
312
                      .b_rd_en_i_1({wr_addr_i[10:9] == 2'b01}), // I
313
 
314
                      .a_rd_a_i_2(rd_addr_i[8:0]),              // I [8:0]
315
                      .a_rd_en_i_2(rd_data2_en),                // I [1:0]
316
                      .a_rd_d_o_2(rd_data2_o),                  // O [31:0]
317
 
318
                      .b_wr_a_i_2(wr_addr_i[8:0]),              // I [8:0]
319
                      .b_wr_d_i_2(post_wr_data),                // I [31:0]
320
                      .b_wr_en_i_2({write_en & (wr_addr_i[10:9] == 2'b10)}), // I
321
                      .b_rd_d_o_2(w_pre_wr_data2[31:0]),        // I [31:0]
322
                      .b_rd_en_i_2({wr_addr_i[10:9] == 2'b10}), // I
323
 
324
                      .a_rd_a_i_3(rd_addr_i[8:0]),              // [8:0]
325
                      .a_rd_en_i_3(rd_data3_en),                // [1:0]
326
                      .a_rd_d_o_3(rd_data3_o),                  // O [31:0]
327
 
328
                      .b_wr_a_i_3(wr_addr_i[8:0]),              // I [8:0]
329
                      .b_wr_d_i_3(post_wr_data),                // I [31:0]
330
                      .b_wr_en_i_3({write_en & (wr_addr_i[10:9] == 2'b11)}), // I
331
                      .b_rd_d_o_3(w_pre_wr_data3[31:0]),        // I [31:0]
332
                      .b_rd_en_i_3({wr_addr_i[10:9] == 2'b11})  // I
333
 
334
                     );
335
 
336
  // synthesis translate_off
337
  reg  [8*20:1] state_ascii;
338
  always @(wr_mem_state)
339
  begin
340
    if      (wr_mem_state==`PIO_MEM_ACCESS_WR_RST)    state_ascii <= #`TCQ "PIO_MEM_WR_RST";
341
    else if (wr_mem_state==`PIO_MEM_ACCESS_WR_WAIT)   state_ascii <= #`TCQ "PIO_MEM_WR_WAIT";
342
    else if (wr_mem_state==`PIO_MEM_ACCESS_WR_READ)   state_ascii <= #`TCQ "PIO_MEM_WR_READ";
343
    else if (wr_mem_state==`PIO_MEM_ACCESS_WR_WRITE)  state_ascii <= #`TCQ "PIO_MEM_WR_WRITE";
344
    else                                              state_ascii <= #`TCQ "PIO MEM STATE ERR";
345
 
346
  end
347
  // synthesis translate_on
348
 
349
endmodule
350
 

powered by: WebSVN 2.1.0

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