mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 13:47:13 -04:00
Use stream_arbiter and fix write ordering
This commit is contained in:
parent
6381b3d3ee
commit
be0b4cd440
2 changed files with 58 additions and 95 deletions
1
Makefile
1
Makefile
|
@ -100,6 +100,7 @@ src := $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv)) \
|
|||
src/common_cells/src/rstgen.sv \
|
||||
src/common_cells/src/stream_mux.sv \
|
||||
src/common_cells/src/stream_demux.sv \
|
||||
src/common_cells/src/stream_arbiter.sv \
|
||||
src/util/axi_master_connect.sv \
|
||||
src/util/axi_slave_connect.sv \
|
||||
src/util/axi_master_connect_rev.sv \
|
||||
|
|
|
@ -101,81 +101,70 @@ module std_cache_subsystem #(
|
|||
// -----------------------
|
||||
// Arbitrate AXI Ports
|
||||
// -----------------------
|
||||
logic [1:0] aw_select, ar_select, w_select;
|
||||
logic aw_arbiter_valid, ar_arbiter_valid, w_arbiter_valid;
|
||||
logic aw_enable_d, aw_enable_q;
|
||||
logic ar_enable_d, ar_enable_q;
|
||||
logic w_enable_d, w_enable_q;
|
||||
|
||||
// AW Channel
|
||||
rrarbiter #(
|
||||
.NUM_REQ ( 3 ),
|
||||
.LOCK_IN ( 1 )
|
||||
) i_rrarbiter_aw (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.flush_i ( 1'b0 ),
|
||||
.en_i ( aw_enable_q ),
|
||||
.req_i ( {axi_req_icache.aw_valid, axi_req_bypass.aw_valid, axi_req_data.aw_valid} ),
|
||||
.ack_o ( ),
|
||||
.vld_o ( aw_arbiter_valid ),
|
||||
.idx_o ( aw_select )
|
||||
);
|
||||
|
||||
stream_mux #(
|
||||
.DATA_T ( ariane_axi::aw_chan_t ),
|
||||
.N_INP ( 3 )
|
||||
) i_stream_mux_aw (
|
||||
.inp_data_i ( {axi_req_icache.aw, axi_req_bypass.aw, axi_req_data.aw} ),
|
||||
.inp_valid_i ( {axi_req_icache.aw_valid, axi_req_bypass.aw_valid, axi_req_data.aw_valid} ),
|
||||
.inp_ready_o ( {axi_resp_icache.aw_ready, axi_resp_bypass.aw_ready, axi_resp_data.aw_ready} ),
|
||||
.inp_sel_i ( aw_select ),
|
||||
.oup_data_o ( axi_req_o.aw ),
|
||||
.oup_valid_o ( axi_req_o.aw_valid ),
|
||||
.oup_ready_i ( axi_resp_i.aw_ready )
|
||||
);
|
||||
logic [1:0] w_select, w_id;
|
||||
logic full;
|
||||
|
||||
// AR Channel
|
||||
rrarbiter #(
|
||||
.NUM_REQ ( 3 ),
|
||||
.LOCK_IN ( 1 )
|
||||
) i_rrarbiter_ar (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.flush_i ( 1'b0 ),
|
||||
.en_i ( ar_enable_q ),
|
||||
.req_i ( {axi_req_icache.ar_valid, axi_req_bypass.ar_valid, axi_req_data.ar_valid} ),
|
||||
.ack_o ( ),
|
||||
.vld_o ( ar_arbiter_valid ),
|
||||
.idx_o ( ar_select )
|
||||
);
|
||||
|
||||
stream_mux #(
|
||||
stream_arbiter #(
|
||||
.DATA_T ( ariane_axi::ar_chan_t ),
|
||||
.N_INP ( 3 )
|
||||
) i_stream_mux_ar (
|
||||
) i_stream_arbiter_ar (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.inp_data_i ( {axi_req_icache.ar, axi_req_bypass.ar, axi_req_data.ar} ),
|
||||
.inp_valid_i ( {axi_req_icache.ar_valid, axi_req_bypass.ar_valid, axi_req_data.ar_valid} ),
|
||||
.inp_ready_o ( {axi_resp_icache.ar_ready, axi_resp_bypass.ar_ready, axi_resp_data.ar_ready} ),
|
||||
.inp_sel_i ( ar_select ),
|
||||
.oup_data_o ( axi_req_o.ar ),
|
||||
.oup_valid_o ( axi_req_o.ar_valid ),
|
||||
.oup_ready_i ( axi_resp_i.ar_ready )
|
||||
);
|
||||
|
||||
// W Channel
|
||||
rrarbiter #(
|
||||
.NUM_REQ ( 3 ),
|
||||
.LOCK_IN ( 1 )
|
||||
) i_rrarbiter_w (
|
||||
// AW Channel
|
||||
stream_arbiter #(
|
||||
.DATA_T ( ariane_axi::aw_chan_t ),
|
||||
.N_INP ( 3 )
|
||||
) i_stream_arbiter_aw (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.flush_i ( 1'b0 ),
|
||||
.en_i ( w_enable_q ),
|
||||
.req_i ( {axi_req_icache.w_valid, axi_req_bypass.w_valid, axi_req_data.w_valid} ),
|
||||
.ack_o ( ),
|
||||
.vld_o ( w_arbiter_valid ),
|
||||
.idx_o ( w_select )
|
||||
.inp_data_i ( {axi_req_icache.aw, axi_req_bypass.aw, axi_req_data.aw} ),
|
||||
.inp_valid_i ( {axi_req_icache.aw_valid & ~full, axi_req_bypass.aw_valid & ~full, axi_req_data.aw_valid & ~full} ),
|
||||
.inp_ready_o ( {axi_resp_icache.aw_ready, axi_resp_bypass.aw_ready, axi_resp_data.aw_ready} ),
|
||||
.oup_data_o ( axi_req_o.aw ),
|
||||
.oup_valid_o ( axi_req_o.aw_valid ),
|
||||
.oup_ready_i ( axi_resp_i.aw_ready )
|
||||
);
|
||||
|
||||
// WID has been removed in AXI 4 so we need to keep track which AW request has been accepted
|
||||
// to forward the correct write data.
|
||||
always_comb begin
|
||||
w_select = 0;
|
||||
unique case (axi_req_o.aw.id)
|
||||
4'b1111: w_select = 0; // dcache
|
||||
4'b1000, 4'b1001, 4'b1010, 4'b1011: w_select = 1; // bypass
|
||||
4'b0000: w_select = 2; // icache
|
||||
default: w_select = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
fifo_v3 #(
|
||||
.FALL_THROUGH ( 1'b1 ),
|
||||
.DATA_WIDTH ( 2 ),
|
||||
.DEPTH ( 4 )
|
||||
) i_fifo_w_channel (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( 1'b0 ),
|
||||
.testmode_i ( 1'b0 ),
|
||||
.full_o ( full ),
|
||||
.empty_o ( ), // leave open
|
||||
.usage_o ( ), // leave open
|
||||
.data_i ( w_select ),
|
||||
// a new transaction was requested
|
||||
.push_i ( axi_req_o.aw_valid & axi_resp_i.aw_ready & ~full ),
|
||||
// write ID to select the output MUX
|
||||
.data_o ( w_id ),
|
||||
// transaction has finished
|
||||
.pop_i ( axi_req_o.w_valid & axi_resp_i.w_ready & axi_req_o.w.last )
|
||||
);
|
||||
|
||||
stream_mux #(
|
||||
|
@ -185,39 +174,12 @@ module std_cache_subsystem #(
|
|||
.inp_data_i ( {axi_req_icache.w, axi_req_bypass.w, axi_req_data.w} ),
|
||||
.inp_valid_i ( {axi_req_icache.w_valid, axi_req_bypass.w_valid, axi_req_data.w_valid} ),
|
||||
.inp_ready_o ( {axi_resp_icache.w_ready, axi_resp_bypass.w_ready, axi_resp_data.w_ready} ),
|
||||
.inp_sel_i ( w_select ),
|
||||
.inp_sel_i ( w_id ),
|
||||
.oup_data_o ( axi_req_o.w ),
|
||||
.oup_valid_o ( axi_req_o.w_valid ),
|
||||
.oup_ready_i ( axi_resp_i.w_ready )
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
aw_enable_d = aw_enable_q;
|
||||
ar_enable_d = ar_enable_q;
|
||||
w_enable_d = w_enable_q;
|
||||
|
||||
// freeze the arbiter
|
||||
if (aw_arbiter_valid) aw_enable_d = 1'b0;
|
||||
if (ar_arbiter_valid) ar_enable_d = 1'b0;
|
||||
if (w_arbiter_valid) w_enable_d = 1'b0;
|
||||
// we've got a valid transaction, free the arbitration decision
|
||||
if (axi_resp_i.aw_ready && axi_req_o.aw_valid) aw_enable_d = 1'b1;
|
||||
if (axi_resp_i.ar_ready && axi_req_o.ar_valid) ar_enable_d = 1'b1;
|
||||
if (axi_resp_i.w_ready && axi_req_o.w_valid) w_enable_d = 1'b1;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
aw_enable_q <= 1'b1;
|
||||
ar_enable_q <= 1'b1;
|
||||
w_enable_q <= 1'b1;
|
||||
end else begin
|
||||
aw_enable_q <= aw_enable_d;
|
||||
ar_enable_q <= ar_enable_d;
|
||||
w_enable_q <= w_enable_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Route responses based on ID
|
||||
// 0000 -> I$
|
||||
// 10[00|10|01|11] -> Bypass
|
||||
|
@ -232,10 +194,10 @@ module std_cache_subsystem #(
|
|||
always_comb begin
|
||||
r_select = 0;
|
||||
unique case (axi_resp_i.r.id)
|
||||
4'b0000: r_select = 2; // icache
|
||||
4'b1111: r_select = 0; // dcache
|
||||
4'b1111: r_select = 0; // dcache
|
||||
4'b1000, 4'b1001, 4'b1010, 4'b1011: r_select = 1; // bypass
|
||||
default: r_select = 0;
|
||||
4'b0000: r_select = 2; // icache
|
||||
default: r_select = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -259,10 +221,10 @@ module std_cache_subsystem #(
|
|||
always_comb begin
|
||||
b_select = 0;
|
||||
unique case (axi_resp_i.b.id)
|
||||
4'b0000: b_select = 2; // icache
|
||||
4'b1111: b_select = 0; // dcache
|
||||
4'b1111: b_select = 0; // dcache
|
||||
4'b1000, 4'b1001, 4'b1010, 4'b1011: b_select = 1; // bypass
|
||||
default: b_select = 0;
|
||||
4'b0000: b_select = 2; // icache
|
||||
default: b_select = 0;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue