lm32_ram.v

Mon, 05 Apr 2010 21:00:31 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 05 Apr 2010 21:00:31 +0100
changeset 6
a8e459b24c31
parent 2
a61bb364ae1f
permissions
-rw-r--r--

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