lm32_ram.v

changeset 0
cd0b58aa6f83
child 2
a61bb364ae1f
child 26
73de224304c1
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/lm32_ram.v	Sun Apr 04 20:40:03 2010 +0100
     1.3 @@ -0,0 +1,289 @@
     1.4 +// =============================================================================
     1.5 +//                           COPYRIGHT NOTICE
     1.6 +// Copyright 2006 (c) Lattice Semiconductor Corporation
     1.7 +// ALL RIGHTS RESERVED
     1.8 +// This confidential and proprietary software may be used only as authorised by
     1.9 +// a licensing agreement from Lattice Semiconductor Corporation.
    1.10 +// The entire notice above must be reproduced on all authorized copies and
    1.11 +// copies may only be made to the extent permitted by a licensing agreement from
    1.12 +// Lattice Semiconductor Corporation.
    1.13 +//
    1.14 +// Lattice Semiconductor Corporation        TEL : 1-800-Lattice (USA and Canada)
    1.15 +// 5555 NE Moore Court                            408-826-6000 (other locations)
    1.16 +// Hillsboro, OR 97124                     web  : http://www.latticesemi.com/
    1.17 +// U.S.A                                   email: techsupport@latticesemi.com
    1.18 +// =============================================================================/
    1.19 +//                         FILE DETAILS
    1.20 +// Project          : LatticeMico32
    1.21 +// File             : lm32_ram.v
    1.22 +// Title            : Pseudo dual-port RAM.
    1.23 +// Version          : 6.1.17
    1.24 +//                  : Initial Release
    1.25 +// Version          : 7.0SP2, 3.0
    1.26 +//                  : No Change
    1.27 +// Version          : 3.1
    1.28 +//                  : Options added to select EBRs (True-DP, Psuedo-DP, DQ, or
    1.29 +//                  : Distributed RAM).
    1.30 +// Version          : 3.2
    1.31 +//                  : EBRs use SYNC resets instead of ASYNC resets.
    1.32 +// Version          : 3.5
    1.33 +//                  : Added read-after-write hazard resolution when using true
    1.34 +//                  : dual-port EBRs
    1.35 +// =============================================================================
    1.36 +
    1.37 +`include "lm32_include.v"
    1.38 +
    1.39 +/////////////////////////////////////////////////////
    1.40 +// Module interface
    1.41 +/////////////////////////////////////////////////////
    1.42 +
    1.43 +module lm32_ram 
    1.44 +  (
    1.45 +   // ----- Inputs -------
    1.46 +   read_clk,
    1.47 +   write_clk,
    1.48 +   reset,
    1.49 +   enable_read,
    1.50 +   read_address,
    1.51 +   enable_write,
    1.52 +   write_address,
    1.53 +   write_data,
    1.54 +   write_enable,
    1.55 +   // ----- Outputs -------
    1.56 +   read_data
    1.57 +   );
    1.58 +   
    1.59 +   /*----------------------------------------------------------------------
    1.60 +    Parameters
    1.61 +    ----------------------------------------------------------------------*/
    1.62 +   parameter data_width = 1;               // Width of the data ports
    1.63 +   parameter address_width = 1;            // Width of the address ports
    1.64 +   parameter RAM_IMPLEMENTATION = "AUTO";  // Implement memory in EBRs, else
    1.65 +                                           // let synthesis tool select best 
    1.66 +                                           // possible solution (EBR or LUT)
    1.67 +   parameter RAM_TYPE = "RAM_DP";          // Type of EBR to be used
    1.68 +   
    1.69 +   /*----------------------------------------------------------------------
    1.70 +    Inputs
    1.71 +    ----------------------------------------------------------------------*/
    1.72 +   input read_clk;                         // Read clock
    1.73 +   input write_clk;                        // Write clock
    1.74 +   input reset;                            // Reset
    1.75 +   
    1.76 +   input enable_read;                      // Access enable
    1.77 +   input [address_width-1:0] read_address; // Read/write address
    1.78 +   input enable_write;                     // Access enable
    1.79 +   input [address_width-1:0] write_address;// Read/write address
    1.80 +   input [data_width-1:0] write_data;      // Data to write to specified address
    1.81 +   input write_enable;                     // Write enable
    1.82 +   
    1.83 +   /*----------------------------------------------------------------------
    1.84 +    Outputs
    1.85 +    ----------------------------------------------------------------------*/
    1.86 +   output [data_width-1:0] read_data;      // Data read from specified addess
    1.87 +   wire   [data_width-1:0] read_data;
    1.88 +   
    1.89 +   generate
    1.90 +      
    1.91 +      if ( RAM_IMPLEMENTATION == "EBR" )
    1.92 +	begin
    1.93 +	   if ( RAM_TYPE == "RAM_DP" )
    1.94 +	     begin
    1.95 +		pmi_ram_dp 
    1.96 +		  #( 
    1.97 +		     // ----- Parameters -----
    1.98 +		     .pmi_wr_addr_depth(1<<address_width),
    1.99 +		     .pmi_wr_addr_width(address_width),
   1.100 +		     .pmi_wr_data_width(data_width),
   1.101 +		     .pmi_rd_addr_depth(1<<address_width),
   1.102 +		     .pmi_rd_addr_width(address_width),
   1.103 +		     .pmi_rd_data_width(data_width),
   1.104 +		     .pmi_regmode("noreg"),
   1.105 +		     .pmi_gsr("enable"),
   1.106 +		     .pmi_resetmode("sync"),
   1.107 +		     .pmi_init_file("none"),
   1.108 +		     .pmi_init_file_format("binary"),
   1.109 +		     .pmi_family(`LATTICE_FAMILY),
   1.110 +		     .module_type("pmi_ram_dp")
   1.111 +		     )
   1.112 +		lm32_ram_inst
   1.113 +		  (
   1.114 +		   // ----- Inputs -----
   1.115 +		   .Data(write_data),
   1.116 +		   .WrAddress(write_address),
   1.117 +		   .RdAddress(read_address),
   1.118 +		   .WrClock(write_clk),
   1.119 +		   .RdClock(read_clk),
   1.120 +		   .WrClockEn(enable_write),
   1.121 +		   .RdClockEn(enable_read),
   1.122 +		   .WE(write_enable),
   1.123 +		   .Reset(reset),
   1.124 +		   // ----- Outputs -----
   1.125 +		   .Q(read_data)
   1.126 +		   );
   1.127 +	     end
   1.128 +	   else
   1.129 +	     begin
   1.130 +		// True Dual-Port EBR
   1.131 +		wire   [data_width-1:0] read_data_A, read_data_B;
   1.132 +		reg [data_width-1:0] 	raw_data, raw_data_nxt;
   1.133 +		reg 			raw, raw_nxt;
   1.134 +		
   1.135 +		/*----------------------------------------------------------------------
   1.136 +		 Is a read being performed in the same cycle as a write? Indicate this
   1.137 +		 event with a RAW hazard signal that is released only when a new read
   1.138 +		 or write occurs later.
   1.139 +		 ----------------------------------------------------------------------*/
   1.140 +		always @(/*AUTOSENSE*/enable_read or enable_write
   1.141 +			 or raw or raw_data or read_address
   1.142 +			 or write_address or write_data
   1.143 +			 or write_enable)
   1.144 +		  if (// Read
   1.145 +		      enable_read
   1.146 +		      // Write
   1.147 +		      && enable_write && write_enable
   1.148 +		      // Read and write address match
   1.149 +		      && (read_address == write_address))
   1.150 +		    begin
   1.151 +		       raw_data_nxt = write_data;
   1.152 +		       raw_nxt = 1'b1;
   1.153 +		    end
   1.154 +		  else
   1.155 +		    if (raw && (enable_read == 1'b0) && (enable_write == 1'b0))
   1.156 +		      begin
   1.157 +			 raw_data_nxt = raw_data;
   1.158 +			 raw_nxt = 1'b1;
   1.159 +		      end
   1.160 +		    else
   1.161 +		      begin
   1.162 +			 raw_data_nxt = raw_data;
   1.163 +			 raw_nxt = 1'b0;
   1.164 +		      end
   1.165 +		
   1.166 +		// Send back write data in case of a RAW hazard; else send back
   1.167 +		// data from memory
   1.168 +		assign read_data = raw ? raw_data : read_data_B;
   1.169 +		
   1.170 +		/*----------------------------------------------------------------------
   1.171 +		 Sequential Logic
   1.172 +		 ----------------------------------------------------------------------*/
   1.173 +		always @(posedge read_clk)
   1.174 +		  if (reset)
   1.175 +		    begin
   1.176 +		       raw_data <= #1 0;
   1.177 +		       raw <= #1 1'b0;
   1.178 +		    end
   1.179 +		  else
   1.180 +		    begin
   1.181 +		       raw_data <= #1 raw_data_nxt;
   1.182 +		       raw <= #1 raw_nxt;
   1.183 +		    end
   1.184 +		
   1.185 +		pmi_ram_dp_true 
   1.186 +		  #( 
   1.187 +		     // ----- Parameters -----
   1.188 +		     .pmi_addr_depth_a(1<<address_width),
   1.189 +		     .pmi_addr_width_a(address_width),
   1.190 +		     .pmi_data_width_a(data_width),
   1.191 +		     .pmi_addr_depth_b(1<<address_width),
   1.192 +		     .pmi_addr_width_b(address_width),
   1.193 +		     .pmi_data_width_b(data_width),
   1.194 +		     .pmi_regmode_a("noreg"),
   1.195 +		     .pmi_regmode_b("noreg"),
   1.196 +		     .pmi_gsr("enable"),
   1.197 +		     .pmi_resetmode("sync"),
   1.198 +		     .pmi_init_file("none"),
   1.199 +		     .pmi_init_file_format("binary"),
   1.200 +		     .pmi_family(`LATTICE_FAMILY),
   1.201 +		     .module_type("pmi_ram_dp_true")
   1.202 +		     )
   1.203 +		lm32_ram_inst
   1.204 +		  (
   1.205 +		   // ----- Inputs -----
   1.206 +		   .DataInA(write_data),
   1.207 +		   .DataInB(write_data),
   1.208 +		   .AddressA(write_address),
   1.209 +		   .AddressB(read_address),
   1.210 +		   .ClockA(write_clk),
   1.211 +		   .ClockB(read_clk),
   1.212 +		   .ClockEnA(enable_write),
   1.213 +		   .ClockEnB(enable_read),
   1.214 +		   .WrA(write_enable),
   1.215 +		   .WrB(`FALSE),
   1.216 +		   .ResetA(reset),
   1.217 +		   .ResetB(reset),
   1.218 +		   // ----- Outputs -----
   1.219 +		   .QA(read_data_A),
   1.220 +		   .QB(read_data_B)
   1.221 +		   );
   1.222 +	     end
   1.223 +	end
   1.224 +	else if ( RAM_IMPLEMENTATION == "SLICE" )
   1.225 +	  begin
   1.226 +	     reg [address_width-1:0] ra; // Registered read address
   1.227 +	     
   1.228 +	     pmi_distributed_dpram 
   1.229 +	       #(
   1.230 +		 // ----- Parameters -----
   1.231 +		 .pmi_addr_depth(1<<address_width),
   1.232 +		 .pmi_addr_width(address_width),
   1.233 +		 .pmi_data_width(data_width),
   1.234 +		 .pmi_regmode("noreg"),
   1.235 +		 .pmi_init_file("none"),
   1.236 +		 .pmi_init_file_format("binary"),
   1.237 +		 .pmi_family(`LATTICE_FAMILY),
   1.238 +		 .module_type("pmi_distributed_dpram")
   1.239 +		 )
   1.240 +	     pmi_distributed_dpram_inst
   1.241 +	       (
   1.242 +		// ----- Inputs -----
   1.243 +		.WrAddress(write_address),
   1.244 +		.Data(write_data),
   1.245 +		.WrClock(write_clk),
   1.246 +		.WE(write_enable),
   1.247 +		.WrClockEn(enable_write),
   1.248 +		.RdAddress(ra),
   1.249 +		.RdClock(read_clk),
   1.250 +		.RdClockEn(enable_read),
   1.251 +		.Reset(reset),
   1.252 +		// ----- Outputs -----
   1.253 +		.Q(read_data)
   1.254 +		);
   1.255 +	     
   1.256 +	     always @(posedge read_clk)
   1.257 +	       if (enable_read)
   1.258 +		 ra <= read_address;
   1.259 +	  end
   1.260 +      
   1.261 +	else 
   1.262 +	  begin
   1.263 +	     /*----------------------------------------------------------------------
   1.264 +	      Internal nets and registers
   1.265 +	      ----------------------------------------------------------------------*/
   1.266 +	     reg [data_width-1:0]    mem[0:(1<<address_width)-1]; // The RAM
   1.267 +	     reg [address_width-1:0] ra; // Registered read address
   1.268 +	     
   1.269 +	     /*----------------------------------------------------------------------
   1.270 +	      Combinational Logic
   1.271 +	      ----------------------------------------------------------------------*/
   1.272 +	     // Read port
   1.273 +	     assign read_data = mem[ra]; 
   1.274 +	     
   1.275 +	     /*----------------------------------------------------------------------
   1.276 +	      Sequential Logic
   1.277 +	      ----------------------------------------------------------------------*/
   1.278 +	     // Write port
   1.279 +	     always @(posedge write_clk)
   1.280 +	       if ((write_enable == `TRUE) && (enable_write == `TRUE))
   1.281 +		 mem[write_address] <= write_data; 
   1.282 +	     
   1.283 +	     // Register read address for use on next cycle
   1.284 +	     always @(posedge read_clk)
   1.285 +	       if (enable_read)
   1.286 +		 ra <= read_address;
   1.287 +	     
   1.288 +	  end
   1.289 +
   1.290 +   endgenerate
   1.291 +
   1.292 +endmodule