lm32_ram.v

Sun, 04 Apr 2010 22:05:07 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 04 Apr 2010 22:05:07 +0100
changeset 3
b153470d41c5
parent 2
a61bb364ae1f
permissions
-rw-r--r--

remove more Lattice-specific fluff

Code now synthesizes properly on Altera Quartus 9.0 build 235

     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 `ifdef PLATFORM_LATTICE
    62    parameter RAM_IMPLEMENTATION = "AUTO";  // Implement memory in EBRs, else
    63                                            // let synthesis tool select best 
    64                                            // possible solution (EBR or LUT)
    65    parameter RAM_TYPE = "RAM_DP";          // Type of EBR to be used
    66 `endif
    68    /*----------------------------------------------------------------------
    69     Inputs
    70     ----------------------------------------------------------------------*/
    71    input read_clk;                         // Read clock
    72    input write_clk;                        // Write clock
    73    input reset;                            // Reset
    75    input enable_read;                      // Access enable
    76    input [address_width-1:0] read_address; // Read/write address
    77    input enable_write;                     // Access enable
    78    input [address_width-1:0] write_address;// Read/write address
    79    input [data_width-1:0] write_data;      // Data to write to specified address
    80    input write_enable;                     // Write enable
    82    /*----------------------------------------------------------------------
    83     Outputs
    84     ----------------------------------------------------------------------*/
    85    output [data_width-1:0] read_data;      // Data read from specified addess
    86    wire   [data_width-1:0] read_data;
    88 `ifdef PLATFORM_LATTICE
    89    generate
    91       if ( RAM_IMPLEMENTATION == "EBR" )
    92 	begin
    93 	   if ( RAM_TYPE == "RAM_DP" )
    94 	     begin
    95 		pmi_ram_dp 
    96 		  #( 
    97 		     // ----- Parameters -----
    98 		     .pmi_wr_addr_depth(1<<address_width),
    99 		     .pmi_wr_addr_width(address_width),
   100 		     .pmi_wr_data_width(data_width),
   101 		     .pmi_rd_addr_depth(1<<address_width),
   102 		     .pmi_rd_addr_width(address_width),
   103 		     .pmi_rd_data_width(data_width),
   104 		     .pmi_regmode("noreg"),
   105 		     .pmi_gsr("enable"),
   106 		     .pmi_resetmode("sync"),
   107 		     .pmi_init_file("none"),
   108 		     .pmi_init_file_format("binary"),
   109 		     .pmi_family(`LATTICE_FAMILY),
   110 		     .module_type("pmi_ram_dp")
   111 		     )
   112 		lm32_ram_inst
   113 		  (
   114 		   // ----- Inputs -----
   115 		   .Data(write_data),
   116 		   .WrAddress(write_address),
   117 		   .RdAddress(read_address),
   118 		   .WrClock(write_clk),
   119 		   .RdClock(read_clk),
   120 		   .WrClockEn(enable_write),
   121 		   .RdClockEn(enable_read),
   122 		   .WE(write_enable),
   123 		   .Reset(reset),
   124 		   // ----- Outputs -----
   125 		   .Q(read_data)
   126 		   );
   127 	     end
   128 	   else
   129 	     begin
   130 		// True Dual-Port EBR
   131 		wire   [data_width-1:0] read_data_A, read_data_B;
   132 		reg [data_width-1:0] 	raw_data, raw_data_nxt;
   133 		reg 			raw, raw_nxt;
   135 		/*----------------------------------------------------------------------
   136 		 Is a read being performed in the same cycle as a write? Indicate this
   137 		 event with a RAW hazard signal that is released only when a new read
   138 		 or write occurs later.
   139 		 ----------------------------------------------------------------------*/
   140 		always @(/*AUTOSENSE*/enable_read or enable_write
   141 			 or raw or raw_data or read_address
   142 			 or write_address or write_data
   143 			 or write_enable)
   144 		  if (// Read
   145 		      enable_read
   146 		      // Write
   147 		      && enable_write && write_enable
   148 		      // Read and write address match
   149 		      && (read_address == write_address))
   150 		    begin
   151 		       raw_data_nxt = write_data;
   152 		       raw_nxt = 1'b1;
   153 		    end
   154 		  else
   155 		    if (raw && (enable_read == 1'b0) && (enable_write == 1'b0))
   156 		      begin
   157 			 raw_data_nxt = raw_data;
   158 			 raw_nxt = 1'b1;
   159 		      end
   160 		    else
   161 		      begin
   162 			 raw_data_nxt = raw_data;
   163 			 raw_nxt = 1'b0;
   164 		      end
   166 		// Send back write data in case of a RAW hazard; else send back
   167 		// data from memory
   168 		assign read_data = raw ? raw_data : read_data_B;
   170 		/*----------------------------------------------------------------------
   171 		 Sequential Logic
   172 		 ----------------------------------------------------------------------*/
   173 		always @(posedge read_clk)
   174 		  if (reset)
   175 		    begin
   176 		       raw_data <= #1 0;
   177 		       raw <= #1 1'b0;
   178 		    end
   179 		  else
   180 		    begin
   181 		       raw_data <= #1 raw_data_nxt;
   182 		       raw <= #1 raw_nxt;
   183 		    end
   185 		pmi_ram_dp_true 
   186 		  #( 
   187 		     // ----- Parameters -----
   188 		     .pmi_addr_depth_a(1<<address_width),
   189 		     .pmi_addr_width_a(address_width),
   190 		     .pmi_data_width_a(data_width),
   191 		     .pmi_addr_depth_b(1<<address_width),
   192 		     .pmi_addr_width_b(address_width),
   193 		     .pmi_data_width_b(data_width),
   194 		     .pmi_regmode_a("noreg"),
   195 		     .pmi_regmode_b("noreg"),
   196 		     .pmi_gsr("enable"),
   197 		     .pmi_resetmode("sync"),
   198 		     .pmi_init_file("none"),
   199 		     .pmi_init_file_format("binary"),
   200 		     .pmi_family(`LATTICE_FAMILY),
   201 		     .module_type("pmi_ram_dp_true")
   202 		     )
   203 		lm32_ram_inst
   204 		  (
   205 		   // ----- Inputs -----
   206 		   .DataInA(write_data),
   207 		   .DataInB(write_data),
   208 		   .AddressA(write_address),
   209 		   .AddressB(read_address),
   210 		   .ClockA(write_clk),
   211 		   .ClockB(read_clk),
   212 		   .ClockEnA(enable_write),
   213 		   .ClockEnB(enable_read),
   214 		   .WrA(write_enable),
   215 		   .WrB(`FALSE),
   216 		   .ResetA(reset),
   217 		   .ResetB(reset),
   218 		   // ----- Outputs -----
   219 		   .QA(read_data_A),
   220 		   .QB(read_data_B)
   221 		   );
   222 	     end
   223 	end
   224 	else if ( RAM_IMPLEMENTATION == "SLICE" )
   225 	  begin
   226 	     reg [address_width-1:0] ra; // Registered read address
   228 	     pmi_distributed_dpram 
   229 	       #(
   230 		 // ----- Parameters -----
   231 		 .pmi_addr_depth(1<<address_width),
   232 		 .pmi_addr_width(address_width),
   233 		 .pmi_data_width(data_width),
   234 		 .pmi_regmode("noreg"),
   235 		 .pmi_init_file("none"),
   236 		 .pmi_init_file_format("binary"),
   237 		 .pmi_family(`LATTICE_FAMILY),
   238 		 .module_type("pmi_distributed_dpram")
   239 		 )
   240 	     pmi_distributed_dpram_inst
   241 	       (
   242 		// ----- Inputs -----
   243 		.WrAddress(write_address),
   244 		.Data(write_data),
   245 		.WrClock(write_clk),
   246 		.WE(write_enable),
   247 		.WrClockEn(enable_write),
   248 		.RdAddress(ra),
   249 		.RdClock(read_clk),
   250 		.RdClockEn(enable_read),
   251 		.Reset(reset),
   252 		// ----- Outputs -----
   253 		.Q(read_data)
   254 		);
   256 	     always @(posedge read_clk)
   257 	       if (enable_read)
   258 		 ra <= read_address;
   259 	  end
   261 	else 
   262 	  begin
   263 `endif
   264 	     /*----------------------------------------------------------------------
   265 	      Internal nets and registers
   266 	      ----------------------------------------------------------------------*/
   267 	     reg [data_width-1:0]    mem[0:(1<<address_width)-1]; // The RAM
   268 	     reg [address_width-1:0] ra; // Registered read address
   270 	     /*----------------------------------------------------------------------
   271 	      Combinational Logic
   272 	      ----------------------------------------------------------------------*/
   273 	     // Read port
   274 	     assign read_data = mem[ra]; 
   276 	     /*----------------------------------------------------------------------
   277 	      Sequential Logic
   278 	      ----------------------------------------------------------------------*/
   279 	     // Write port
   280 	     always @(posedge write_clk)
   281 	       if ((write_enable == `TRUE) && (enable_write == `TRUE))
   282 		 mem[write_address] <= write_data; 
   284 	     // Register read address for use on next cycle
   285 	     always @(posedge read_clk)
   286 	       if (enable_read)
   287 		 ra <= read_address;
   289 `ifdef PLATFORM_LATTICE
   290 	  end
   292    endgenerate
   293 `endif
   294 endmodule