@@ -26,42 +26,69 @@ module tlul_fifo_sync #(
2626 output [SpareRspW- 1 : 0 ] spare_rsp_o
2727);
2828
29- // Put everything on the request side into one FIFO
30- localparam int unsigned REQFIFO_WIDTH = $bits (tlul_pkg :: tl_h2d_t) - 2 + SpareReqW;
29+ // Put everything on the request side into two FIFOs.
30+ // The first FIFO holds all data except the integrity bits of the `a_user` field. The second FIFO
31+ // only holds the command and data integrity bits of the `a_user` field. This is a FI
32+ // countermeasure, as a fault into one of the two FIFOs will trigger an integrity error once the
33+ // integrity bits are checked.
34+ localparam int unsigned REQFIFO_INTG_WIDTH = tlul_pkg :: H2DCmdIntgWidth + tlul_pkg :: DataIntgWidth;
35+ localparam int unsigned REQFIFO_WIDTH = $bits (tlul_pkg :: tl_h2d_t) - 2 + SpareReqW -
36+ REQFIFO_INTG_WIDTH ;
3137
3238 prim_fifo_sync # (.Width (REQFIFO_WIDTH ), .Pass (ReqPass), .Depth (ReqDepth)) reqfifo (
3339 .clk_i,
3440 .rst_ni,
3541 .clr_i (1'b0 ),
3642 .wvalid_i (tl_h_i.a_valid),
3743 .wready_o (tl_h_o.a_ready),
38- .wdata_i ({ tl_h_i.a_opcode ,
39- tl_h_i.a_param ,
40- tl_h_i.a_size ,
41- tl_h_i.a_source ,
42- tl_h_i.a_address,
43- tl_h_i.a_mask ,
44- tl_h_i.a_data ,
45- tl_h_i.a_user ,
44+ .wdata_i ({ tl_h_i.a_opcode ,
45+ tl_h_i.a_param ,
46+ tl_h_i.a_size ,
47+ tl_h_i.a_source ,
48+ tl_h_i.a_address ,
49+ tl_h_i.a_mask ,
50+ tl_h_i.a_data ,
51+ tl_h_i.a_user.rsvd ,
52+ tl_h_i.a_user.instr_type,
4653 spare_req_i} ),
4754 .rvalid_o (tl_d_o.a_valid),
4855 .rready_i (tl_d_i.a_ready),
49- .rdata_o ({ tl_d_o.a_opcode ,
50- tl_d_o.a_param ,
51- tl_d_o.a_size ,
52- tl_d_o.a_source ,
53- tl_d_o.a_address,
54- tl_d_o.a_mask ,
55- tl_d_o.a_data ,
56- tl_d_o.a_user ,
56+ .rdata_o ({ tl_d_o.a_opcode ,
57+ tl_d_o.a_param ,
58+ tl_d_o.a_size ,
59+ tl_d_o.a_source ,
60+ tl_d_o.a_address ,
61+ tl_d_o.a_mask ,
62+ tl_d_o.a_data ,
63+ tl_d_o.a_user.rsvd ,
64+ tl_d_o.a_user.instr_type,
5765 spare_req_o} ),
5866 .full_o (),
5967 .depth_o (),
6068 .err_o ());
6169
62- // Put everything on the response side into the other FIFO
70+ prim_fifo_sync # (.Width (REQFIFO_INTG_WIDTH ), .Pass (ReqPass), .Depth (ReqDepth)) reqfifo_intg (
71+ .clk_i,
72+ .rst_ni,
73+ .clr_i (1'b0 ),
74+ .wvalid_i (tl_h_i.a_valid),
75+ .wready_o (),
76+ .wdata_i ({ tl_h_i.a_user.cmd_intg,
77+ tl_h_i.a_user.data_intg} ),
78+ .rvalid_o (),
79+ .rready_i (tl_d_i.a_ready),
80+ .rdata_o ({ tl_d_o.a_user.cmd_intg,
81+ tl_d_o.a_user.data_intg} ),
82+ .full_o (),
83+ .depth_o (),
84+ .err_o ());
6385
64- localparam int unsigned RSPFIFO_WIDTH = $bits (tlul_pkg :: tl_d2h_t) - 2 + SpareRspW;
86+ // Put everything on the response side into the other two FIFOs.
87+ // The integrity bits and all other bits are separated into two different FIFOs for the same
88+ // reason as above.
89+ localparam int unsigned RSPFIFO_INTG_WIDTH = $bits (tlul_pkg :: tl_d_user_t);
90+ localparam int unsigned RSPFIFO_WIDTH = $bits (tlul_pkg :: tl_d2h_t) - 2 + SpareRspW -
91+ RSPFIFO_INTG_WIDTH ;
6592
6693 prim_fifo_sync # (.Width (RSPFIFO_WIDTH ), .Pass (RspPass), .Depth (RspDepth)) rspfifo (
6794 .clk_i,
@@ -76,7 +103,6 @@ module tlul_fifo_sync #(
76103 tl_d_i.d_sink ,
77104 (tl_d_i.d_opcode == tlul_pkg :: AccessAckData) ? tl_d_i.d_data :
78105 { top_pkg :: TL_DW { 1'b0 }} ,
79- tl_d_i.d_user ,
80106 tl_d_i.d_error ,
81107 spare_rsp_i} ),
82108 .rvalid_o (tl_h_o.d_valid),
@@ -87,11 +113,24 @@ module tlul_fifo_sync #(
87113 tl_h_o.d_source,
88114 tl_h_o.d_sink ,
89115 tl_h_o.d_data ,
90- tl_h_o.d_user ,
91116 tl_h_o.d_error ,
92117 spare_rsp_o} ),
93118 .full_o (),
94119 .depth_o (),
95120 .err_o ());
96121
122+ prim_fifo_sync # (.Width (RSPFIFO_INTG_WIDTH ), .Pass (RspPass), .Depth (RspDepth)) rspfifo_intg (
123+ .clk_i,
124+ .rst_ni,
125+ .clr_i (1'b0 ),
126+ .wvalid_i (tl_d_i.d_valid),
127+ .wready_o (),
128+ .wdata_i (tl_d_i.d_user ),
129+ .rvalid_o (),
130+ .rready_i (tl_h_i.d_ready),
131+ .rdata_o (tl_h_o.d_user ),
132+ .full_o (),
133+ .depth_o (),
134+ .err_o ());
135+
97136endmodule
0 commit comments