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