Find file
Fetching contributors…
Cannot retrieve contributors at this time
146 lines (120 sloc) 4.73 KB
/*
* LatticeMico32
* True dual-ported RAM
*
* Copyright (c) 2012 Michael Walle <michael@walle.cc>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_dp_ram (
// ----- Inputs -------
clk_a,
clk_b,
ce_a,
ce_b,
addr_a,
addr_b,
di_a,
di_b,
we_a,
we_b,
// ----- Outputs -------
do_a,
do_b
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter data_width = 1; // Width of the data ports
parameter address_width = 1; // Width of the address ports
parameter init_file = "NONE"; // Initialization file
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_a; // Clock port A
input clk_b; // Clock port B
input ce_a; // Clock enable port A
input ce_b; // Clock enable port B
input [address_width-1:0] addr_a; // Read/write address port A
input [address_width-1:0] addr_b; // Read/write address port B
input [data_width-1:0] di_a; // Data input port A
input [data_width-1:0] di_b; // Data input port B
input we_a; // Write enable port A
input we_b; // Write enable port B
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
output [data_width-1:0] do_a; // Data output port A
wire [data_width-1:0] do_a;
output [data_width-1:0] do_b; // Data output port B
wire [data_width-1:0] do_b;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
reg [data_width-1:0] mem[0:(1<<address_width)-1];
reg [address_width-1:0] ra_a; // Registered read address port A
reg [address_width-1:0] ra_b; // Registered read address port B
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
// Combinational logic
/////////////////////////////////////////////////////
// Read ports
assign do_a = mem[ra_a];
assign do_b = mem[ra_b];
/////////////////////////////////////////////////////
// Sequential logic
/////////////////////////////////////////////////////
// Write ports
always @(posedge clk_a)
if ((ce_a == `TRUE) && (we_a == `TRUE))
mem[addr_a] <= di_a;
always @(posedge clk_b)
if ((ce_b == `TRUE) && (we_b == `TRUE))
mem[addr_b] <= di_b;
// Register read addresses for use on next cycle
always @(posedge clk_a)
if (ce_a == `TRUE)
ra_a <= addr_a;
always @(posedge clk_b)
if (ce_b == `TRUE)
ra_b <= addr_b;
/////////////////////////////////////////////////////
// Initialization
/////////////////////////////////////////////////////
generate
if (init_file != "NONE")
begin
initial $readmemh(init_file, mem);
end
endgenerate
endmodule