Looking at the BVF_RISCV_SUBSYSTEM (DEFAULT configuration) in Libero, there is an APB_ARBITER which spits the FIC3 APB bus into two address spaces, high and low. This is implemented in Verilog in apb_arbiter.v. It is pretty simple, but Iā€™m mystified by one point; the last three lines are:

assign in_prdata = out_low_prdata | out_high_prdata;

assign in_pready = (in_psel & !in_paddr[select_bit]) ? out_low_pready : out_high_pready;

assign in_pslverr = (in_psel & !in_paddr[select_bit]) ? out_low_pslverr : out_high_pslverr;

Since there is no requirement that a peripheral drive the prdata bus low when not selected, the first statement does not make sense. I would expect it to be:

assign in_prdata =  (in_psel & !in_paddr[select_bit]) ? out_low_prdata : out_high_prdata;

What am I missing?

Digging in more, downstream of this component, is always a CoreAPB3. This component ensures that prdata is zero if none of its slots is selected. Hence, the simple ā€œ|ā€ works.