17 #ifndef __AXISLAVETOREG_H__ 18 #define __AXISLAVETOREG_H__ 22 #include <hls_globals.h> 24 #include <mem_array.h> 54 template <
typename axiCfg,
int numReg,
int numAddrBitsToInspect = axiCfg::addrW
idth>
57 static const int kDebugLevel = 5;
62 sc_in<bool> reset_bar;
64 typename axi4_::read::template slave<> if_axi_rd;
65 typename axi4_::write::template slave<> if_axi_wr;
68 static const int bytesPerReg = axi4_::DATA_WIDTH >> 3;
71 sc_in<NVUINTW(numAddrBitsToInspect)> baseAddr;
74 sc_out<NVUINTW(axi4_::DATA_WIDTH)> regOut[numReg];
79 reset_bar(
"reset_bar"),
80 if_axi_rd(
"if_axi_rd"),
81 if_axi_wr(
"if_axi_wr")
84 sensitive << clk.pos();
85 async_reset_signal_is(reset_bar,
false);
93 NVUINTW(axi4_::DATA_WIDTH) reg[numReg];
94 NVUINTW(numAddrBitsToInspect) maxValidAddr = baseAddr.read() + bytesPerReg*numReg - 1;
96 #pragma hls_unroll yes 97 for (
int i=0; i<numReg; i++) {
99 regOut[i].write(reg[i]);
108 NVUINTW(numAddrBitsToInspect) axiRdAddr;
109 NVUINTW(axi4_::ALEN_WIDTH) axiRdLen;
111 NVUINTW(numAddrBitsToInspect) axiWrAddr;
114 bool read_arb_req = 0;
115 bool write_arb_req = 0;
116 bool arb_needs_update = 1;
121 #pragma hls_pipeline_init_interval 1 122 #pragma pipeline_stall_mode flush 126 valid_mask = write_arb_req << 1 | read_arb_req;
127 if (arb_needs_update) {
128 select_mask = arb.pick(valid_mask);
129 if (select_mask != 0) arb_needs_update = 0;
133 if (if_axi_rd.nb_aread(axi_rd_req)) {
135 NVUINTW(numAddrBitsToInspect) addr_temp(
static_cast<sc_uint<numAddrBitsToInspect>
>(axi_rd_req.addr));
136 NVUINTW(axi4_::ALEN_WIDTH) len_temp(
static_cast< sc_uint<axi4_::ALEN_WIDTH>
>(axi_rd_req.len));
137 axiRdAddr = addr_temp;
142 if (!write_arb_req) {
143 if (if_axi_wr.aw.PopNB(axi_wr_req_addr)) {
145 NVUINTW(numAddrBitsToInspect) addr_temp(
static_cast< sc_uint<numAddrBitsToInspect>
>(axi_wr_req_addr.addr));
146 axiWrAddr = addr_temp;
150 if (select_mask == 1) {
151 valid_rd_addr = (axiRdAddr >= baseAddr.read() && axiRdAddr <= maxValidAddr);
153 NVUINTW(regAddrWidth) regAddr = (axiRdAddr - baseAddr.read()) >> axiAddrBitsPerReg;
154 axi_rd_resp.id = axi_rd_req.id;
156 axi_rd_resp.resp = axi4_::Enc::XRESP::OKAY;
157 NVUINTW(axi4_::DATA_WIDTH) read_data;
158 axi_rd_resp.data = reg[regAddr];
161 axi_rd_resp.resp = axi4_::Enc::XRESP::SLVERR;
164 axi_rd_resp.last = 1;
166 arb_needs_update = 1;
168 axi_rd_resp.last = 0;
170 axiRdAddr += bytesPerReg;
172 if_axi_rd.rwrite(axi_rd_resp);
173 CDCOUT(sc_time_stamp() <<
" " << name() <<
" Read from local reg:" 174 <<
" axi_addr=" << hex << axiRdAddr.to_int64()
175 <<
" reg_addr=" << regAddr.to_int64()
176 <<
" data=" << hex << axi_rd_resp.data
177 << endl, kDebugLevel);
178 }
else if (select_mask == 2) {
179 if (if_axi_wr.w.PopNB(axi_wr_req_data)) {
180 valid_wr_addr = (axiWrAddr >= baseAddr.read() && axiWrAddr <= maxValidAddr);
182 NVUINTW(axi4_::DATA_WIDTH) axiData(static_cast<typename axi4_::Data>(axi_wr_req_data.data));
183 NVUINTW(regAddrWidth) regAddr = (axiWrAddr - baseAddr.read()) >> axiAddrBitsPerReg;
184 if (!axi_wr_req_data.wstrb.and_reduce()) {
185 NVUINTW(axi4_::DATA_WIDTH) old_data = reg[regAddr];
186 #pragma hls_unroll yes 187 for (
int i=0; i<axi4_::WSTRB_WIDTH; i++) {
188 if (axi_wr_req_data.wstrb[i] == 0) {
189 axiData =
nvhls::set_slc(axiData, nvhls::get_slc<8>(old_data,8*i), 8*i);
193 #pragma hls_unroll yes 194 for (
int i=0; i<numReg; i++) {
199 CDCOUT(sc_time_stamp() <<
" " << name() <<
" Wrote to local reg:" 200 <<
" axi_addr=" << hex << axiWrAddr.to_int64()
201 <<
" reg_addr=" << regAddr.to_int64()
202 <<
" data=" << hex << axi_wr_req_data.data
203 <<
" wstrb=" << hex << axi_wr_req_data.wstrb.to_uint64()
204 << endl, kDebugLevel);
205 if (axi_wr_req_data.last == 1) {
207 arb_needs_update = 1;
208 if (axiCfg::useWriteResponses) {
209 axi_wr_resp.id = axi_wr_req_addr.id;
211 axi_wr_resp.resp = axi4_::Enc::XRESP::OKAY;
213 axi_wr_resp.resp = axi4_::Enc::XRESP::SLVERR;
215 if_axi_wr.bwrite(axi_wr_resp);
218 axiWrAddr += bytesPerReg;
222 #pragma hls_unroll yes 223 for (
int i=0; i<numReg; i++) {
224 regOut[i].write(reg[i]);
An AXI slave containing memory-mapped registers.
type1 set_slc(type1 X, type2 Y, const unsigned int i)
Function that replaces slice of bits.
A struct composed of the signals associated with an AXI write response.
NVUINTW(Wrapped< T >::width) TypeToNVUINT(T in)
Convert Type to NVUINT.
A struct composed of the signals associated with AXI write data.
A struct composed of the signals associated with AXI read and write requests.
A struct composed of the signals associated with an AXI read response.
The base axi4 class parameterized according a valid config.
Compute Celing of log2 of a constant.
#define NVHLS_ASSERT_MSG(X, MSG)
A generalized implementation of generic n-way roundrobin arbiter.