diff --git a/hw/application_fpga/Makefile b/hw/application_fpga/Makefile index f653e1a..6664b2e 100644 --- a/hw/application_fpga/Makefile +++ b/hw/application_fpga/Makefile @@ -42,11 +42,11 @@ ASFLAGS = -target riscv32-unknown-none-elf -march=rv32imc -mabi=ilp32 -mno-relax ICE40_SIM_CELLS = $(shell yosys-config --datdir/ice40/cells_sim.v) -# FPGA specific Verilog source files. +# FPGA specific source files. FPGA_SRC = $(P)/rtl/application_fpga.v \ $(P)/rtl/clk_reset_gen.v -# Verilator simulation specific Verilog source files. +# Verilator simulation specific source files. VERILATOR_FPGA_SRC = $(P)/tb/application_fpga_vsim.v \ $(P)/tb/reset_gen_vsim.v @@ -54,6 +54,7 @@ VERILATOR_FPGA_SRC = $(P)/tb/application_fpga_vsim.v \ VERILOG_SRCS = \ $(P)/rtl/ram.v \ $(P)/rtl/rom.v \ + $(P)/rtl/fw_ram.v \ $(P)/core/picorv32/rtl/picorv32.v \ $(P)/core/timer/rtl/timer_core.v \ $(P)/core/timer/rtl/timer.v \ diff --git a/hw/application_fpga/fw/mta1_mkdf_mem.h b/hw/application_fpga/fw/mta1_mkdf_mem.h index b66af7c..99e499b 100644 --- a/hw/application_fpga/fw/mta1_mkdf_mem.h +++ b/hw/application_fpga/fw/mta1_mkdf_mem.h @@ -29,6 +29,7 @@ enum { MTA1_MKDF_MMIO_UDS_BASE = MTA1_MKDF_MMIO_BASE | 0x02000000, MTA1_MKDF_MMIO_UART_BASE = MTA1_MKDF_MMIO_BASE | 0x03000000, MTA1_MKDF_MMIO_TOUCH_BASE = MTA1_MKDF_MMIO_BASE | 0x04000000, + MTA1_MKDF_MMIO_FW_RAM_BASE = MTA1_MKDF_MMIO_BASE | 0x10000000, // This "core" only exists in QEMU MTA1_MKDF_MMIO_QEMU_BASE = MTA1_MKDF_MMIO_BASE | 0x3e000000, MTA1_MKDF_MMIO_MTA1_BASE = MTA1_MKDF_MMIO_BASE | 0x3f000000, // 0xff000000 diff --git a/hw/application_fpga/rtl/application_fpga.v b/hw/application_fpga/rtl/application_fpga.v index 6049ba4..930925f 100644 --- a/hw/application_fpga/rtl/application_fpga.v +++ b/hw/application_fpga/rtl/application_fpga.v @@ -48,6 +48,7 @@ module application_fpga( localparam UDS_PREFIX = 6'h02; localparam UART_PREFIX = 6'h03; localparam TOUCH_SENSE_PREFIX = 6'h04; + localparam FW_RAM_PREFIX = 6'h10; localparam MTA1_PREFIX = 6'h3f; @@ -122,6 +123,15 @@ module application_fpga( wire [31 : 0] uart_read_data; wire uart_ready; + /* verilator lint_off UNOPTFLAT */ + reg fw_ram_cs; + /* verilator lint_on UNOPTFLAT */ + reg [3 : 0] fw_ram_we; + reg [7 : 0] fw_ram_address; + reg [31 : 0] fw_ram_write_data; + wire [31 : 0] fw_ram_read_data; + wire fw_ram_ready; + /* verilator lint_off UNOPTFLAT */ reg touch_sense_cs; /* verilator lint_on UNOPTFLAT */ @@ -217,6 +227,21 @@ module application_fpga( ); + fw_ram fw_ram_inst( + .clk(clk), + .reset_n(reset_n), + + .fw_app_mode(fw_app_mode), + + .cs(fw_ram_cs), + .we(fw_ram_we), + .address(fw_ram_address), + .write_data(fw_ram_write_data), + .read_data(fw_ram_read_data), + .ready(fw_ram_ready) + ); + + rosc trng_inst( .clk(clk), .reset_n(reset_n), @@ -350,6 +375,11 @@ module application_fpga( ram_address = cpu_addr[16 : 2]; ram_write_data = cpu_wdata; + fw_ram_cs = 1'h0; + fw_ram_we = cpu_wstrb; + fw_ram_address = cpu_addr[9 : 2]; + fw_ram_write_data = cpu_wdata; + trng_cs = 1'h0; trng_we = |cpu_wstrb; trng_address = cpu_addr[9 : 2]; @@ -428,6 +458,12 @@ module application_fpga( muxed_ready_new = touch_sense_ready; end + FW_RAM_PREFIX: begin + fw_ram_cs = 1'h1; + muxed_rdata_new = fw_ram_read_data; + muxed_ready_new = fw_ram_ready; + end + MTA1_PREFIX: begin mta1_cs = 1'h1; muxed_rdata_new = mta1_read_data; diff --git a/hw/application_fpga/rtl/fw_ram.v b/hw/application_fpga/rtl/fw_ram.v new file mode 100644 index 0000000..d445d9c --- /dev/null +++ b/hw/application_fpga/rtl/fw_ram.v @@ -0,0 +1,92 @@ +//====================================================================== +// +// fw_ram.v +// -------- +// A small 512 x 32 RAM for FW use. With support for 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 [7 : 0] address, + input wire [31 : 0] write_data, + output wire [31 : 0] read_data, + output wire ready + ); + + + //---------------------------------------------------------------- + // Registers and wires. + //---------------------------------------------------------------- + reg ready_reg; + + + //---------------------------------------------------------------- + // Concurrent assignment of ports. + //---------------------------------------------------------------- + assign ready = ready_reg; + + + //---------------------------------------------------------------- + // Block RAM instances. + //---------------------------------------------------------------- + SB_RAM40_4K fw_ram0( + .RDATA(read_data[15:0]), + .RADDR(address), + .RCLK(clk), + .RCLKE(1'h1), + .RE(cs), + .WADDR(address), + .WCLK(clk), + .WCLKE(1'h1), + .WDATA(write_data[15:0]), + .WE(|we), + .MASK({{4{we[1]}}, {4{we[0]}}}) + ); + + + SB_RAM40_4K fw_ram1( + .RDATA(read_data[31:16]), + .RADDR(address), + .RCLK(clk), + .RCLKE(1'h1), + .RE(cs), + .WADDR(address), + .WCLK(clk), + .WCLKE(1'h1), + .WDATA(write_data[31:16]), + .WE(|we), + .MASK({{4{we[3]}}, {4{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 + +endmodule // fw_ram + +//====================================================================== +// EOF fw_ram.v +//======================================================================