tillitis-key/hw/application_fpga/rtl/ram.v
2022-09-19 08:51:11 +02:00

145 lines
3.9 KiB
Verilog

//======================================================================
//
// ram.v
// -----
// Module that encapsulates the four SPRAM blocks in the Lattice
// iCE40UP 5K device. This creates a single 32-bit wide,
// 128 kByte large memory.
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
//
//======================================================================
`default_nettype none
module ram(
input wire clk,
input wire reset_n,
input wire cs,
input wire [03 : 0] we,
input wire [14 : 0] address,
input wire [31 : 0] write_data,
output wire [31 : 0] read_data,
output wire ready
);
//----------------------------------------------------------------
// Registers and wires.
//----------------------------------------------------------------
reg ready_reg;
reg cs0;
reg cs1;
reg [31 : 0] read_data0;
reg [31 : 0] read_data1;
reg [31 : 0] muxed_read_data;
//----------------------------------------------------------------
// Concurrent assignment of ports.
//----------------------------------------------------------------
assign read_data = muxed_read_data;
assign ready = ready_reg;
//----------------------------------------------------------------
// SPRAM instances.
//----------------------------------------------------------------
SB_SPRAM256KA spram0(
.ADDRESS(address[13:0]),
.DATAIN(write_data[15:0]),
.MASKWREN({we[1], we[1], we[0], we[0]}),
.WREN(we[1] | we[0]),
.CHIPSELECT(cs0),
.CLOCK(clk),
.STANDBY(1'b0),
.SLEEP(1'b0),
.POWEROFF(1'b1),
.DATAOUT(read_data0[15:0])
);
SB_SPRAM256KA spram1(
.ADDRESS(address[13:0]),
.DATAIN(write_data[31:16]),
.MASKWREN({we[3], we[3], we[2], we[2]}),
.WREN(we[3] | we[2]),
.CHIPSELECT(cs0),
.CLOCK(clk),
.STANDBY(1'b0),
.SLEEP(1'b0),
.POWEROFF(1'b1),
.DATAOUT(read_data0[31:16])
);
SB_SPRAM256KA spram2(
.ADDRESS(address[13:0]),
.DATAIN(write_data[15:0]),
.MASKWREN({we[1], we[1], we[0], we[0]}),
.WREN(we[1] | we[0]),
.CHIPSELECT(cs1),
.CLOCK(clk),
.STANDBY(1'b0),
.SLEEP(1'b0),
.POWEROFF(1'b1),
.DATAOUT(read_data1[15:0])
);
SB_SPRAM256KA spram3(
.ADDRESS(address[13:0]),
.DATAIN(write_data[31:16]),
.MASKWREN({we[3], we[3], we[2], we[2]}),
.WREN(we[3] | we[2]),
.CHIPSELECT(cs1),
.CLOCK(clk),
.STANDBY(1'b0),
.SLEEP(1'b0),
.POWEROFF(1'b1),
.DATAOUT(read_data1[31:16])
);
//----------------------------------------------------------------
// reg_update
//
// Posedge triggered with synchronous, active low reset.
// This simply creates a one cycle access latency to match
// the latency of the spram blocks.
//----------------------------------------------------------------
always @(posedge clk)
begin : reg_update
if (!reset_n) begin
ready_reg <= 1'h0;
end
else begin
ready_reg <= cs;
end
end
//----------------------------------------------------------------
// mem_mux
//----------------------------------------------------------------
always @*
begin : mem_mux
cs0 = 1'h0;
cs1 = 1'h0;
if (address[14]) begin
cs1 = cs;
muxed_read_data = read_data1;
end else begin
cs0 = cs;
muxed_read_data = read_data0;
end
end
endmodule // ram
//======================================================================
// EOF ram.v
//======================================================================