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