lm32_ram.v

Sat, 06 Aug 2011 01:26:56 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 06 Aug 2011 01:26:56 +0100
changeset 27
d6c693415d59
parent 26
73de224304c1
permissions
-rwxr-xr-x

remove synthesis delay entities to ease merge

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