|
| 1 | +// Copyright 2023 ETH Zurich and University of Bologna. |
| 2 | +// Solderpad Hardware License, Version 0.51, see LICENSE for details. |
| 3 | +// SPDX-License-Identifier: SHL-0.51 |
| 4 | + |
| 5 | +// Authors: |
| 6 | +// - Thomas Benz <[email protected]> |
| 7 | + |
| 8 | +/// RT midend for the iDMA |
| 9 | +module idma_rt_midend #( |
| 10 | + /// Number of parallel events |
| 11 | + parameter int unsigned NumEvents = 32'd1, |
| 12 | + /// The width of the event counters (count multiple of clock period) |
| 13 | + parameter int unsigned EventCntWidth = 32'd32, |
| 14 | + /// Number of outstanding DMA events |
| 15 | + parameter int unsigned NumOutstanding = 32'd2, |
| 16 | + /// Address type |
| 17 | + parameter type addr_t = logic, |
| 18 | + /// ND iDMA request type |
| 19 | + parameter type idma_nd_req_t = logic, |
| 20 | + /// iDMA response type |
| 21 | + parameter type idma_rsp_t = logic, |
| 22 | + /// *DO NOT OVERWRITE*: Derived event counter type. |
| 23 | + parameter type event_cnt_t = logic [EventCntWidth-1:0] |
| 24 | +)( |
| 25 | + /// Clock |
| 26 | + input logic clk_i, |
| 27 | + /// Asynchronous reset, active low |
| 28 | + input logic rst_ni, |
| 29 | + /// The threshold an event is triggered |
| 30 | + input event_cnt_t [NumEvents-1:0] event_counts_i, |
| 31 | + /// The source address of the event |
| 32 | + input addr_t [NumEvents-1:0] src_addr_i, |
| 33 | + /// The destination address of the event |
| 34 | + input addr_t [NumEvents-1:0] dst_addr_i, |
| 35 | + /// The length of the event |
| 36 | + input addr_t [NumEvents-1:0] length_i, |
| 37 | + /// The source stride of the event |
| 38 | + input addr_t [NumEvents-1:0] src_1d_stride_i, |
| 39 | + /// The destination stride of the event |
| 40 | + input addr_t [NumEvents-1:0] dst_1d_stride_i, |
| 41 | + /// The number of repetitions of the event |
| 42 | + input addr_t [NumEvents-1:0] num_1d_reps_i, |
| 43 | + /// The source stride of the event |
| 44 | + input addr_t [NumEvents-1:0] src_2d_stride_i, |
| 45 | + /// The destination stride of the event |
| 46 | + input addr_t [NumEvents-1:0] dst_2d_stride_i, |
| 47 | + /// The number of repetitions of the event |
| 48 | + input addr_t [NumEvents-1:0] num_2d_reps_i, |
| 49 | + /// Enable the given event |
| 50 | + input logic [NumEvents-1:0] event_ena_i, |
| 51 | + /// Current state of the counters (debugging) |
| 52 | + output event_cnt_t [NumEvents-1:0] event_counts_o, |
| 53 | + /// ND iDMA request |
| 54 | + output idma_nd_req_t nd_req_o, |
| 55 | + /// ND iDMA request valid |
| 56 | + output logic nd_req_valid_o, |
| 57 | + /// ND iDMA request ready |
| 58 | + input logic nd_req_ready_i, |
| 59 | + /// iDMA 1D response |
| 60 | + input idma_rsp_t burst_rsp_i, |
| 61 | + /// iDMA 1D response valid |
| 62 | + input logic burst_rsp_valid_i, |
| 63 | + /// iDMA 1D response ready |
| 64 | + output logic burst_rsp_ready_o, |
| 65 | + /// Bypass: ND iDMA request |
| 66 | + input idma_nd_req_t nd_req_i, |
| 67 | + /// Bypass: ND iDMA request valid |
| 68 | + input logic nd_req_valid_i, |
| 69 | + /// Bypass: ND iDMA request ready |
| 70 | + output logic nd_req_ready_o, |
| 71 | + /// Bypass: iDMA 1D response |
| 72 | + output idma_rsp_t burst_rsp_o, |
| 73 | + /// Bypass: iDMA 1D response valid |
| 74 | + output logic burst_rsp_valid_o, |
| 75 | + /// Bypass: iDMA 1D response ready |
| 76 | + input logic burst_rsp_ready_i |
| 77 | +); |
| 78 | + |
| 79 | + typedef struct packed { |
| 80 | + idma_nd_req_t req; |
| 81 | + logic src; |
| 82 | + } ext_arb_t; |
| 83 | + |
| 84 | + // signals around the external arbiter |
| 85 | + ext_arb_t ext_req, int_req, out_req; |
| 86 | + |
| 87 | + // the choice signal |
| 88 | + logic choice, choice_head; |
| 89 | + |
| 90 | + // counter overflow -> event is valid |
| 91 | + logic [NumEvents-1:0] event_valid; |
| 92 | + |
| 93 | + // handshake the event |
| 94 | + logic [NumEvents-1:0] event_ready; |
| 95 | + |
| 96 | + // clear signal for the counter |
| 97 | + logic [NumEvents-1:0] cnt_load; |
| 98 | + |
| 99 | + // enable signal for the counter |
| 100 | + logic [NumEvents-1:0] cnt_ena; |
| 101 | + |
| 102 | + // each counter assembles the struct |
| 103 | + idma_nd_req_t [NumEvents-1:0] idma_nd_req; |
| 104 | + |
| 105 | + // internal request and its handshake signals |
| 106 | + idma_nd_req_t idma_nd_req_int; |
| 107 | + logic nd_req_valid_int; |
| 108 | + logic nd_req_ready_int; |
| 109 | + |
| 110 | + // internal response stub |
| 111 | + idma_rsp_t int_rsp; |
| 112 | + logic int_valid; |
| 113 | + |
| 114 | + // generate the counters timing the events and assemble the transfers |
| 115 | + for (genvar c = 0; c < NumEvents; c++) begin : gen_counters |
| 116 | + // counter instance |
| 117 | + counter #( |
| 118 | + .WIDTH ( EventCntWidth ), |
| 119 | + .STICKY_OVERFLOW ( 1'b0 ) |
| 120 | + ) i_counter ( |
| 121 | + .clk_i, |
| 122 | + .rst_ni, |
| 123 | + .clear_i ( 1'b0 ), |
| 124 | + .en_i ( cnt_ena [c] ), |
| 125 | + .load_i ( cnt_load [c] ), |
| 126 | + .down_i ( 1'b1 ), |
| 127 | + .d_i ( event_counts_i [c] ), |
| 128 | + .q_o ( event_counts_o [c] ), |
| 129 | + .overflow_o ( event_valid [c] ) |
| 130 | + ); |
| 131 | + |
| 132 | + // n-d assignment |
| 133 | + assign idma_nd_req[c].d_req[0].reps = num_1d_reps_i [c]; |
| 134 | + assign idma_nd_req[c].d_req[0].src_strides = src_1d_stride_i [c]; |
| 135 | + assign idma_nd_req[c].d_req[0].dst_strides = dst_1d_stride_i [c]; |
| 136 | + assign idma_nd_req[c].d_req[1].reps = num_1d_reps_i [c]; |
| 137 | + assign idma_nd_req[c].d_req[1].src_strides = src_1d_stride_i [c]; |
| 138 | + assign idma_nd_req[c].d_req[1].dst_strides = dst_1d_stride_i [c]; |
| 139 | + |
| 140 | + // 1D assignment |
| 141 | + assign idma_nd_req[c].burst_req.length = length_i [c]; |
| 142 | + assign idma_nd_req[c].burst_req.src_addr = src_addr_i [c]; |
| 143 | + assign idma_nd_req[c].burst_req.dst_addr = dst_addr_i [c]; |
| 144 | + assign idma_nd_req[c].burst_req.opt = '0; |
| 145 | + |
| 146 | + end |
| 147 | + |
| 148 | + // clear on handshake |
| 149 | + assign cnt_load = event_ready & event_valid; |
| 150 | + |
| 151 | + // disable counters if they are valid |
| 152 | + assign cnt_ena = event_ena_i & ~(event_valid); |
| 153 | + |
| 154 | + // arbitrates the events |
| 155 | + stream_arbiter #( |
| 156 | + .DATA_T ( idma_nd_req_t ), |
| 157 | + .N_INP ( NumEvents ), |
| 158 | + .ARBITER ( "rr" ) |
| 159 | + ) i_stream_arbiter ( |
| 160 | + .clk_i, |
| 161 | + .rst_ni, |
| 162 | + .inp_data_i ( idma_nd_req ), |
| 163 | + .inp_valid_i ( event_valid ), |
| 164 | + .inp_ready_o ( event_ready ), |
| 165 | + .oup_data_o ( idma_nd_req_int ), |
| 166 | + .oup_valid_o ( nd_req_valid_int ), |
| 167 | + .oup_ready_i ( nd_req_ready_int ) |
| 168 | + ); |
| 169 | + |
| 170 | + // arbitrates the events |
| 171 | + stream_arbiter #( |
| 172 | + .DATA_T ( ext_arb_t ), |
| 173 | + .N_INP ( 32'd2 ), |
| 174 | + .ARBITER ( "rr" ) |
| 175 | + ) i_stream_arbiter_bypass ( |
| 176 | + .clk_i, |
| 177 | + .rst_ni, |
| 178 | + .inp_data_i ( { ext_req, int_req } ), |
| 179 | + .inp_valid_i ( { nd_req_valid_i, nd_req_valid_int } ), |
| 180 | + .inp_ready_o ( { nd_req_ready_o, nd_req_ready_int } ), |
| 181 | + .oup_data_o ( out_req ), |
| 182 | + .oup_valid_o ( nd_req_valid_o ), |
| 183 | + .oup_ready_i ( nd_req_ready_i ) |
| 184 | + ); |
| 185 | + |
| 186 | + // assemble arbiter inputs |
| 187 | + assign ext_req.req = nd_req_i; |
| 188 | + assign ext_req.src = 1'b1; |
| 189 | + |
| 190 | + assign int_req.req = idma_nd_req_int; |
| 191 | + assign int_req.src = 1'b0; |
| 192 | + |
| 193 | + // arbiters outputs |
| 194 | + assign nd_req_o = out_req.req; |
| 195 | + assign choice = out_req.src; |
| 196 | + |
| 197 | + // safe the choice in a fifo |
| 198 | + stream_fifo #( |
| 199 | + .FALL_THROUGH ( 1'b0 ), |
| 200 | + .DATA_WIDTH ( 32'd1 ), |
| 201 | + .DEPTH ( NumOutstanding ) |
| 202 | + ) i_stream_fifo ( |
| 203 | + .clk_i, |
| 204 | + .rst_ni, |
| 205 | + .flush_i ( 1'b0 ), |
| 206 | + .testmode_i ( 1'b0 ), |
| 207 | + .usage_o ( /* NC */ ), |
| 208 | + .data_i ( choice ), |
| 209 | + .valid_i ( nd_req_valid_i & nd_req_ready_o ), |
| 210 | + .ready_o ( /* HACK: NC */ ), |
| 211 | + .data_o ( choice_head ), |
| 212 | + .valid_o ( /* HACK: NC */ ), |
| 213 | + .ready_i ( burst_rsp_valid_o & burst_rsp_ready_i ) |
| 214 | + ); |
| 215 | + |
| 216 | + // arbitration of responses |
| 217 | + stream_demux #( |
| 218 | + .N_OUP ( 32'd2 ) |
| 219 | + ) i_stream_demux ( |
| 220 | + .inp_valid_i ( burst_rsp_valid_i ), |
| 221 | + .inp_ready_o ( burst_rsp_ready_o ), |
| 222 | + .oup_sel_i ( choice_head ), |
| 223 | + .oup_valid_o ( { burst_rsp_valid_o, int_valid } ), |
| 224 | + .oup_ready_i ( { burst_rsp_ready_i, 1'b1 } ) |
| 225 | + ); |
| 226 | + |
| 227 | + assign burst_rsp_o = burst_rsp_i; |
| 228 | + |
| 229 | +endmodule |
0 commit comments