OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [rtl/] [src_peripheral/] [ram/] [wb_dual_port_ram.v] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 alirezamon
/**********************************************************************
2
**      File:  wb_dual_port_ram.v
3
**
4
**
5
**      Copyright (C) 2014-2017  Alireza Monemi
6
**
7
**      This file is part of ProNoC
8
**
9
**      ProNoC ( stands for Prototype Network-on-chip)  is free software:
10
**      you can redistribute it and/or modify it under the terms of the GNU
11
**      Lesser General Public License as published by the Free Software Foundation,
12
**      either version 2 of the License, or (at your option) any later version.
13
**
14
**      ProNoC is distributed in the hope that it will be useful, but WITHOUT
15
**      ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
**      or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
17
**      Public License for more details.
18
**
19
**      You should have received a copy of the GNU Lesser General Public
20
**      License along with ProNoC. If not, see <http:**www.gnu.org/licenses/>.
21
**
22
**
23
**      Description:
24
**      wishbone based dual port ram
25
**
26
**
27
*******************************************************************/
28
 
29
 
30
 
31
// synthesis translate_off
32
`timescale 1ns / 1ps
33
// synthesis translate_on
34
 
35
 
36
 
37
 
38
module wb_dual_port_ram #(
39
        parameter INITIAL_EN= "NO",
40
    parameter MEM_CONTENT_FILE_NAME= "ram0",// ram initial file name
41
    parameter INIT_FILE_PATH = "path_to/sw", // The sw folder path. It will be used for finding initial file. The path will be rewriten by the top module. 
42
        parameter Dw=32, //RAM data_width in bits
43
        parameter Aw=10, //RAM address width
44
        parameter BYTE_WR_EN= "YES",//"YES","NO"
45
        parameter FPGA_VENDOR= "ALTERA",//"ALTERA","XILINX","GENERIC"
46
        parameter CORE_NUM=0, // use for initialing
47
        // wishbon bus param
48
        parameter   PORT_A_BURST_MODE= "DISABLED", // "DISABLED" , "ENABLED" wisbone bus burst mode 
49
        parameter   PORT_B_BURST_MODE= "DISABLED", // "DISABLED" , "ENABLED" wisbone bus burst mode 
50
        parameter       TAGw   =   3,
51
        parameter       SELw   =   Dw/8,
52
        parameter       CTIw   =   3,
53
        parameter       BTEw   =   2,
54
    parameter   WB_Aw  =   20 // Wishbon bus reserved address with range. WB_Aw >=Aw 
55
 
56
        )
57
        (
58
            clk,
59
            reset,
60
 
61
            //wishbone bus port one interafces
62
            sa_dat_i,
63
            sa_sel_i,
64
            sa_addr_i,
65
            sa_tag_i,
66
            sa_cti_i,
67
            sa_bte_i,
68
            sa_stb_i,
69
            sa_cyc_i,
70
            sa_we_i,
71
            sa_dat_o,
72
            sa_ack_o,
73
            sa_err_o,
74
            sa_rty_o,
75
 
76
 
77
 
78
            //wishbone bus port two interfaces
79
            sb_dat_i,
80
            sb_sel_i,
81
            sb_addr_i,
82
            sb_tag_i,
83
            sb_cti_i,
84
            sb_bte_i,
85
            sb_stb_i,
86
            sb_cyc_i,
87
            sb_we_i,
88
            sb_dat_o,
89
            sb_ack_o,
90
            sb_err_o,
91
            sb_rty_o
92
 
93
        );
94
 
95
 
96
        // synthesis translate_off 
97
     initial begin
98
                if(WB_Aw<Aw)begin
99
                        $display("Error: The wishbon bus reserved address range width (%d) should be larger than ram width (%d): %m",WB_Aw,Aw);
100
                        $stop;
101
                end
102
         end
103
        // synthesis translate_on
104
 
105
 
106
 
107
        function integer log2;
108
        input integer number; begin
109
        log2=0;
110
        while(2**log2<number) begin
111
            log2=log2+1;
112
        end
113
        end
114
        endfunction // log2 
115
 
116
    function   [15:0]i2s;
117
    input   integer c;  integer i;  integer tmp; begin
118
    tmp =0;
119
    for (i=0; i<2; i=i+1'b1) begin
120
                        tmp =  tmp +    (((c % 10)   + 6'd48) << i*8);
121
                        c       =   c/10;
122
    end
123
    i2s = tmp[15:0];
124
    end
125
    endfunction //i2s
126
/* verilator lint_off WIDTH */
127
    localparam  BYTE_ENw= ( BYTE_WR_EN == "YES")? Dw/8 : 1;
128
/* verilator lint_on WIDTH */
129
 
130
 
131
        input                  clk;
132
        input                  reset;
133
 
134
 
135
 
136
 
137
     //wishbone bus interface
138
        input       [Dw-1       :   0]      sa_dat_i,sb_dat_i;
139
        input       [SELw-1     :   0]      sa_sel_i,sb_sel_i;
140
        input       [Aw-1       :   0]      sa_addr_i,sb_addr_i;
141
        input       [TAGw-1     :   0]      sa_tag_i,sb_tag_i;
142
        input                               sa_stb_i,sb_stb_i;
143
        input                               sa_cyc_i,sb_cyc_i;
144
        input                               sa_we_i,sb_we_i;
145
        input       [CTIw-1     :   0]      sa_cti_i,sb_cti_i;
146
        input       [BTEw-1     :   0]      sa_bte_i,sb_bte_i;
147
 
148
        output      [Dw-1       :   0]      sa_dat_o,sb_dat_o;
149
        output                              sa_ack_o,sb_ack_o;
150
        output                              sa_err_o,sb_err_o;
151
        output                              sa_rty_o,sb_rty_o;
152
 
153
 
154
 
155
 
156
 
157
 
158
    wire   [Dw-1   :   0]  data_a,data_b;
159
    wire   [Aw-1   :   0]  addr_a,addr_b;
160
    wire               we_a,we_b;
161
    wire   [Dw-1    :   0]  q_a,q_b;
162
 
163
 
164
`ifdef VERILATOR
165
        // The verilator does not recognize altsyncram, use Generic Ram instead
166
    localparam FPGA_VENDOR_MDFY= "GENERIC";
167
`else
168
    `ifdef MODEL_TECH
169
        localparam FPGA_VENDOR_MDFY= "GENERIC";
170
    `else
171
       localparam FPGA_VENDOR_MDFY= FPGA_VENDOR;
172
    `endif
173
`endif
174
 
175
    /* verilator lint_off WIDTH */
176
        localparam MEM_NAME =
177
       (FPGA_VENDOR_MDFY== "ALTERA")? {MEM_CONTENT_FILE_NAME,".mif"} :
178
       (FPGA_VENDOR_MDFY== "XILINX")? {MEM_CONTENT_FILE_NAME,".mem"} :
179
                            {MEM_CONTENT_FILE_NAME,".hex"}; //Generic
180
    /* verilator lint_on WIDTH */
181
 
182
    localparam [7:0] N1 = (CORE_NUM%10) + 48;
183
    localparam [7:0] N2 = ((CORE_NUM/10)%10) + 48;
184
    localparam [7:0] N3 = ((CORE_NUM/100)%10) + 48;
185
    localparam NN = (CORE_NUM<10) ? N1 : (CORE_NUM<100)? {N2,N1} : {N3,N2,N1};
186
 
187
    /* verilator lint_off WIDTH */
188
    localparam  INIT_FILE =
189
       (FPGA_VENDOR_MDFY== "XILINX")? {"tile",NN,MEM_NAME}:
190
       {INIT_FILE_PATH,"/RAM/",MEM_NAME};
191
    localparam  XILINX_INIT_FILE = (INITIAL_EN == "NO") ? "none" : INIT_FILE_PATH;
192
    localparam  ALTERA_INIT_FILE = (INITIAL_EN == "NO") ? "UNUSED" : INIT_FILE_PATH;
193
    /* verilator lint_on WIDTH */
194
 
195
 
196
 
197
    wb_bram_ctrl #(
198
        .Dw(Dw),
199
        .Aw(Aw),
200
        .BURST_MODE(PORT_A_BURST_MODE),
201
        .SELw(SELw),
202
        .CTIw(CTIw),
203
        .BTEw(BTEw)
204
    )
205
   ctrl_a
206
   (
207
        .clk(clk),
208
        .reset(reset),
209
        .d(data_a),
210
        .addr(addr_a),
211
        .we(we_a),
212
        .q(q_a),
213
        .byteena_a( ),
214
        .sa_dat_i(sa_dat_i),
215
        .sa_sel_i(sa_sel_i),
216
        .sa_addr_i(sa_addr_i),
217
        .sa_stb_i(sa_stb_i),
218
        .sa_cyc_i(sa_cyc_i),
219
        .sa_we_i(sa_we_i),
220
        .sa_cti_i(sa_cti_i),
221
        .sa_bte_i(sa_bte_i),
222
        .sa_dat_o(sa_dat_o),
223
        .sa_ack_o(sa_ack_o),
224
        .sa_err_o(sa_err_o),
225
        .sa_rty_o(sa_rty_o)
226
   );
227
 
228
 
229
    wb_bram_ctrl #(
230
        .Dw(Dw),
231
        .Aw(Aw),
232
        .BURST_MODE(PORT_B_BURST_MODE),
233
        .SELw(SELw),
234
        .CTIw(CTIw),
235
        .BTEw(BTEw)
236
    )
237
    ctrl_b
238
    (
239
        .clk(clk),
240
        .reset(reset),
241
        .d(data_b),
242
        .addr(addr_b),
243
        .we(we_b),
244
        .q(q_b),
245
        .byteena_a( ),
246
        .sa_dat_i(sb_dat_i),
247
        .sa_sel_i(sb_sel_i),
248
        .sa_addr_i(sb_addr_i),
249
        .sa_stb_i(sb_stb_i),
250
        .sa_cyc_i(sb_cyc_i),
251
        .sa_we_i(sb_we_i),
252
        .sa_cti_i(sb_cti_i),
253
        .sa_bte_i(sa_bte_i),
254
        .sa_dat_o(sb_dat_o),
255
        .sa_ack_o(sb_ack_o),
256
        .sa_err_o(sb_err_o),
257
        .sa_rty_o(sb_rty_o)
258
   );
259
 
260
 
261
 
262
    generate
263
    /* verilator lint_off WIDTH */
264
    if(FPGA_VENDOR_MDFY=="ALTERA")begin:altera_fpga
265
    /* verilator lint_on WIDTH */
266
        localparam  RAM_ID ={"ENABLE_RUNTIME_MOD=NO"};
267
         // aletra dual port ram 
268
                altsyncram #(
269
                        .operation_mode("BIDIR_DUAL_PORT"),
270
                        .address_reg_b("CLOCK0"),
271
                        .wrcontrol_wraddress_reg_b("CLOCK0"),
272
                        .indata_reg_b("CLOCK0"),
273
                        .outdata_reg_a("UNREGISTERED"),
274
                        .outdata_reg_b("UNREGISTERED"),
275
                        .width_a(Dw),
276
                        .width_b(Dw),
277
                        .lpm_hint(RAM_ID),
278
                        .read_during_write_mode_mixed_ports("DONT_CARE"),
279
                        .widthad_a(Aw),
280
                        .widthad_b(Aw),
281
                        .width_byteena_a(BYTE_ENw),
282
                        .init_file(ALTERA_INIT_FILE)
283
 
284
                ) ram_inst
285
                (
286
                        .clock0(clk),
287
                        .address_a(addr_a),
288
                        .wren_a(we_a),
289
                        .data_a(data_a),
290
                        .q_a(q_a),
291
                        .byteena_a(sa_sel_i),
292
 
293
                        .address_b(addr_b),
294
                        .wren_b(we_b),
295
                        .data_b(data_b),
296
                        .q_b(q_b),
297
                        .byteena_b(1'b1),
298
 
299
                        .rden_a(1'b1),
300
                        .rden_b(1'b1),
301
                        .clock1(1'b1),
302
                        .clocken0(1'b1),
303
                        .clocken1(1'b1),
304
                        .clocken2(1'b1),
305
                        .clocken3(1'b1),
306
                        .aclr0(1'b0),
307
                        .aclr1(1'b0),
308
                        .addressstall_a(1'b0),
309
                        .addressstall_b(1'b0),
310
                        .eccstatus(   )
311
 
312
                );
313
 
314
 
315
    end //altera_fpga
316
    /* verilator lint_off WIDTH */
317
    else if(FPGA_VENDOR_MDFY=="XILINX")begin:xilinx_ram
318
    /* verilator lint_on WIDTH */
319
        localparam MEMORY_SIZE = (2**Aw)*Dw;//total memory array size, in bits
320
        wire [BYTE_ENw-1   :   0] xilinx_we_a = (we_a)? sa_sel_i : {BYTE_ENw{1'b0}};
321
        wire [BYTE_ENw-1   :   0] xilinx_we_b = (we_b)? {BYTE_ENw{1'b1}} : {BYTE_ENw{1'b0}};
322
 
323
 
324
        xpm_memory_tdpram #(
325
          .ADDR_WIDTH_A(Aw),               // DECIMAL
326
          .ADDR_WIDTH_B(Aw),               // DECIMAL
327
          .AUTO_SLEEP_TIME(0),            // DECIMAL
328
          .BYTE_WRITE_WIDTH_A(8),        // DECIMAL
329
          .BYTE_WRITE_WIDTH_B(8),        // DECIMAL
330
          //.CASCADE_HEIGHT(0),             // DECIMAL
331
          .CLOCKING_MODE("common_clock"), // String
332
          .ECC_MODE("no_ecc"),            // String
333
          .MEMORY_INIT_FILE(XILINX_INIT_FILE),      // String
334
          .MEMORY_INIT_PARAM(""),        // String
335
          .MEMORY_OPTIMIZATION("true"),   // String
336
          .MEMORY_PRIMITIVE("auto"),      // String
337
          .MEMORY_SIZE(MEMORY_SIZE),             // DECIMAL
338
          .MESSAGE_CONTROL(0),            // DECIMAL
339
          .READ_DATA_WIDTH_A(Dw),         // DECIMAL
340
          .READ_DATA_WIDTH_B(Dw),         // DECIMAL
341
          .READ_LATENCY_A(1),             // DECIMAL
342
          .READ_LATENCY_B(1),             // DECIMAL
343
          .READ_RESET_VALUE_A("0"),       // String
344
          .READ_RESET_VALUE_B("0"),       // String
345
         // .RST_MODE_A("SYNC"),            // String
346
         // .RST_MODE_B("SYNC"),            // String
347
         // .SIM_ASSERT_CHK(0),             // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
348
          .USE_EMBEDDED_CONSTRAINT(0),    // DECIMAL
349
          .USE_MEM_INIT(1),               // DECIMAL
350
          .WAKEUP_TIME("disable_sleep"),  // String
351
          .WRITE_DATA_WIDTH_A(Dw),        // DECIMAL
352
          .WRITE_DATA_WIDTH_B(Dw),        // DECIMAL
353
          .WRITE_MODE_A("no_change"),     // String
354
          .WRITE_MODE_B("no_change")      // String
355
       )
356
       xpm_memory_tdpram_inst
357
       (
358
          .dbiterra( ),             // 1-bit output: Status signal to indicate double bit error occurrence
359
                                           // on the data output of port A.
360
 
361
          .dbiterrb( ),             // 1-bit output: Status signal to indicate double bit error occurrence
362
                                           // on the data output of port A.
363
 
364
          .douta(q_a),                   // READ_DATA_WIDTH_A-bit output: Data output for port A read operations.
365
          .doutb(q_b),                   // READ_DATA_WIDTH_B-bit output: Data output for port B read operations.
366
          .sbiterra( ),             // 1-bit output: Status signal to indicate single bit error occurrence
367
                                           // on the data output of port A.
368
 
369
          .sbiterrb( ),             // 1-bit output: Status signal to indicate single bit error occurrence
370
                                           // on the data output of port B.
371
 
372
          .addra(addr_a),                   // ADDR_WIDTH_A-bit input: Address for port A write and read operations.
373
          .addrb(addr_b),                   // ADDR_WIDTH_B-bit input: Address for port B write and read operations.
374
          .clka(clk),                     // 1-bit input: Clock signal for port A. Also clocks port B when
375
                                           // parameter CLOCKING_MODE is "common_clock".
376
 
377
          .clkb(clk),                     // 1-bit input: Clock signal for port B when parameter CLOCKING_MODE is
378
                                           // "independent_clock". Unused when parameter CLOCKING_MODE is
379
                                           // "common_clock".
380
 
381
          .dina(data_a),                     // WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations.
382
          .dinb(data_b),                     // WRITE_DATA_WIDTH_B-bit input: Data input for port B write operations.
383
          .ena(1'b1),                       // 1-bit input: Memory enable signal for port A. Must be high on clock
384
                                           // cycles when read or write operations are initiated. Pipelined
385
                                           // internally.
386
 
387
          .enb(1'b1),                       // 1-bit input: Memory enable signal for port B. Must be high on clock
388
                                           // cycles when read or write operations are initiated. Pipelined
389
                                           // internally.
390
 
391
          .injectdbiterra(1'b0), // 1-bit input: Controls double bit error injection on input data when
392
                                           // ECC enabled (Error injection capability is not available in
393
                                           // "decode_only" mode).
394
 
395
          .injectdbiterrb(1'b0), // 1-bit input: Controls double bit error injection on input data when
396
                                           // ECC enabled (Error injection capability is not available in
397
                                           // "decode_only" mode).
398
 
399
          .injectsbiterra(1'b0), // 1-bit input: Controls single bit error injection on input data when
400
                                           // ECC enabled (Error injection capability is not available in
401
                                           // "decode_only" mode).
402
 
403
          .injectsbiterrb(1'b0), // 1-bit input: Controls single bit error injection on input data when
404
                                           // ECC enabled (Error injection capability is not available in
405
                                           // "decode_only" mode).
406
 
407
          .regcea(1'b1),                 // 1-bit input: Clock Enable for the last register stage on the output
408
                                           // data path.
409
 
410
          .regceb(1'b1),                 // 1-bit input: Clock Enable for the last register stage on the output
411
                                           // data path.
412
 
413
          .rsta(reset),                     // 1-bit input: Reset signal for the final port A output register stage.
414
                                           // Synchronously resets output port douta to the value specified by
415
                                           // parameter READ_RESET_VALUE_A.
416
 
417
          .rstb(reset),                     // 1-bit input: Reset signal for the final port B output register stage.
418
                                           // Synchronously resets output port doutb to the value specified by
419
                                           // parameter READ_RESET_VALUE_B.
420
 
421
          .sleep(1'b0),                   // 1-bit input: sleep signal to enable the dynamic power saving feature.
422
          .wea(xilinx_we_a),                       // WRITE_DATA_WIDTH_A-bit input: Write enable vector for port A input
423
                                           // data port dina. 1 bit wide when word-wide writes are used. In
424
                                           // byte-wide write configurations, each bit controls the writing one
425
                                           // byte of dina to address addra. For example, to synchronously write
426
                                           // only bits [15-8] of dina when WRITE_DATA_WIDTH_A is 32, wea would be
427
                                           // 4'b0010.
428
 
429
          .web(xilinx_we_b)                        // WRITE_DATA_WIDTH_B-bit input: Write enable vector for port B input
430
                                           // data port dinb. 1 bit wide when word-wide writes are used. In
431
                                           // byte-wide write configurations, each bit controls the writing one
432
                                           // byte of dinb to address addrb. For example, to synchronously write
433
                                           // only bits [15-8] of dinb when WRITE_DATA_WIDTH_B is 32, web would be
434
                                           // 4'b0010.
435
 
436
       );
437
 
438
 
439
 
440
 
441
 
442
    end//
443
    /* verilator lint_off WIDTH */
444
    else if(FPGA_VENDOR_MDFY=="GENERIC")begin:generic_ram
445
    /* verilator lint_on WIDTH */
446
 
447
 
448
        generic_dual_port_ram #(
449
            .Dw(Dw),
450
            .Aw(Aw),
451
            .BYTE_WR_EN(BYTE_WR_EN),
452
                        .INITIAL_EN(INITIAL_EN),
453
                        .INIT_FILE(INIT_FILE)
454
        )
455
        ram_inst
456
        (
457
            .data_a(data_a),
458
                .data_b(data_b),
459
                .addr_a(addr_a),
460
                .addr_b(addr_b),
461
                .byteena_a(sa_sel_i),
462
                .byteena_b({BYTE_ENw{1'b1}}),
463
                .we_a(we_a),
464
                .we_b(we_b),
465
                .clk(clk),
466
                .q_a(q_a),
467
                .q_b(q_b)
468
 
469
        );
470
 
471
    end //Generic
472
 
473
 
474
    endgenerate
475
 
476
 
477
 
478
endmodule
479
 
480
 
481
 
482
 
483
 
484
 
485
 
486
 
487
 
488
 

powered by: WebSVN 2.1.0

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