-
Notifications
You must be signed in to change notification settings - Fork 399
/
Copy pathtrue_dual_port_write_first_2_clock_ram.sv
executable file
·123 lines (100 loc) · 3.02 KB
/
true_dual_port_write_first_2_clock_ram.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//------------------------------------------------------------------------------
// true_dual_port_write_first_2_clock_ram.sv
// published as part of https://github.com/pConst/basic_verilog
// Konstantin Pavlov, [email protected]
//------------------------------------------------------------------------------
// INFO ------------------------------------------------------------------------
// This is originally a Vivado template for block RAM with some minor edits
// Also tested for Quartus IDE to automatically infer block memories
//
/* --- INSTANTIATION TEMPLATE BEGIN ---
true_dual_port_write_first_2_clock_ram #(
.RAM_WIDTH( DATA_W ),
.RAM_DEPTH( DEPTH ),
.RAM_STYLE( "block" ), // "block","register","M10K","logic",...
.INIT_FILE( "init.mem" )
) DR1 (
.clka( w_clk ),
.addra( w_ptr[DEPTH_W-1:0] ),
.ena( w_req ),
.wea( 1'b1 ),
.dina( w_data[DATA_W-1:0] ),
.douta( ),
.clkb( r_clk ),
.addrb( r_ptr[DEPTH_W-1:0] ),
.enb( r_req ),
.web( 1'b0 ),
.dinb( '0 ),
.doutb( r_data[DATA_W-1:0] )
);
--- INSTANTIATION TEMPLATE END ---*/
module true_dual_port_write_first_2_clock_ram #( parameter
RAM_WIDTH = 16,
RAM_DEPTH = 8,
// optional initialization parameters
RAM_STYLE = "block",
INIT_FILE = ""
)(
input clka,
input [clogb2(RAM_DEPTH-1)-1:0] addra,
input ena,
input wea,
input [RAM_WIDTH-1:0] dina,
output [RAM_WIDTH-1:0] douta,
input clkb,
input [clogb2(RAM_DEPTH-1)-1:0] addrb,
input enb,
input web,
input [RAM_WIDTH-1:0] dinb,
output [RAM_WIDTH-1:0] doutb
);
// Xilinx:
// ram_style = "{ auto | block | distributed | register | ultra }"
// "ram_style" is equivalent to "ramstyle" in Vivado
// Altera:
// ramstyle = "{ logic | M9K | MLAB }" and other variants
// ONLY FOR QUARTUS IDE
// You can provide initialization in convinient .mif format
//(* ram_init_file = INIT_FILE *) logic [RAM_WIDTH-1:0] data_mem [RAM_DEPTH-1:0];
(* ramstyle = RAM_STYLE *) logic [RAM_WIDTH-1:0] data_mem [RAM_DEPTH-1:0];
logic [RAM_WIDTH-1:0] ram_data_a = {RAM_WIDTH{1'b0}};
logic [RAM_WIDTH-1:0] ram_data_b = {RAM_WIDTH{1'b0}};
// either initializes the memory values to a specified file or to all zeros
generate
if (INIT_FILE != "") begin: use_init_file
initial
$readmemh(INIT_FILE, data_mem, 0, RAM_DEPTH-1);
end else begin: init_bram_to_zero
integer i;
initial begin
for (i=0; i<RAM_DEPTH; i=i+1 ) begin
data_mem[i] = {RAM_WIDTH{1'b0}};
end
end
end
endgenerate
always @(posedge clka) begin
if (ena) begin
if (wea) begin
data_mem[addra] <= dina;
ram_data_a <= dina;
end else begin
ram_data_a <= data_mem[addra];
end
end
end
always @(posedge clkb) begin
if (enb) begin
if (web) begin
data_mem[addrb] <= dinb;
ram_data_b <= dinb;
end else begin
ram_data_b <= data_mem[addrb];
end
end
end
// no output register
assign douta = ram_data_a;
assign doutb = ram_data_b;
`include "clogb2.svh"
endmodule