blob: 1c00fdbc38d262230c8122323e68ece1eeb12d27 [file] [log] [blame]
module apb_pulpino
#(
parameter APB_ADDR_WIDTH = 12, //APB slaves are 4KB by default
parameter BOOT_ADDR = 32'h8000
)
(
HCLK,
HRESETn,
PADDR,
PWDATA,
PWRITE,
PSEL,
PENABLE,
PRDATA,
PREADY,
PSLVERR,
pad_cfg_o,
clk_gate_o,
pad_mux_o,
boot_addr_o
);
//parameter APB_ADDR_WIDTH = 12;
//parameter BOOT_ADDR = 32'h00008000;
input wire HCLK;
input wire HRESETn;
input wire [APB_ADDR_WIDTH - 1:0] PADDR;
input wire [31:0] PWDATA;
input wire PWRITE;
input wire PSEL;
input wire PENABLE;
output reg [31:0] PRDATA;
output wire PREADY;
output wire PSLVERR;
output wire [191:0] pad_cfg_o;
output wire [31:0] clk_gate_o;
output wire [31:0] pad_mux_o;
output wire [31:0] boot_addr_o;
reg [31:0] pad_mux_q;
reg [31:0] pad_mux_n;
reg [31:0] boot_adr_q;
reg [31:0] boot_adr_n;
reg [31:0] clk_gate_q;
reg [31:0] clk_gate_n;
reg [191:0] pad_cfg_q;
reg [191:0] pad_cfg_n;
wire [3:0] register_adr;
reg [1:0] status_n;
reg [1:0] status_q;
assign register_adr = PADDR[5:2];
assign pad_mux_o = pad_mux_q;
assign clk_gate_o = clk_gate_q;
assign pad_cfg_o = pad_cfg_q;
assign boot_addr_o = boot_adr_q;
always @(*) begin
pad_mux_n = pad_mux_q;
pad_cfg_n = pad_cfg_q;
clk_gate_n = clk_gate_q;
boot_adr_n = boot_adr_q;
status_n = status_q;
if ((PSEL && PENABLE) && PWRITE)
case (register_adr)
4'b0000: pad_mux_n = PWDATA;
4'b0001: clk_gate_n = PWDATA;
4'b0010: boot_adr_n = PWDATA;
4'b1000: begin
pad_cfg_n[0+:6] = PWDATA[5:0];
pad_cfg_n[6+:6] = PWDATA[13:8];
pad_cfg_n[12+:6] = PWDATA[21:16];
pad_cfg_n[18+:6] = PWDATA[29:24];
end
4'b1001: begin
pad_cfg_n[24+:6] = PWDATA[5:0];
pad_cfg_n[30+:6] = PWDATA[13:8];
pad_cfg_n[36+:6] = PWDATA[21:16];
pad_cfg_n[42+:6] = PWDATA[29:24];
end
4'b1010: begin
pad_cfg_n[48+:6] = PWDATA[5:0];
pad_cfg_n[54+:6] = PWDATA[13:8];
pad_cfg_n[60+:6] = PWDATA[21:16];
pad_cfg_n[66+:6] = PWDATA[29:24];
end
4'b1011: begin
pad_cfg_n[72+:6] = PWDATA[5:0];
pad_cfg_n[78+:6] = PWDATA[13:8];
pad_cfg_n[84+:6] = PWDATA[21:16];
pad_cfg_n[90+:6] = PWDATA[29:24];
end
4'b1100: begin
pad_cfg_n[96+:6] = PWDATA[5:0];
pad_cfg_n[102+:6] = PWDATA[13:8];
pad_cfg_n[108+:6] = PWDATA[21:16];
pad_cfg_n[114+:6] = PWDATA[29:24];
end
4'b1101: begin
pad_cfg_n[120+:6] = PWDATA[5:0];
pad_cfg_n[126+:6] = PWDATA[13:8];
pad_cfg_n[132+:6] = PWDATA[21:16];
pad_cfg_n[138+:6] = PWDATA[29:24];
end
4'b1110: begin
pad_cfg_n[144+:6] = PWDATA[5:0];
pad_cfg_n[150+:6] = PWDATA[13:8];
pad_cfg_n[156+:6] = PWDATA[21:16];
pad_cfg_n[162+:6] = PWDATA[29:24];
end
4'b1111: begin
pad_cfg_n[168+:6] = PWDATA[5:0];
pad_cfg_n[174+:6] = PWDATA[13:8];
pad_cfg_n[180+:6] = PWDATA[21:16];
pad_cfg_n[186+:6] = PWDATA[29:24];
end
4'b0101: status_n = PWDATA[1:0];
endcase
end
always @(*) begin
PRDATA = 'b0;
if ((PSEL && PENABLE) && !PWRITE)
case (register_adr)
4'b0000: PRDATA = pad_mux_q;
4'b0010: PRDATA = boot_adr_q;
4'b0001: PRDATA = clk_gate_q;
4'b1000: PRDATA = {2'b00, pad_cfg_q[18+:6], 2'b00, pad_cfg_q[12+:6], 2'b00, pad_cfg_q[6+:6], 2'b00, pad_cfg_q[0+:6]};
4'b1001: PRDATA = {2'b00, pad_cfg_q[42+:6], 2'b00, pad_cfg_q[36+:6], 2'b00, pad_cfg_q[30+:6], 2'b00, pad_cfg_q[24+:6]};
4'b1010: PRDATA = {2'b00, pad_cfg_q[66+:6], 2'b00, pad_cfg_q[60+:6], 2'b00, pad_cfg_q[54+:6], 2'b00, pad_cfg_q[48+:6]};
4'b1011: PRDATA = {2'b00, pad_cfg_q[90+:6], 2'b00, pad_cfg_q[84+:6], 2'b00, pad_cfg_q[78+:6], 2'b00, pad_cfg_q[72+:6]};
4'b1100: PRDATA = {2'b00, pad_cfg_q[114+:6], 2'b00, pad_cfg_q[108+:6], 2'b00, pad_cfg_q[102+:6], 2'b00, pad_cfg_q[96+:6]};
4'b1101: PRDATA = {2'b00, pad_cfg_q[138+:6], 2'b00, pad_cfg_q[132+:6], 2'b00, pad_cfg_q[126+:6], 2'b00, pad_cfg_q[120+:6]};
4'b1110: PRDATA = {2'b00, pad_cfg_q[162+:6], 2'b00, pad_cfg_q[156+:6], 2'b00, pad_cfg_q[150+:6], 2'b00, pad_cfg_q[144+:6]};
4'b1111: PRDATA = {2'b00, pad_cfg_q[186+:6], 2'b00, pad_cfg_q[180+:6], 2'b00, pad_cfg_q[174+:6], 2'b00, pad_cfg_q[168+:6]};
4'b0100: PRDATA = 32'b00000000000000001000000010000010;
4'b0101: PRDATA = {30'b000000000000000000000000000000, status_q[1:0]};
default: PRDATA = 'b0;
endcase
end
always @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
pad_mux_q <= 32'b00000000000000000000000000000000;
clk_gate_q <= 1'sb1;
pad_cfg_q <= {32 {6'b000000}};
boot_adr_q <= BOOT_ADDR;
status_q <= 1'sb1;
pad_cfg_q[0+:6] <= 6'b000000;
pad_cfg_q[6+:6] <= 6'b000000;
pad_cfg_q[12+:6] <= 6'b000000;
pad_cfg_q[18+:6] <= 6'b000000;
pad_cfg_q[24+:6] <= 6'b000000;
pad_cfg_q[30+:6] <= 6'b000000;
pad_cfg_q[36+:6] <= 6'b000000;
pad_cfg_q[42+:6] <= 6'b000000;
pad_cfg_q[48+:6] <= 6'b000000;
pad_cfg_q[54+:6] <= 6'b000000;
pad_cfg_q[60+:6] <= 6'b000000;
pad_cfg_q[66+:6] <= 6'b000000;
pad_cfg_q[72+:6] <= 6'b000000;
pad_cfg_q[78+:6] <= 6'b000000;
pad_cfg_q[84+:6] <= 6'b000000;
pad_cfg_q[90+:6] <= 6'b000000;
pad_cfg_q[96+:6] <= 6'b000000;
pad_cfg_q[102+:6] <= 6'b000000;
pad_cfg_q[108+:6] <= 6'b000000;
pad_cfg_q[114+:6] <= 6'b000000;
pad_cfg_q[120+:6] <= 6'b000000;
end
else begin
pad_mux_q <= pad_mux_n;
clk_gate_q <= clk_gate_n;
pad_cfg_q <= pad_cfg_n;
boot_adr_q <= boot_adr_n;
status_q <= status_n;
end
assign PREADY = 1'b1;
assign PSLVERR = 1'b0;
endmodule