Memory write

Here’s a very simple APB module I created to control a RISC-V processor:

Some things I noted:
You’re doing full address decoding; don’t do that, just the interesting bits,
i.e. 23-2; don’t try to decode bits 0 and 1, you’re handling 32-bits wide data.
Just trust that bits 31-24 will be decoded by whatever APB_MTARGET you connect to.

module ControlAPB #(
   parameter SELECT_BIT = 10
)(
   input  wire                  PCLK
  ,input  wire                  PRESETN
  // APB Slave
  ,input  wire           [31:0] PADDR
  ,input  wire                  PENABLE
  ,output wire           [31:0] PRDATA
  ,output wire                  PREADY
  ,input  wire                  PSEL
  ,output wire                  PSLVERR
  ,input  wire           [31:0] PWDATA
  ,input  wire                  PWRITE
  // MEMORY
  ,input  wire           [31:0] M_IN_0
  ,input  wire           [31:0] M_IN_1
  ,output wire [SELECT_BIT-1:0] M_ADDR
  ,output wire           [31:0] M_OUT
  ,output wire            [1:0] M_WEN
  ,output wire            [3:0] M_WBE
  // PRC
  ,output wire                  PRESETN_O
  ,output wire                  IE_O
  ,output wire           [23:0] START_PC_O
);

   assign PSLVERR = 1'b0;
   assign PREADY  = 1'b1;

   assign M_ADDR  = PADDR[SELECT_BIT+2:2];
   assign M_OUT   = PWDATA;

   assign M_WEN   = &{PENABLE, PWRITE, PSEL};

   assign M_WBE   = 4'b1111;

// +--------------------------------------+
// | R I       |            PC            |
// +-----------+- ------------------------+
// | 3 3 222222|22221111_11111100_00000000|
// | 1 0 987654|32109876_54321098_76543210|
// +-----------+--------------------------+
//
// Note: PC is shifted << 8 to make it 32bit,
//       so the execution granularity is 256 bytes.
//
   reg [31:0] res_int_pc_start;

   always @(posedge PCLK) begin
      if (~PRESETN) begin
         res_int_pc_start <= 32'b10_000000_10000000_00000000_00000000;
      end else begin
         if(M_WEN & PADDR[23:20] == 4'b0001) begin
            res_int_pc_start[31:30] <= PWDATA[31:30];
            if (res_int_pc_start[31] == 1'b0) begin
               res_int_pc_start[23:0] <= PWDATA[23:0]; // Only accept new PC if the CPU is *already* halted.
            end
         end
      end
   end

   assign PRESETN_O   = &{PRESETN, res_int_pc_start[31]};
   assign IE_O        = &{PRESETN, res_int_pc_start[30]};
   assign START_PC_O  = res_int_pc_start[23:0];

   assign PRDATA      = (PADDR[23:20] == 4'b0001) ? res_int_pc_start :
                        (PADDR[SELECT_BIT]) ? M_IN_1 : M_IN_0;

endmodule

This is how it’s connected:

So the gist of it is: Don’t decode more than the bits you really need,
and don’t touch bits 0 and 1.

Doesn’t that look so much more reasonable? :grinning: