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? ![]()
