🐛 Fix potential AXI ordering issue

This commit is contained in:
Florian Zaruba 2018-11-26 17:55:10 +01:00
parent 932ef8a351
commit 91d7babc87
No known key found for this signature in database
GPG key ID: E742FFE8EC38A792
4 changed files with 28 additions and 25 deletions

View file

@ -1,4 +1,4 @@
## Buttons
\## Buttons
set_property -dict {PACKAGE_PIN R19 IOSTANDARD LVCMOS33} [get_ports cpu_resetn]
## PMOD Header JC

View file

@ -55,7 +55,7 @@ open_run synth_1
exec mkdir -p reports/
exec rm -rf reports/*
check_timing -file reports/$project.check_timing.rpt
check_timing -verbose -file reports/$project.check_timing.rpt
report_timing -max_paths 100 -nworst 100 -delay_type max -sort_by slack -file reports/$project.timing_WORST_100.rpt
report_timing -nworst 1 -delay_type max -sort_by group -file reports/$project.timing.rpt
report_utilization -hierarchical -file reports/$project.utilization.rpt

View file

@ -7,7 +7,7 @@ create_project $ipName . -part $partNumber
set_property board_part $boardName [current_project]
create_ip -name axi_gpio -vendor xilinx.com -library ip -module_name $ipName
set_property -dict [list CONFIG.C_GPIO_WIDTH {8} CONFIG.C_GPIO2_WIDTH {8} CONFIG.C_IS_DUAL {1} CONFIG.C_ALL_INPUTS_2 {1} CONFIG.C_INTERRUPT_PRESENT {0} CONFIG.GPIO_BOARD_INTERFACE {led_8bits} CONFIG.GPIO2_BOARD_INTERFACE {dip_switches_8bits}] [get_ips $ipName]
set_property -dict [list CONFIG.C_GPIO_WIDTH {8} CONFIG.C_GPIO2_WIDTH {8} CONFIG.C_IS_DUAL {1} CONFIG.C_ALL_INPUTS_2 {1} CONFIG.C_INTERRUPT_PRESENT {0}] [get_ips $ipName]
generate_target {instantiation_template} [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci]
generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci]

View file

@ -101,8 +101,9 @@ module std_cache_subsystem #(
// -----------------------
// Arbitrate AXI Ports
// -----------------------
logic [1:0] w_select, w_id;
logic full;
logic [1:0] w_select, w_select_fifo, w_select_arbiter;
logic w_fifo_empty;
// AR Channel
stream_arbiter #(
@ -127,7 +128,7 @@ module std_cache_subsystem #(
.clk_i,
.rst_ni,
.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_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} ),
.oup_data_o ( axi_req_o.aw ),
.oup_valid_o ( axi_req_o.aw_valid ),
@ -139,42 +140,47 @@ module std_cache_subsystem #(
always_comb begin
w_select = 0;
unique case (axi_req_o.aw.id)
4'b1111: w_select = 0; // dcache
4'b1100: w_select = 2; // dcache
4'b1000, 4'b1001, 4'b1010, 4'b1011: w_select = 1; // bypass
4'b0000: w_select = 2; // icache
default: w_select = 0;
default: w_select = 0; // icache
endcase
end
// TODO(zarubaf): This causes a cycle delay, might be optimize-able, FALL_THROUGH
// option made problems during synthesis (timing loop)
fifo_v3 #(
.FALL_THROUGH ( 1'b1 ),
.DATA_WIDTH ( 2 ),
// we can have a maximum of 4 oustanding transactions as each port is blocking
.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
.full_o ( ), // leave open
.empty_o ( w_fifo_empty ),
.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 ),
// a new transaction was requested and granted
.push_i ( axi_req_o.aw_valid & axi_resp_i.aw_ready ),
// write ID to select the output MUX
.data_o ( w_id ),
.data_o ( w_select_fifo ),
// transaction has finished
.pop_i ( axi_req_o.w_valid & axi_resp_i.w_ready & axi_req_o.w.last )
);
// icache will never write so select it as default (e.g.: when no arbitration is active)
// this is equal to setting it to zero
assign w_select_arbiter = (w_fifo_empty) ? 0 : w_select_fifo;
stream_mux #(
.DATA_T ( ariane_axi::w_chan_t ),
.N_INP ( 3 )
) i_stream_mux_w (
.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_id ),
.inp_data_i ( {axi_req_data.w, axi_req_bypass.w, axi_req_icache.w} ),
.inp_valid_i ( {axi_req_data.w_valid, axi_req_bypass.w_valid, axi_req_icache.w_valid} ),
.inp_ready_o ( {axi_resp_data.w_ready, axi_resp_bypass.w_ready, axi_resp_icache.w_ready} ),
.inp_sel_i ( w_select_arbiter ),
.oup_data_o ( axi_req_o.w ),
.oup_valid_o ( axi_req_o.w_valid ),
.oup_ready_i ( axi_resp_i.w_ready )
@ -183,7 +189,7 @@ module std_cache_subsystem #(
// Route responses based on ID
// 0000 -> I$
// 10[00|10|01|11] -> Bypass
// 1111 -> D$
// 1100 -> D$
// R Channel
assign axi_resp_icache.r = axi_resp_i.r;
assign axi_resp_bypass.r = axi_resp_i.r;
@ -194,7 +200,7 @@ module std_cache_subsystem #(
always_comb begin
r_select = 0;
unique case (axi_resp_i.r.id)
4'b1111: r_select = 0; // dcache
4'b1100: r_select = 0; // dcache
4'b1000, 4'b1001, 4'b1010, 4'b1011: r_select = 1; // bypass
4'b0000: r_select = 2; // icache
default: r_select = 0;
@ -221,7 +227,7 @@ module std_cache_subsystem #(
always_comb begin
b_select = 0;
unique case (axi_resp_i.b.id)
4'b1111: b_select = 0; // dcache
4'b1100: b_select = 0; // dcache
4'b1000, 4'b1001, 4'b1010, 4'b1011: b_select = 1; // bypass
4'b0000: b_select = 2; // icache
default: b_select = 0;
@ -238,7 +244,6 @@ module std_cache_subsystem #(
.oup_ready_i ( {axi_req_icache.b_ready, axi_req_bypass.b_ready, axi_req_data.b_ready} )
);
///////////////////////////////////////////////////////
// assertions
///////////////////////////////////////////////////////
@ -266,6 +271,4 @@ module std_cache_subsystem #(
`endif
//pragma translate_on
endmodule // std_cache_subsystem