Преглед изворни кода

Fix mailboxes to support overwrites and precedence over SW to RTL writes. Add more control code to SW.

Signed-off-by: Jakub Duchniewicz <j.duchniewicz@gmail.com>
Jakub Duchniewicz пре 11 часа
родитељ
комит
506cdd9e8d

+ 6 - 4
projects/riscv_usb/fw/fw_app.c

@@ -31,7 +31,6 @@
 #include "spi.h"
 #include "utils.h"
 #include "registers.h"
-#include "buttons.h"
 #include "generation.h"
 
 /* FLASH */
@@ -271,8 +270,11 @@ void main()
             // button registers have to be cleared upon reading
             clear_button_regs();
             write_regs_to_mailbox();
-            // TODO: need a new value to write contents to flash ( probably +1 mailbox?)
-			//write_to_flash();
+            if (mailbox_regs->regs.write_flash)
+            {
+                store_generation_values_flash();
+                mailbox_regs->regs.write_flash = 0x0;
+            }
         }
 
         // TODO: Add incrementing/decrementing values from console
@@ -325,5 +327,5 @@ void main()
 			}
 		}
 #endif
-	}
+        }
 }

+ 43 - 16
projects/riscv_usb/fw/generation.c

@@ -56,22 +56,40 @@ uint32_t validate_generation_values(tweaked_params_s * pParams)
 
 void update_three_signal_values(tweaked_params_s * pParams, wb_mailbox_button_regs_t * pButtons)
 {
-    // TODO: fill all the remaining incrementations/decrementations
+    // TODO: I assume here that value of 1 means one button press - how to interpret long presses?
+    // Optimization - we only call delta - increment and decrement
+    int32_t delta = pButtons->regs.inc_f1 - pButtons->regs.dec_f1;
+    if (delta > 0)
+        inc_f1(pParams, delta);
+    else if (delta < 0)
+        dec_f1(pParams, -delta);
+
+    // TODO: add handling of the rest
+    //delta = pButtons->regs.inc_d1 - pButtons->regs.dec_d1;
 }
 
 
 // TODO: all of these have to be updated by a value read from the register (how to calibrate it?)
-void inc_f1(tweaked_params_s * pParams, uint32_t val){
+void inc_f1(tweaked_params_s * pParams, uint32_t val) {
     int32_t f1 = pParams->f1;
-
-    f1 += 5;
-    if(f1>MAX_FREQ1)
-        return;
-    int32_t _period1 = DIV_ROUND(BASE_FREQ, f1);
-
-    uint32_t pulses_time = pParams->_period3*(pParams->N3+2)*N_PULSE_TRAINS;
-    if(pulses_time>_period1)
-        return;
+    int32_t _period1 = 0;
+
+    while (val) {
+        f1 += 5;
+        if (f1 > MAX_FREQ1)
+            return;
+        _period1 = DIV_ROUND(BASE_FREQ, f1);
+
+        uint32_t pulses_time = pParams->_period3*(pParams->N3+2)*N_PULSE_TRAINS;
+        if (pulses_time > _period1)
+        {
+            // undo the last step
+            f1 -= 5;
+            _period1 = DIV_ROUND(BASE_FREQ, f1);
+            break;
+        }
+        --val;
+    }
 
     int32_t _duty1 = _period1*pParams->D1/4000;
     int32_t _duty2 = _period1*pParams->D2/4000;
@@ -86,11 +104,20 @@ void inc_f1(tweaked_params_s * pParams, uint32_t val){
 
 void dec_f1(tweaked_params_s * pParams, uint32_t val) {
     int32_t f1 = pParams->f1;
-
-    f1 -= 5;
-    if(f1<MIN_FREQ1)
-        return;
-    int32_t _period1 = DIV_ROUND(BASE_FREQ, f1);
+    int32_t _period1 = 0;
+
+    while (val) {
+        f1 -= 5;
+        if (f1 < MIN_FREQ1)
+        {
+            f1 += 5;
+            _period1 = DIV_ROUND(BASE_FREQ, f1);
+            break;
+        }
+        _period1 = DIV_ROUND(BASE_FREQ, f1);
+
+        --val;
+    }
 
     int32_t _duty1 = _period1*pParams->D1/4000;
     int32_t _duty2 = _period1*pParams->D2/4000;

+ 3 - 0
projects/riscv_usb/fw/generation.h

@@ -52,3 +52,6 @@ typedef struct {
 void init_params(tweaked_params_s * pParams);
 uint32_t validate_generation_values(tweaked_params_s * pParams);
 void update_three_signal_values(tweaked_params_s * pParams, wb_mailbox_button_regs_t * pButtons);
+
+void inc_f1(tweaked_params_s * pParams, uint32_t val);
+void dec_f1(tweaked_params_s * pParams, uint32_t val);

+ 2 - 1
projects/riscv_usb/fw/registers.h

@@ -16,7 +16,8 @@ typedef struct {
     uint32_t npuls3;
     uint32_t odd_train_flag;
     uint32_t ena_odd_out3;
-    uint32_t reserved[5];
+    uint32_t write_flash;
+    uint32_t reserved[4];
 } three_signal_regs_t __attribute__((packed,aligned(4)));
 
 typedef struct {

+ 52 - 34
projects/riscv_usb/rtl/mailbox_wb_rtl2sw.v

@@ -6,58 +6,78 @@
  * Copyright (C) 2025 Krzysztof Skrzynecki, Jakub Duchniewicz <j.duchniewicz@gmail.com>
  * SPDX-License-Identifier: TODO:
  */
-
 `default_nettype none
 
 module mailbox_wb_rtl2sw #(
-    parameter AW = 4,  // Address width for 16 registers (4 bits)
-    parameter DW = 32   // Data width for the Wishbone interface (32 bits)
+    parameter AW = 4,  // 16 registers => 4-bit address
+    parameter DW = 32  // 32-bit Wishbone Data
 )(
     input  wire             clk,
     input  wire             rst,
+
+    // -------------------------
     // Wishbone Interface
-    input  wire [AW-1:0]    wb_addr,
-    output reg  [DW-1:0]    wb_rdata,
-    input  wire             wb_cyc,
-    output reg              wb_ack,
+    // -------------------------
+    input  wire [AW-1:0]    wb_addr,    // register index (0..15)
+    input  wire [DW-1:0]    wb_wdata,   // Wishbone write data
+    input  wire             wb_we,      // Wishbone write enable
+    input  wire             wb_cyc,     // Wishbone cycle (bus valid)
+    output reg  [DW-1:0]    wb_rdata,   // Wishbone read data
+    output reg              wb_ack,     // Wishbone acknowledge
 
-    input wire [16*16-1:0] registers_flat_in
+    // -------------------------
+    // Hardware-driven inputs
+    // (16 registers x 16 bits = 256 bits total)
+    // -------------------------
+    input wire [16*16-1:0]  registers_flat_in
 );
 
-    // Internal registers (16 registers, each 16 bits wide)
-    reg [15:0] registers_array[15:0];
+    // Internal 16-bit registers. Indices: 0..15
+    reg [15:0] registers_array [0:15];
 
-    generate
-        genvar j;
-        for (j = 0; j < 16; j = j + 1) begin : unflatten_ro
-            always @(posedge clk or posedge rst) begin
-                if (rst) begin
-                    registers_array[j] <= 16'h0;
-                end else begin
-                    // Continuously update read-only registers
-                    // from the hardware input
-                    registers_array[j] <= registers_flat_in[16*(j+1)-1 : 16*j];
-                end
-            end
-        end
-    endgenerate
-
-    // Always reset the registers on reset signal
+    //-------------------------------------------
+    // A single procedural always block
+    //-------------------------------------------
     integer i;
     always @(posedge clk or posedge rst) begin
         if (rst) begin
+            // 1) Reset logic
             wb_ack <= 1'b0;
             for (i = 0; i < 16; i = i + 1) begin
-                registers_array[i] <= 16'h0; // Reset all registers to 0
+                registers_array[i] <= 16'h0000;
             end
+            wb_rdata <= 32'h0000_0000;
         end else begin
-            // Default no ack
+            //-----------------------------------
+            // 2) Default: no Wishbone ack
+            //-----------------------------------
             wb_ack <= 1'b0;
 
+            //-----------------------------------
+            // 3) HW vs SW for each register
+            //    - If SW writes (wb_we) to j,
+            //      that overrides the HW input
+            //-----------------------------------
+            integer j;
+            for (j = 0; j < 16; j = j + 1) begin
+                if (wb_cyc && wb_we && (wb_addr == j)) begin
+                    // CPU write has priority this cycle
+                    registers_array[j] <= wb_wdata[15:0];
+                end else begin
+                    // Otherwise, updated by HW input
+                    registers_array[j] <= registers_flat_in[16*(j+1)-1 : 16*j];
+                end
+            end
+
+            //-----------------------------------
+            // 4) Wishbone read logic
+            //    - If bus is active (wb_cyc),
+            //      read out the requested register
+            //-----------------------------------
             if (wb_cyc) begin
-                // Read operation (read the correct register based on address)
+                wb_ack <= 1'b1;
                 case (wb_addr)
-                    4'b0000: wb_rdata <= {16'h0, registers_array[0]}; // Place 16-bit value in lower half of 32-bit bus
+                    4'b0000: wb_rdata <= {16'h0, registers_array[0]};
                     4'b0001: wb_rdata <= {16'h0, registers_array[1]};
                     4'b0010: wb_rdata <= {16'h0, registers_array[2]};
                     4'b0011: wb_rdata <= {16'h0, registers_array[3]};
@@ -73,13 +93,11 @@ module mailbox_wb_rtl2sw #(
                     4'b1101: wb_rdata <= {16'h0, registers_array[13]};
                     4'b1110: wb_rdata <= {16'h0, registers_array[14]};
                     4'b1111: wb_rdata <= {16'h0, registers_array[15]};
-                    default: wb_rdata <= 32'hDEAD_BEEF; // Default error value
+                    default: wb_rdata <= 32'hDEAD_BEEF;
                 endcase
-
-                // Acknowledge for exactly 1 cycle
-                wb_ack <= 1'b1;
             end
         end
     end
 
 endmodule
+

+ 6 - 0
projects/riscv_usb/rtl/mailbox_wb_sw2rtl.v

@@ -23,6 +23,7 @@ module mailbox_wb_sw2rtl #(
     input  wire             wb_cyc,
     output reg              wb_ack,
 
+    input wire              write_flash, // TODO: this is a hack - ideally we would have a better mailbox design
     // Flattened custom hardware side (RTL)
     output wire [16*16-1:0]     registers_flat  // Flattened register array (16 registers of 16 bits each)
 );
@@ -66,6 +67,11 @@ module mailbox_wb_sw2rtl #(
                     endcase
                 end
 
+                // Force write 1 to regiser[9] - to write mailbox values to flash
+                if (write_flash) begin
+                    registers_array[9] <= 32'h1;
+                end
+
                 // Read operation (read the correct register based on address)
                 case (wb_addr)
                     4'b0000: wb_rdata <= {16'h0, registers_array[0]}; // Place 16-bit value in lower half of 32-bit bus

+ 5 - 2
projects/riscv_usb/rtl/top.v

@@ -99,7 +99,7 @@ module top (
     wire [PULSE_COUNTER_WIDTH-1:0] npuls3;
     wire [1:0] odd_train_flag;
     wire ena_odd_out3;
-    wire write_flash;
+    reg write_flash;
 
     // Buttons
     reg [BUTTON_COUNTER_WIDTH-1:0] inc_f1;
@@ -232,6 +232,7 @@ module top (
 		.wb_we(wb_we),
 		.wb_cyc(wb_cyc[4]),
 		.wb_ack(wb_ack[4]),
+        .write_flash(write_flash),
 		.registers_flat(mailbox_regs_flat)
 	);
 
@@ -247,7 +248,7 @@ module top (
     assign npuls3 = mailbox_regs_flat[127:112];      // Next 16 bits for npuls3
     assign odd_train_flag = mailbox_regs_flat[143:128]; // Next 16 bits for odd_train_flag
     assign ena_odd_out3 = mailbox_regs_flat[159:144]; // Next 16 bits for ena_odd_out3
-    assign write_flash = mailbox_regs_flat[175:160]; // Next 16 bits for write_flash (triggered from keyboard)
+    //assign write_flash = mailbox_regs_flat[175:160]; // Next 16 bits for write_flash (triggered from keyboard)
 
     three_signal #(
         .FAST_PWM_WIDTH(FAST_PWM_WIDTH),
@@ -280,7 +281,9 @@ module top (
 		.clk(clk_24m),
 		.rst(rst),
 		.wb_addr(wb_addr[3:0]),
+		.wb_wdata(wb_wdata),
 		.wb_rdata(wb_rdata[5]),
+        .wb_we(wb_we),
 		.wb_cyc(wb_cyc[5]),
 		.wb_ack(wb_ack[5]),
 		.registers_flat_in(mailbox_btns_flat)