1
+
2
+ // Xilinx True Dual Port RAM, Read First, Dual Clock
3
+ // This code implements a parameterizable true dual port memory (both ports can read and write).
4
+ // The behavior of this RAM is when data is written, the prior memory contents at the write
5
+ // address are presented on the output port. If the output data is
6
+ // not needed during writes or the last read value is desired to be retained,
7
+ // it is suggested to use a no change RAM as it is more power efficient.
8
+ // If a reset or enable is not necessary, it may be tied off or removed from the code.
9
+
10
+ module xilinx_true_dual_port_read_first_2_clock_ram #(
11
+ parameter RAM_WIDTH = 18 , // Specify RAM data width
12
+ parameter RAM_DEPTH = 1024 , // Specify RAM depth (number of entries)
13
+ parameter RAM_PERFORMANCE = "HIGH_PERFORMANCE" , // Select "HIGH_PERFORMANCE" or "LOW_LATENCY"
14
+ parameter INIT_FILE = "" // Specify name/location of RAM initialization file if using one (leave blank if not)
15
+ ) (
16
+ input [clogb2(RAM_DEPTH- 1 )- 1 :0 ] addra, // Port A address bus, width determined from RAM_DEPTH
17
+ input [clogb2(RAM_DEPTH- 1 )- 1 :0 ] addrb, // Port B address bus, width determined from RAM_DEPTH
18
+ input [RAM_WIDTH- 1 :0 ] dina, // Port A RAM input data
19
+ input [RAM_WIDTH- 1 :0 ] dinb, // Port B RAM input data
20
+ input clka, // Port A clock
21
+ input clkb, // Port B clock
22
+ input wea, // Port A write enable
23
+ input web, // Port B write enable
24
+ input ena, // Port A RAM Enable, for additional power savings, disable port when not in use
25
+ input enb, // Port B RAM Enable, for additional power savings, disable port when not in use
26
+ input rsta, // Port A output reset (does not affect memory contents)
27
+ input rstb, // Port B output reset (does not affect memory contents)
28
+ input regcea, // Port A output register enable
29
+ input regceb, // Port B output register enable
30
+ output [RAM_WIDTH- 1 :0 ] douta, // Port A RAM output data
31
+ output [RAM_WIDTH- 1 :0 ] doutb // Port B RAM output data
32
+ );
33
+
34
+ reg [RAM_WIDTH- 1 :0 ] BRAM [RAM_DEPTH- 1 :0 ];
35
+ reg [RAM_WIDTH- 1 :0 ] ram_data_a = {RAM_WIDTH{1'b0 }};
36
+ reg [RAM_WIDTH- 1 :0 ] ram_data_b = {RAM_WIDTH{1'b0 }};
37
+
38
+ // The following code either initializes the memory values to a specified file or to all zeros to match hardware
39
+ generate
40
+ if (INIT_FILE != "" ) begin : use_init_file
41
+ initial
42
+ $readmemh (INIT_FILE, BRAM, 0 , RAM_DEPTH- 1 );
43
+ end else begin : init_bram_to_zero
44
+ integer ram_index;
45
+ initial
46
+ for (ram_index = 0 ; ram_index < RAM_DEPTH; ram_index = ram_index + 1 )
47
+ BRAM[ram_index] = {RAM_WIDTH{1'b0 }};
48
+ end
49
+ endgenerate
50
+
51
+ always @(posedge clka)
52
+ if (ena) begin
53
+ if (wea)
54
+ BRAM[addra] <= dina;
55
+ ram_data_a <= BRAM[addra];
56
+ end
57
+
58
+ always @(posedge clkb)
59
+ if (enb) begin
60
+ if (web)
61
+ BRAM[addrb] <= dinb;
62
+ ram_data_b <= BRAM[addrb];
63
+ end
64
+
65
+ // The following code generates HIGH_PERFORMANCE (use output register) or LOW_LATENCY (no output register)
66
+ generate
67
+ if (RAM_PERFORMANCE == "LOW_LATENCY" ) begin : no_output_register
68
+
69
+ // The following is a 1 clock cycle read latency at the cost of a longer clock-to-out timing
70
+ assign douta = ram_data_a;
71
+ assign doutb = ram_data_b;
72
+
73
+ end else begin : output_register
74
+
75
+ // The following is a 2 clock cycle read latency with improve clock-to-out timing
76
+
77
+ reg [RAM_WIDTH- 1 :0 ] douta_reg = {RAM_WIDTH{1'b0 }};
78
+ reg [RAM_WIDTH- 1 :0 ] doutb_reg = {RAM_WIDTH{1'b0 }};
79
+
80
+ always @(posedge clka)
81
+ if (rsta)
82
+ douta_reg <= {RAM_WIDTH{1'b0 }};
83
+ else if (regcea)
84
+ douta_reg <= ram_data_a;
85
+
86
+ always @(posedge clkb)
87
+ if (rstb)
88
+ doutb_reg <= {RAM_WIDTH{1'b0 }};
89
+ else if (regceb)
90
+ doutb_reg <= ram_data_b;
91
+
92
+ assign douta = douta_reg;
93
+ assign doutb = doutb_reg;
94
+
95
+ end
96
+ endgenerate
97
+
98
+ // The following function calculates the address width based on specified RAM depth
99
+ function integer clogb2;
100
+ input integer depth;
101
+ for (clogb2= 0 ; depth> 0 ; clogb2= clogb2+ 1 )
102
+ depth = depth >> 1 ;
103
+ endfunction
104
+
105
+ endmodule
106
+
107
+ // The following is an instantiation template for xilinx_true_dual_port_read_first_2_clock_ram
108
+ /*
109
+ // Xilinx True Dual Port RAM, Read First, Dual Clock
110
+ xilinx_true_dual_port_read_first_2_clock_ram #(
111
+ .RAM_WIDTH(18), // Specify RAM data width
112
+ .RAM_DEPTH(1024), // Specify RAM depth (number of entries)
113
+ .RAM_PERFORMANCE("HIGH_PERFORMANCE"), // Select "HIGH_PERFORMANCE" or "LOW_LATENCY"
114
+ .INIT_FILE("") // Specify name/location of RAM initialization file if using one (leave blank if not)
115
+ ) your_instance_name (
116
+ .addra(addra), // Port A address bus, width determined from RAM_DEPTH
117
+ .addrb(addrb), // Port B address bus, width determined from RAM_DEPTH
118
+ .dina(dina), // Port A RAM input data, width determined from RAM_WIDTH
119
+ .dinb(dinb), // Port B RAM input data, width determined from RAM_WIDTH
120
+ .clka(clka), // Port A clock
121
+ .clkb(clkb), // Port B clock
122
+ .wea(wea), // Port A write enable
123
+ .web(web), // Port B write enable
124
+ .ena(ena), // Port A RAM Enable, for additional power savings, disable port when not in use
125
+ .enb(enb), // Port B RAM Enable, for additional power savings, disable port when not in use
126
+ .rsta(rsta), // Port A output reset (does not affect memory contents)
127
+ .rstb(rstb), // Port B output reset (does not affect memory contents)
128
+ .regcea(regcea), // Port A output register enable
129
+ .regceb(regceb), // Port B output register enable
130
+ .douta(douta), // Port A RAM output data, width determined from RAM_WIDTH
131
+ .douta(douta) // Port B RAM output data, width determined from RAM_WIDTH
132
+ );
133
+ */
134
+
135
+
0 commit comments