From 35052e50cb1185abe1fd888961e41f54e32c00e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Str=C3=B6mbergson?= Date: Wed, 21 Aug 2024 13:29:27 +0200 Subject: [PATCH] FPGA: Move RAM address and data scrambling into the RAM module. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the logic implementing the RAM address and data scrambling, descrambling into the RAM module. This cleans up the top level, and makes it easier to change the scrambling without chaning the top. In order to do correct scrambling the address to the RAM core must be 16 bits, not 15. Clean up some minor details at the top level, fixing text aligment and grouping of ports in instances. Signed-off-by: Joachim Strömbergson --- .../application_fpga.bin.sha256 | 2 +- hw/application_fpga/core/ram/rtl/ram.v | 57 ++++++++++++++----- hw/application_fpga/firmware.bin.sha512 | 1 - hw/application_fpga/rtl/application_fpga.v | 18 ++++-- 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/hw/application_fpga/application_fpga.bin.sha256 b/hw/application_fpga/application_fpga.bin.sha256 index f4360e1..acd0d24 100644 --- a/hw/application_fpga/application_fpga.bin.sha256 +++ b/hw/application_fpga/application_fpga.bin.sha256 @@ -1 +1 @@ -42746c6d9d879ad975874fb51b3d4e031578dac9a0e7ddd4b10a1d3efa34c6c7 application_fpga.bin +deb4c6f80b28d12ecfb350ac749369c875866d6715c2d14b1ce1b80a272f3ee6 application_fpga.bin diff --git a/hw/application_fpga/core/ram/rtl/ram.v b/hw/application_fpga/core/ram/rtl/ram.v index bb91f7f..fe36c13 100644 --- a/hw/application_fpga/core/ram/rtl/ram.v +++ b/hw/application_fpga/core/ram/rtl/ram.v @@ -6,6 +6,10 @@ // iCE40UP 5K device. This creates a single 32-bit wide, // 128 kByte large memory. // +// The block also implements data and address scrambling controlled +// by the ram_addr_rand and ram_data_rand seeds. +// +// // Author: Joachim Strombergson // Copyright (C) 2022 - Tillitis AB // SPDX-License-Identifier: GPL-2.0-only @@ -17,9 +21,13 @@ module ram( input wire clk, input wire reset_n, + + input wire [14 : 0] ram_addr_rand, + input wire [31 : 0] ram_data_rand, + input wire cs, input wire [03 : 0] we, - input wire [14 : 0] address, + input wire [15 : 0] address, input wire [31 : 0] write_data, output wire [31 : 0] read_data, output wire ready @@ -29,7 +37,7 @@ module ram( //---------------------------------------------------------------- // Registers and wires. //---------------------------------------------------------------- - reg ready_reg; + reg ready_reg; reg cs0; reg cs1; @@ -37,11 +45,15 @@ module ram( reg [31 : 0] read_data1; reg [31 : 0] muxed_read_data; + reg [14 : 0] scrambled_ram_addr; + reg [31 : 0] scrambled_write_data; + reg [31 : 0] descrambled_read_data; + //---------------------------------------------------------------- // Concurrent assignment of ports. //---------------------------------------------------------------- - assign read_data = muxed_read_data; + assign read_data = descrambled_read_data; assign ready = ready_reg; @@ -49,8 +61,8 @@ module ram( // SPRAM instances. //---------------------------------------------------------------- SB_SPRAM256KA spram0( - .ADDRESS(address[13:0]), - .DATAIN(write_data[15:0]), + .ADDRESS(scrambled_ram_addr[13:0]), + .DATAIN(scrambled_write_data[15:0]), .MASKWREN({we[1], we[1], we[0], we[0]}), .WREN(we[1] | we[0]), .CHIPSELECT(cs0), @@ -62,8 +74,8 @@ module ram( ); SB_SPRAM256KA spram1( - .ADDRESS(address[13:0]), - .DATAIN(write_data[31:16]), + .ADDRESS(scrambled_ram_addr[13:0]), + .DATAIN(scrambled_write_data[31:16]), .MASKWREN({we[3], we[3], we[2], we[2]}), .WREN(we[3] | we[2]), .CHIPSELECT(cs0), @@ -76,8 +88,8 @@ module ram( SB_SPRAM256KA spram2( - .ADDRESS(address[13:0]), - .DATAIN(write_data[15:0]), + .ADDRESS(scrambled_ram_addr[13:0]), + .DATAIN(scrambled_write_data[15:0]), .MASKWREN({we[1], we[1], we[0], we[0]}), .WREN(we[1] | we[0]), .CHIPSELECT(cs1), @@ -89,8 +101,8 @@ module ram( ); SB_SPRAM256KA spram3( - .ADDRESS(address[13:0]), - .DATAIN(write_data[31:16]), + .ADDRESS(scrambled_ram_addr[13:0]), + .DATAIN(scrambled_write_data[31:16]), .MASKWREN({we[3], we[3], we[2], we[2]}), .WREN(we[3] | we[2]), .CHIPSELECT(cs1), @@ -120,15 +132,32 @@ module ram( end + //---------------------------------------------------------------- + // scramble_descramble + // + // Scramble address and write data, and descramble read data using + // the ram_addr_rand and ram_data_rand seeds. + //---------------------------------------------------------------- + always @* + begin: scramble_descramble + scrambled_ram_addr = address[14 : 0] ^ ram_addr_rand; + scrambled_write_data = write_data ^ ram_data_rand ^ {2{address}}; + descrambled_read_data = muxed_read_data ^ ram_data_rand ^ {2{address}}; + end + + //---------------------------------------------------------------- // mem_mux + // + // Select which of the data read from the banks should be + // returned during a read access. //---------------------------------------------------------------- always @* begin : mem_mux - cs0 = ~address[14] & cs; - cs1 = address[14] & cs; + cs0 = ~scrambled_ram_addr[14] & cs; + cs1 = scrambled_ram_addr[14] & cs; - if (address[14]) begin + if (scrambled_ram_addr[14]) begin muxed_read_data = read_data1; end else begin muxed_read_data = read_data0; diff --git a/hw/application_fpga/firmware.bin.sha512 b/hw/application_fpga/firmware.bin.sha512 index 990aeeb..c5e51a0 100644 --- a/hw/application_fpga/firmware.bin.sha512 +++ b/hw/application_fpga/firmware.bin.sha512 @@ -1,2 +1 @@ edb39fca7dafb8ea0b89fdeecd960d7656e14ce461e49af97160a8bd6e67d9987e816adad37ba0fcfa63d107c3160988e4c3423ce4a71c39544bc0045888fec1 firmware.bin - diff --git a/hw/application_fpga/rtl/application_fpga.v b/hw/application_fpga/rtl/application_fpga.v index 92c91f0..4b274b2 100644 --- a/hw/application_fpga/rtl/application_fpga.v +++ b/hw/application_fpga/rtl/application_fpga.v @@ -94,7 +94,7 @@ module application_fpga( reg ram_cs; reg [3 : 0] ram_we; - reg [14 : 0] ram_address; + reg [15 : 0] ram_address; reg [31 : 0] ram_write_data; wire [31 : 0] ram_read_data; wire ram_ready; @@ -181,6 +181,7 @@ module application_fpga( .mem_wdata(cpu_wdata), .mem_wstrb(cpu_wstrb), .mem_rdata(muxed_rdata_reg), + .mem_instr(cpu_instr), // Defined unused ports. Makes lint happy. But // we still needs to help lint with empty ports. @@ -189,7 +190,6 @@ module application_fpga( .eoi(), .trace_valid(), .trace_data(), - .mem_instr(cpu_instr), .mem_la_read(), .mem_la_write(), .mem_la_addr(), @@ -222,6 +222,9 @@ module application_fpga( .clk(clk), .reset_n(reset_n), + .ram_addr_rand(ram_addr_rand), + .ram_data_rand(ram_data_rand), + .cs(ram_cs), .we(ram_we), .address(ram_address), @@ -394,8 +397,8 @@ module application_fpga( ram_cs = 1'h0; ram_we = 4'h0; - ram_address = cpu_addr[16 : 2] ^ ram_addr_rand; - ram_write_data = cpu_wdata ^ ram_data_rand ^ {2{cpu_addr[15 : 0]}}; + ram_address = cpu_addr[17 : 2]; + ram_write_data = cpu_wdata; fw_ram_cs = 1'h0; fw_ram_we = cpu_wstrb; @@ -429,6 +432,10 @@ module application_fpga( tk1_address = cpu_addr[9 : 2]; tk1_write_data = cpu_wdata; + + // Two stage mux implementing read and + // write access performed based on the address + // from the CPU. if (cpu_valid && !muxed_ready_reg) begin if (force_trap) begin muxed_rdata_new = ILLEGAL_INSTRUCTION; @@ -445,7 +452,7 @@ module application_fpga( RAM_PREFIX: begin ram_cs = 1'h1; ram_we = cpu_wstrb; - muxed_rdata_new = ram_read_data ^ ram_data_rand ^ {2{cpu_addr[15 : 0]}}; + muxed_rdata_new = ram_read_data; muxed_ready_new = ram_ready; end @@ -513,6 +520,7 @@ module application_fpga( end end end + endmodule // application_fpga //======================================================================