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 //======================================================================