Sun, 04 Apr 2010 20:40:03 +0100
add lm32 source
1 // =============================================================================
2 // COPYRIGHT NOTICE
3 // Copyright 2006 (c) Lattice Semiconductor Corporation
4 // ALL RIGHTS RESERVED
5 // This confidential and proprietary software may be used only as authorised by
6 // a licensing agreement from Lattice Semiconductor Corporation.
7 // The entire notice above must be reproduced on all authorized copies and
8 // copies may only be made to the extent permitted by a licensing agreement from
9 // Lattice Semiconductor Corporation.
10 //
11 // Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
12 // 5555 NE Moore Court 408-826-6000 (other locations)
13 // Hillsboro, OR 97124 web : http://www.latticesemi.com/
14 // U.S.A email: techsupport@latticesemi.com
15 // =============================================================================/
16 // FILE DETAILS
17 // Project : LatticeMico32
18 // File : lm32_ram.v
19 // Title : Pseudo dual-port RAM.
20 // Version : 6.1.17
21 // : Initial Release
22 // Version : 7.0SP2, 3.0
23 // : No Change
24 // Version : 3.1
25 // : Options added to select EBRs (True-DP, Psuedo-DP, DQ, or
26 // : Distributed RAM).
27 // Version : 3.2
28 // : EBRs use SYNC resets instead of ASYNC resets.
29 // Version : 3.5
30 // : Added read-after-write hazard resolution when using true
31 // : dual-port EBRs
32 // =============================================================================
34 `include "lm32_include.v"
36 /////////////////////////////////////////////////////
37 // Module interface
38 /////////////////////////////////////////////////////
40 module lm32_ram
41 (
42 // ----- Inputs -------
43 read_clk,
44 write_clk,
45 reset,
46 enable_read,
47 read_address,
48 enable_write,
49 write_address,
50 write_data,
51 write_enable,
52 // ----- Outputs -------
53 read_data
54 );
56 /*----------------------------------------------------------------------
57 Parameters
58 ----------------------------------------------------------------------*/
59 parameter data_width = 1; // Width of the data ports
60 parameter address_width = 1; // Width of the address ports
61 parameter RAM_IMPLEMENTATION = "AUTO"; // Implement memory in EBRs, else
62 // let synthesis tool select best
63 // possible solution (EBR or LUT)
64 parameter RAM_TYPE = "RAM_DP"; // Type of EBR to be used
66 /*----------------------------------------------------------------------
67 Inputs
68 ----------------------------------------------------------------------*/
69 input read_clk; // Read clock
70 input write_clk; // Write clock
71 input reset; // Reset
73 input enable_read; // Access enable
74 input [address_width-1:0] read_address; // Read/write address
75 input enable_write; // Access enable
76 input [address_width-1:0] write_address;// Read/write address
77 input [data_width-1:0] write_data; // Data to write to specified address
78 input write_enable; // Write enable
80 /*----------------------------------------------------------------------
81 Outputs
82 ----------------------------------------------------------------------*/
83 output [data_width-1:0] read_data; // Data read from specified addess
84 wire [data_width-1:0] read_data;
86 generate
88 if ( RAM_IMPLEMENTATION == "EBR" )
89 begin
90 if ( RAM_TYPE == "RAM_DP" )
91 begin
92 pmi_ram_dp
93 #(
94 // ----- Parameters -----
95 .pmi_wr_addr_depth(1<<address_width),
96 .pmi_wr_addr_width(address_width),
97 .pmi_wr_data_width(data_width),
98 .pmi_rd_addr_depth(1<<address_width),
99 .pmi_rd_addr_width(address_width),
100 .pmi_rd_data_width(data_width),
101 .pmi_regmode("noreg"),
102 .pmi_gsr("enable"),
103 .pmi_resetmode("sync"),
104 .pmi_init_file("none"),
105 .pmi_init_file_format("binary"),
106 .pmi_family(`LATTICE_FAMILY),
107 .module_type("pmi_ram_dp")
108 )
109 lm32_ram_inst
110 (
111 // ----- Inputs -----
112 .Data(write_data),
113 .WrAddress(write_address),
114 .RdAddress(read_address),
115 .WrClock(write_clk),
116 .RdClock(read_clk),
117 .WrClockEn(enable_write),
118 .RdClockEn(enable_read),
119 .WE(write_enable),
120 .Reset(reset),
121 // ----- Outputs -----
122 .Q(read_data)
123 );
124 end
125 else
126 begin
127 // True Dual-Port EBR
128 wire [data_width-1:0] read_data_A, read_data_B;
129 reg [data_width-1:0] raw_data, raw_data_nxt;
130 reg raw, raw_nxt;
132 /*----------------------------------------------------------------------
133 Is a read being performed in the same cycle as a write? Indicate this
134 event with a RAW hazard signal that is released only when a new read
135 or write occurs later.
136 ----------------------------------------------------------------------*/
137 always @(/*AUTOSENSE*/enable_read or enable_write
138 or raw or raw_data or read_address
139 or write_address or write_data
140 or write_enable)
141 if (// Read
142 enable_read
143 // Write
144 && enable_write && write_enable
145 // Read and write address match
146 && (read_address == write_address))
147 begin
148 raw_data_nxt = write_data;
149 raw_nxt = 1'b1;
150 end
151 else
152 if (raw && (enable_read == 1'b0) && (enable_write == 1'b0))
153 begin
154 raw_data_nxt = raw_data;
155 raw_nxt = 1'b1;
156 end
157 else
158 begin
159 raw_data_nxt = raw_data;
160 raw_nxt = 1'b0;
161 end
163 // Send back write data in case of a RAW hazard; else send back
164 // data from memory
165 assign read_data = raw ? raw_data : read_data_B;
167 /*----------------------------------------------------------------------
168 Sequential Logic
169 ----------------------------------------------------------------------*/
170 always @(posedge read_clk)
171 if (reset)
172 begin
173 raw_data <= #1 0;
174 raw <= #1 1'b0;
175 end
176 else
177 begin
178 raw_data <= #1 raw_data_nxt;
179 raw <= #1 raw_nxt;
180 end
182 pmi_ram_dp_true
183 #(
184 // ----- Parameters -----
185 .pmi_addr_depth_a(1<<address_width),
186 .pmi_addr_width_a(address_width),
187 .pmi_data_width_a(data_width),
188 .pmi_addr_depth_b(1<<address_width),
189 .pmi_addr_width_b(address_width),
190 .pmi_data_width_b(data_width),
191 .pmi_regmode_a("noreg"),
192 .pmi_regmode_b("noreg"),
193 .pmi_gsr("enable"),
194 .pmi_resetmode("sync"),
195 .pmi_init_file("none"),
196 .pmi_init_file_format("binary"),
197 .pmi_family(`LATTICE_FAMILY),
198 .module_type("pmi_ram_dp_true")
199 )
200 lm32_ram_inst
201 (
202 // ----- Inputs -----
203 .DataInA(write_data),
204 .DataInB(write_data),
205 .AddressA(write_address),
206 .AddressB(read_address),
207 .ClockA(write_clk),
208 .ClockB(read_clk),
209 .ClockEnA(enable_write),
210 .ClockEnB(enable_read),
211 .WrA(write_enable),
212 .WrB(`FALSE),
213 .ResetA(reset),
214 .ResetB(reset),
215 // ----- Outputs -----
216 .QA(read_data_A),
217 .QB(read_data_B)
218 );
219 end
220 end
221 else if ( RAM_IMPLEMENTATION == "SLICE" )
222 begin
223 reg [address_width-1:0] ra; // Registered read address
225 pmi_distributed_dpram
226 #(
227 // ----- Parameters -----
228 .pmi_addr_depth(1<<address_width),
229 .pmi_addr_width(address_width),
230 .pmi_data_width(data_width),
231 .pmi_regmode("noreg"),
232 .pmi_init_file("none"),
233 .pmi_init_file_format("binary"),
234 .pmi_family(`LATTICE_FAMILY),
235 .module_type("pmi_distributed_dpram")
236 )
237 pmi_distributed_dpram_inst
238 (
239 // ----- Inputs -----
240 .WrAddress(write_address),
241 .Data(write_data),
242 .WrClock(write_clk),
243 .WE(write_enable),
244 .WrClockEn(enable_write),
245 .RdAddress(ra),
246 .RdClock(read_clk),
247 .RdClockEn(enable_read),
248 .Reset(reset),
249 // ----- Outputs -----
250 .Q(read_data)
251 );
253 always @(posedge read_clk)
254 if (enable_read)
255 ra <= read_address;
256 end
258 else
259 begin
260 /*----------------------------------------------------------------------
261 Internal nets and registers
262 ----------------------------------------------------------------------*/
263 reg [data_width-1:0] mem[0:(1<<address_width)-1]; // The RAM
264 reg [address_width-1:0] ra; // Registered read address
266 /*----------------------------------------------------------------------
267 Combinational Logic
268 ----------------------------------------------------------------------*/
269 // Read port
270 assign read_data = mem[ra];
272 /*----------------------------------------------------------------------
273 Sequential Logic
274 ----------------------------------------------------------------------*/
275 // Write port
276 always @(posedge write_clk)
277 if ((write_enable == `TRUE) && (enable_write == `TRUE))
278 mem[write_address] <= write_data;
280 // Register read address for use on next cycle
281 always @(posedge read_clk)
282 if (enable_read)
283 ra <= read_address;
285 end
287 endgenerate
289 endmodule