tillitis-key/hw/application_fpga/rtl/fw_ram.v
Joachim Strömbergson 15765c3068
fpga: Increase fw_ram to 4 kBytes
Signed-off-by: Joachim Strömbergson <joachim@assured.se>
2024-07-11 14:20:00 +02:00

230 lines
5.5 KiB
Verilog

//======================================================================
//
// fw_ram.v
// --------
// A 1024 x 32 bit RAM (4096 bytes) for use by the FW. The memory has
// support for mode based access control.
//
// Author: Joachim Strombergson
// Copyright (C) 2022 - Tillitis AB
// SPDX-License-Identifier: GPL-2.0-only
//
//======================================================================
`default_nettype none
module fw_ram(
input wire clk,
input wire reset_n,
input wire fw_app_mode,
input wire cs,
input wire [3 : 0] we,
input wire [9 : 0] address,
input wire [31 : 0] write_data,
output wire [31 : 0] read_data,
output wire ready
);
//----------------------------------------------------------------
// Registers and wires.
//----------------------------------------------------------------
reg [31 : 0] tmp_read_data;
reg [31 : 0] mem_read_data0;
reg [31 : 0] mem_read_data1;
reg [31 : 0] mem_read_data2;
reg [31 : 0] mem_read_data3;
reg ready_reg;
wire fw_app_cs;
reg bank0;
reg bank1;
reg bank2;
reg bank3;
//----------------------------------------------------------------
// Concurrent assignment of ports.
//----------------------------------------------------------------
assign read_data = tmp_read_data;
assign ready = ready_reg;
assign fw_app_cs = cs && ~fw_app_mode;
//----------------------------------------------------------------
// Block RAM instances.
//----------------------------------------------------------------
// Bank0
SB_RAM40_4K fw_ram0_0(
.RDATA(mem_read_data0[15 : 0]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(fw_app_cs & bank0),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[15 : 0]),
.WE((|we & fw_app_cs & bank0)),
.MASK({{8{~we[1]}}, {8{~we[0]}}})
);
SB_RAM40_4K fw_ram0_1(
.RDATA(mem_read_data0[31 : 16]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(fw_app_cs & bank0),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[31 : 16]),
.WE((|we & fw_app_cs & bank0)),
.MASK({{8{~we[3]}}, {8{~we[2]}}})
);
// Bank1
SB_RAM40_4K fw_ram1_0(
.RDATA(mem_read_data1[15 : 0]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(fw_app_cs & bank1),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[15 : 0]),
.WE((|we & fw_app_cs & bank1)),
.MASK({{8{~we[1]}}, {8{~we[0]}}})
);
SB_RAM40_4K fw_ram1_1(
.RDATA(mem_read_data1[31 : 16]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(fw_app_cs & bank1),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[31 : 16]),
.WE((|we & fw_app_cs & bank1)),
.MASK({{8{~we[3]}}, {8{~we[2]}}})
);
// Bank2
SB_RAM40_4K fw_ram2_0(
.RDATA(mem_read_data2[15 : 0]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(fw_app_cs & bank2),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[15 : 0]),
.WE((|we & fw_app_cs & bank2)),
.MASK({{8{~we[1]}}, {8{~we[0]}}})
);
SB_RAM40_4K fw_ram2_1(
.RDATA(mem_read_data2[31 : 16]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(fw_app_cs & bank2),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[31 : 16]),
.WE((|we & fw_app_cs & bank2)),
.MASK({{8{~we[3]}}, {8{~we[2]}}})
);
// Bank3
SB_RAM40_4K fw_ram3_0(
.RDATA(mem_read_data3[15 : 0]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(fw_app_cs & bank3),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[15 : 0]),
.WE((|we & fw_app_cs & bank3)),
.MASK({{8{~we[1]}}, {8{~we[0]}}})
);
SB_RAM40_4K fw_ram3_1(
.RDATA(mem_read_data3[31 : 16]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(fw_app_cs & bank3),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[31 : 16]),
.WE((|we & fw_app_cs & bank3)),
.MASK({{8{~we[3]}}, {8{~we[2]}}})
);
//----------------------------------------------------------------
// reg_update
//----------------------------------------------------------------
always @(posedge clk)
begin : reg_update
if (!reset_n) begin
ready_reg <= 1'h0;
end
else begin
ready_reg <= cs;
end
end
//----------------------------------------------------------------
// rw_mux
//----------------------------------------------------------------
always @*
begin : rw_mux;
bank0 = 1'h0;
bank1 = 1'h0;
bank2 = 1'h0;
bank3 = 1'h0;
if (fw_app_cs) begin
case(address[9 : 8])
0: begin
bank0 = 1'h1;
tmp_read_data = mem_read_data0;
end
1: begin
bank1 = 1'h1;
tmp_read_data = mem_read_data1;
end
2: begin
bank2 = 1'h1;
tmp_read_data = mem_read_data2;
end
3: begin
bank3 = 1'h1;
tmp_read_data = mem_read_data3;
end
default: begin
end
endcase // case (address[9 : 8])
end
end
endmodule // fw_ram
//======================================================================
// EOF fw_ram.v
//======================================================================