Skip to content

Commit

Permalink
axi_lite_to_apb: Make pipeline registers optional
Browse files Browse the repository at this point in the history
Rationale: The conversion from AXI-Lite to APB is fairly simple both for
requests and responses.  Thus, unless this needs to be clocked at very
high frequencies, it should be possible without a pipeline register.
This saves one cycle of latency for each request and one for each
response.  Since latency is presumably more critical for this conversion
that achieving maximum frequency, the default is changed to not insert
pipeline registers.

The registers cannot be completely omitted, however, because the
implementation relies on a default-ready behavior both for requests and
responses.  Fall-through registers, which are designed exactly for
adding the default-ready behavior, are thus instantiated when pipelining
is disabled.
  • Loading branch information
andreaskurth committed Feb 1, 2021
1 parent 4d1fe30 commit a2bbc24
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 50 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added

### Changed
- `axi_lite_to_apb`: Make pipeline registers on request and response path optional (can be enabled
with the new `PipelineRequest` and `PipelineResponse` `parameter`s), and disable those pipeline
registers by default.

### Fixed

Expand Down
8 changes: 8 additions & 0 deletions scripts/run_vsim.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ exec_test() {
done
done
;;
axi_lite_to_apb)
for PIPE_REQ in 0 1; do
for PIPE_RESP in 0 1; do
call_vsim tb_axi_lite_to_apb -gTbPipelineRequest=$PIPE_REQ \
-gTbPipelineResponse=$PIPE_RESP
done
done
;;
axi_lite_to_axi)
for DW in 8 16 32 64 128 256 512 1024; do
call_vsim tb_axi_lite_to_axi -gTB_DW=$DW -t 1ps
Expand Down
130 changes: 90 additions & 40 deletions src/axi_lite_to_apb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//
// Authors:
// - Wolfgang Roenninger <[email protected]>
// - Andreas Kurth <[email protected]>
// - Samuel Riedel <[email protected]>

// Description: AXI4-Lite to APB4 bridge
Expand Down Expand Up @@ -51,6 +52,8 @@ module axi_lite_to_apb #(
parameter int unsigned NoRules = 32'd1, // Number of APB address rules
parameter int unsigned AddrWidth = 32'd32, // Address width
parameter int unsigned DataWidth = 32'd32, // Data width
parameter bit PipelineRequest = 1'b0, // Pipeline request path
parameter bit PipelineResponse = 1'b0, // Pipeline response path
parameter type axi_lite_req_t = logic, // AXI4-Lite request struct
parameter type axi_lite_resp_t = logic, // AXI4-Lite response sruct
parameter type apb_req_t = logic, // APB4 request struct
Expand Down Expand Up @@ -163,47 +166,94 @@ module axi_lite_to_apb #(
.idx_o ( /*not used*/ )
);

spill_register #(
.T ( int_req_t ),
.Bypass ( 1'b0 )
) i_req_spill (
.clk_i,
.rst_ni,
.valid_i ( arb_req_valid ),
.ready_o ( arb_req_ready ),
.data_i ( arb_req ),
.valid_o ( apb_req_valid ),
.ready_i ( apb_req_ready ),
.data_o ( apb_req )
);

spill_register #(
.T ( axi_pkg::resp_t ),
.Bypass ( 1'b0 )
) i_write_resp_spill (
.clk_i,
.rst_ni,
.valid_i ( apb_wresp_valid ),
.ready_o ( apb_wresp_ready ),
.data_i ( apb_wresp ),
.valid_o ( axi_bresp_valid ),
.ready_i ( axi_lite_req_i.b_ready ),
.data_o ( axi_bresp )
);
if (PipelineRequest) begin : gen_req_spill
spill_register #(
.T ( int_req_t ),
.Bypass ( 1'b0 )
) i_req_spill (
.clk_i,
.rst_ni,
.valid_i ( arb_req_valid ),
.ready_o ( arb_req_ready ),
.data_i ( arb_req ),
.valid_o ( apb_req_valid ),
.ready_i ( apb_req_ready ),
.data_o ( apb_req )
);
end else begin : gen_req_ft_reg
fall_through_register #(
.T ( int_req_t )
) i_req_ft_reg (
.clk_i,
.rst_ni,
.clr_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.valid_i ( arb_req_valid ),
.ready_o ( arb_req_ready ),
.data_i ( arb_req ),
.valid_o ( apb_req_valid ),
.ready_i ( apb_req_ready ),
.data_o ( apb_req )
);
end

spill_register #(
.T ( int_resp_t ),
.Bypass ( 1'b0 )
) i_read_resp_spill (
.clk_i,
.rst_ni,
.valid_i ( apb_rresp_valid ),
.ready_o ( apb_rresp_ready ),
.data_i ( apb_rresp ),
.valid_o ( axi_rresp_valid ),
.ready_i ( axi_lite_req_i.r_ready ),
.data_o ( axi_rresp )
);
if (PipelineResponse) begin : gen_resp_spill
spill_register #(
.T ( axi_pkg::resp_t ),
.Bypass ( 1'b0 )
) i_write_resp_spill (
.clk_i,
.rst_ni,
.valid_i ( apb_wresp_valid ),
.ready_o ( apb_wresp_ready ),
.data_i ( apb_wresp ),
.valid_o ( axi_bresp_valid ),
.ready_i ( axi_lite_req_i.b_ready ),
.data_o ( axi_bresp )
);
spill_register #(
.T ( int_resp_t ),
.Bypass ( 1'b0 )
) i_read_resp_spill (
.clk_i,
.rst_ni,
.valid_i ( apb_rresp_valid ),
.ready_o ( apb_rresp_ready ),
.data_i ( apb_rresp ),
.valid_o ( axi_rresp_valid ),
.ready_i ( axi_lite_req_i.r_ready ),
.data_o ( axi_rresp )
);
end else begin : gen_resp_ft_reg
fall_through_register #(
.T ( axi_pkg::resp_t )
) i_write_resp_ft_reg (
.clk_i,
.rst_ni,
.clr_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.valid_i ( apb_wresp_valid ),
.ready_o ( apb_wresp_ready ),
.data_i ( apb_wresp ),
.valid_o ( axi_bresp_valid ),
.ready_i ( axi_lite_req_i.b_ready ),
.data_o ( axi_bresp )
);
fall_through_register #(
.T ( int_resp_t )
) i_read_resp_ft_reg (
.clk_i,
.rst_ni,
.clr_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.valid_i ( apb_rresp_valid ),
.ready_o ( apb_rresp_ready ),
.data_i ( apb_rresp ),
.valid_o ( axi_rresp_valid ),
.ready_i ( axi_lite_req_i.r_ready ),
.data_o ( axi_rresp )
);
end

// -----------------------------------------------------------------------------------------------
// APB master FSM
Expand Down
25 changes: 15 additions & 10 deletions test/tb_axi_lite_to_apb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
`include "axi/typedef.svh"
`include "axi/assign.svh"

module tb_axi_lite_to_apb;
module tb_axi_lite_to_apb #(
parameter bit TbPipelineRequest = 1'b0,
parameter bit TbPipelineResponse = 1'b0
);
// Dut parameters
localparam int unsigned NoApbSlaves = 8; // How many APB Slaves there are
localparam int unsigned NoAddrRules = 9; // How many address rules for the APB slaves
Expand Down Expand Up @@ -225,15 +228,17 @@ module tb_axi_lite_to_apb;
// DUT
//-----------------------------------
axi_lite_to_apb #(
.NoApbSlaves ( NoApbSlaves ),
.NoRules ( NoAddrRules ),
.AddrWidth ( AxiAddrWidth ),
.DataWidth ( AxiDataWidth ),
.axi_lite_req_t ( axi_req_t ),
.axi_lite_resp_t( axi_resp_t ),
.apb_req_t ( apb_req_t ),
.apb_resp_t ( apb_resp_t ),
.rule_t ( rule_t )
.NoApbSlaves ( NoApbSlaves ),
.NoRules ( NoAddrRules ),
.AddrWidth ( AxiAddrWidth ),
.DataWidth ( AxiDataWidth ),
.PipelineRequest ( TbPipelineRequest ),
.PipelineResponse ( TbPipelineResponse ),
.axi_lite_req_t ( axi_req_t ),
.axi_lite_resp_t ( axi_resp_t ),
.apb_req_t ( apb_req_t ),
.apb_resp_t ( apb_resp_t ),
.rule_t ( rule_t )
) i_axi_lite_to_apb_dut (
.clk_i ( clk ),
.rst_ni ( rst_n ),
Expand Down

0 comments on commit a2bbc24

Please sign in to comment.