Skip to content

Commit

Permalink
axi_lite_to_apb: Make apb_req_o struct private for each slave
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfgang Rönninger authored and andreaskurth committed Feb 24, 2020
1 parent 18ce901 commit 9d0b126
Showing 1 changed file with 35 additions and 30 deletions.
65 changes: 35 additions & 30 deletions src/axi_lite_to_apb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@
// typedef struct packed {
// addr_t paddr; // same as AXI4-Lite
// prot_t pprot; // same as AXI4-Lite, specification is the same
// sel_t psel; // onehot, one psel line per connected APB4 slave
// logic psel; // each APB4 slave has its own single-bit psel
// logic penable; // enable signal shows second APB4 cycle
// logic pwrite; // write enable
// data_t pwdata; // write data, comes from W channel
// strb_t pstrb; // write strb, comes from W channel
// } apb_req_t;
// To connect one APB4 slave the corresponding `psel` signal only asserts, when the address
// decoding matches. To connect to a single APB4 slave connect each of the `apb_req_o` signals,
// however only the corresponding `psel` bit.
// For every APB4 slave, the `psel` field is only asserted when the decoded address matches that
// slave. If `psel` is deasserted, the value of the other fields may be undefined.
//
// The type of the APB4 response is required to look like:
// typedef struct packed {
Expand Down Expand Up @@ -62,7 +61,7 @@ module axi_lite_to_apb #(
input axi_lite_req_t axi_lite_req_i,
output axi_lite_resp_t axi_lite_resp_o,
// APB master port
output apb_req_t apb_req_o,
output apb_req_t [NoApbSlaves-1:0] apb_req_o,
input apb_resp_t [NoApbSlaves-1:0] apb_resp_i,
// APB Slave Address Map
input rule_t [NoRules-1:0] addr_map_i
Expand Down Expand Up @@ -230,17 +229,9 @@ module axi_lite_to_apb #(

always_comb begin
// default assignments
apb_state_d = apb_state_q;
apb_update = 1'b0;
apb_req_o = '{
paddr: apb_req.addr,
pprot: apb_req.prot,
psel: '0,
penable: '0,
pwrite: apb_req.write,
pwdata: apb_req.data,
pstrb: apb_req.strb
};
apb_state_d = apb_state_q;
apb_update = 1'b0;
apb_req_o = '0;
apb_req_ready = 1'b0;
// response defaults to the two response spill registers
apb_wresp = axi_pkg::RESP_SLVERR;
Expand All @@ -251,13 +242,22 @@ module axi_lite_to_apb #(
unique case (apb_state_q)
Setup: begin
// `Idle` and `Setup` steps
// can check here for readyness, because the response goes into spill_registers
// can check here for readiness, because the response goes into spill_registers
if (apb_req_valid && apb_wresp_ready && apb_rresp_ready) begin
if (apb_dec_valid) begin
// `Setup` step
apb_req_o.psel[apb_sel_idx] = 1'b1;
apb_state_d = Access;
apb_update = 1'b1;
// set the request output
apb_req_o[apb_sel_idx] = '{
paddr: apb_req.addr,
pprot: apb_req.prot,
psel: 1'b1,
penable: 1'b0,
pwrite: apb_req.write,
pwdata: apb_req.data,
pstrb: apb_req.strb
};
apb_state_d = Access;
apb_update = 1'b1;
end else begin
// decode error, generate error and do not generate APB request, pop it
apb_req_ready = 1'b1;
Expand All @@ -273,8 +273,15 @@ module axi_lite_to_apb #(
end
Access: begin
// `Access` step
apb_req_o.psel[apb_sel_idx] = 1'b1;
apb_req_o.penable = 1'b1;
apb_req_o[apb_sel_idx] = '{
paddr: apb_req.addr,
pprot: apb_req.prot,
psel: 1'b1,
penable: 1'b1,
pwrite: apb_req.write,
pwdata: apb_req.data,
pstrb: apb_req.strb
};
if (apb_resp_i[apb_sel_idx].pready) begin
// transfer, pop the request, genereate response and update state
apb_req_ready = 1'b1;
Expand All @@ -293,6 +300,7 @@ module axi_lite_to_apb #(
apb_update = 1'b1;
end
end
default: /* do nothing */ ;
endcase
end

Expand All @@ -302,20 +310,17 @@ module axi_lite_to_apb #(
// pragma translate_off
`ifndef VERILATOR
initial begin : check_params
addr_width: assert ($bits(axi_lite_req_i.aw.addr ) == $bits(apb_req_o.paddr)) else
addr_width: assert ($bits(axi_lite_req_i.aw.addr ) == $bits(apb_req_o[0].paddr)) else
$fatal(1, $sformatf("AXI4-Lite and APB address width not equal"));
wdata_width: assert ($bits(axi_lite_req_i.w.data ) == $bits(apb_req_o.pwdata)) else
wdata_width: assert ($bits(axi_lite_req_i.w.data ) == $bits(apb_req_o[0].pwdata)) else
$fatal(1, $sformatf("AXI4-Lite and APB write data width not equal"));
strb_width: assert ($bits(axi_lite_req_i.w.strb ) == $bits(apb_req_o.pstrb)) else
strb_width: assert ($bits(axi_lite_req_i.w.strb ) == $bits(apb_req_o[0].pstrb)) else
$fatal(1, $sformatf("AXI4-Lite and APB address width not equal"));
rdata_width: assert ($bits(axi_lite_resp_o.r.data ) == $bits(apb_resp_i[0].prdata)) else
$fatal(1, $sformatf("AXI4-Lite and APB read data width not equal"));
sel_width: assert ($bits(apb_req_o.psel) == NoApbSlaves) else
$fatal(1, $sformatf("APB psel signal does not match parameter NoApbSlaves"));
sel_width: assert ($bits(apb_req_o[0].psel) == 32'd1) else
$fatal(1, $sformatf("APB psel signal has to have a width of 1'b1"));
end

sel_onehot: assert property( @(posedge clk_i) disable iff (!rst_ni) $onehot0(apb_req_o.psel)) else
$fatal(1, "apb_req_o.psel is not onehot");
`endif
// pragma translate_on
endmodule
Expand Down

0 comments on commit 9d0b126

Please sign in to comment.