diff --git a/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv b/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv index 504fed223..a57560972 100644 --- a/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv +++ b/hw/core-v-mini-mcu/ao_peripheral_subsystem.sv @@ -82,8 +82,8 @@ module ao_peripheral_subsystem input obi_resp_t dma_read_ch0_resp_i, output obi_req_t dma_write_ch0_req_o, input obi_resp_t dma_write_ch0_resp_i, - output obi_req_t dma_addr_ch0_req_o, - input obi_resp_t dma_addr_ch0_resp_i, + output obi_req_t dma_addr_bcst_ch0_req_o, + input obi_resp_t dma_addr_bcst_ch0_resp_i, output logic dma_done_intr_o, output logic dma_window_intr_o, @@ -392,8 +392,8 @@ module ao_peripheral_subsystem .dma_read_ch0_resp_i, .dma_write_ch0_req_o, .dma_write_ch0_resp_i, - .dma_addr_ch0_req_o, - .dma_addr_ch0_resp_i, + .dma_addr_bcst_ch0_req_o, + .dma_addr_bcst_ch0_resp_i, .trigger_slot_i(dma_trigger_slots), .dma_done_intr_o(dma_done_intr_o), .dma_window_intr_o(dma_window_intr_o) diff --git a/hw/core-v-mini-mcu/core_v_mini_mcu.sv b/hw/core-v-mini-mcu/core_v_mini_mcu.sv index 3b86b0954..461cc0657 100644 --- a/hw/core-v-mini-mcu/core_v_mini_mcu.sv +++ b/hw/core-v-mini-mcu/core_v_mini_mcu.sv @@ -294,8 +294,8 @@ module core_v_mini_mcu input obi_resp_t ext_dma_read_ch0_resp_i, output obi_req_t ext_dma_write_ch0_req_o, input obi_resp_t ext_dma_write_ch0_resp_i, - output obi_req_t ext_dma_addr_ch0_req_o, - input obi_resp_t ext_dma_addr_ch0_resp_i, + output obi_req_t ext_dma_addr_bcst_ch0_req_o, + input obi_resp_t ext_dma_addr_bcst_ch0_resp_i, output reg_req_t ext_peripheral_slave_req_o, input reg_rsp_t ext_peripheral_slave_resp_i, @@ -349,8 +349,8 @@ module core_v_mini_mcu obi_resp_t dma_read_ch0_resp; obi_req_t dma_write_ch0_req; obi_resp_t dma_write_ch0_resp; - obi_req_t dma_addr_ch0_req; - obi_resp_t dma_addr_ch0_resp; + obi_req_t dma_addr_bcst_ch0_req; + obi_resp_t dma_addr_bcst_ch0_resp; // ram signals obi_req_t [core_v_mini_mcu_pkg::NUM_BANKS-1:0] ram_slave_req; @@ -510,8 +510,8 @@ module core_v_mini_mcu .dma_read_ch0_resp_o(dma_read_ch0_resp), .dma_write_ch0_req_i(dma_write_ch0_req), .dma_write_ch0_resp_o(dma_write_ch0_resp), - .dma_addr_ch0_req_i(dma_addr_ch0_req), - .dma_addr_ch0_resp_o(dma_addr_ch0_resp), + .dma_addr_bcst_ch0_req_i(dma_addr_bcst_ch0_req), + .dma_addr_bcst_ch0_resp_o(dma_addr_bcst_ch0_resp), .ext_xbar_master_req_i(ext_xbar_master_req_i), .ext_xbar_master_resp_o(ext_xbar_master_resp_o), .ram_req_o(ram_slave_req), @@ -534,8 +534,8 @@ module core_v_mini_mcu .ext_dma_read_ch0_resp_i(ext_dma_read_ch0_resp_i), .ext_dma_write_ch0_req_o(ext_dma_write_ch0_req_o), .ext_dma_write_ch0_resp_i(ext_dma_write_ch0_resp_i), - .ext_dma_addr_ch0_req_o(ext_dma_addr_ch0_req_o), - .ext_dma_addr_ch0_resp_i(ext_dma_addr_ch0_resp_i) + .ext_dma_addr_bcst_ch0_req_o(ext_dma_addr_bcst_ch0_req_o), + .ext_dma_addr_bcst_ch0_resp_i(ext_dma_addr_bcst_ch0_resp_i) ); memory_subsystem #( @@ -605,8 +605,8 @@ module core_v_mini_mcu .dma_read_ch0_resp_i(dma_read_ch0_resp), .dma_write_ch0_req_o(dma_write_ch0_req), .dma_write_ch0_resp_i(dma_write_ch0_resp), - .dma_addr_ch0_req_o(dma_addr_ch0_req), - .dma_addr_ch0_resp_i(dma_addr_ch0_resp), + .dma_addr_bcst_ch0_req_o(dma_addr_bcst_ch0_req), + .dma_addr_bcst_ch0_resp_i(dma_addr_bcst_ch0_resp), .dma_done_intr_o(dma_done_intr), .dma_window_intr_o(dma_window_intr), .spi_intr_event_o(spi_intr), diff --git a/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl b/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl index 4dcfc0f01..8a56f65ab 100644 --- a/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl +++ b/hw/core-v-mini-mcu/core_v_mini_mcu.sv.tpl @@ -48,8 +48,8 @@ ${pad.core_v_mini_mcu_interface} input obi_resp_t ext_dma_read_ch0_resp_i, output obi_req_t ext_dma_write_ch0_req_o, input obi_resp_t ext_dma_write_ch0_resp_i, - output obi_req_t ext_dma_addr_ch0_req_o, - input obi_resp_t ext_dma_addr_ch0_resp_i, + output obi_req_t ext_dma_addr_bcst_ch0_req_o, + input obi_resp_t ext_dma_addr_bcst_ch0_resp_i, output reg_req_t ext_peripheral_slave_req_o, input reg_rsp_t ext_peripheral_slave_resp_i, @@ -103,8 +103,8 @@ ${pad.core_v_mini_mcu_interface} obi_resp_t dma_read_ch0_resp; obi_req_t dma_write_ch0_req; obi_resp_t dma_write_ch0_resp; - obi_req_t dma_addr_ch0_req; - obi_resp_t dma_addr_ch0_resp; + obi_req_t dma_addr_bcst_ch0_req; + obi_resp_t dma_addr_bcst_ch0_resp; // ram signals obi_req_t [core_v_mini_mcu_pkg::NUM_BANKS-1:0] ram_slave_req; @@ -264,8 +264,8 @@ ${pad.core_v_mini_mcu_interface} .dma_read_ch0_resp_o(dma_read_ch0_resp), .dma_write_ch0_req_i(dma_write_ch0_req), .dma_write_ch0_resp_o(dma_write_ch0_resp), - .dma_addr_ch0_req_i(dma_addr_ch0_req), - .dma_addr_ch0_resp_o(dma_addr_ch0_resp), + .dma_addr_bcst_ch0_req_i(dma_addr_bcst_ch0_req), + .dma_addr_bcst_ch0_resp_o(dma_addr_bcst_ch0_resp), .ext_xbar_master_req_i(ext_xbar_master_req_i), .ext_xbar_master_resp_o(ext_xbar_master_resp_o), .ram_req_o(ram_slave_req), @@ -288,8 +288,8 @@ ${pad.core_v_mini_mcu_interface} .ext_dma_read_ch0_resp_i(ext_dma_read_ch0_resp_i), .ext_dma_write_ch0_req_o(ext_dma_write_ch0_req_o), .ext_dma_write_ch0_resp_i(ext_dma_write_ch0_resp_i), - .ext_dma_addr_ch0_req_o(ext_dma_addr_ch0_req_o), - .ext_dma_addr_ch0_resp_i(ext_dma_addr_ch0_resp_i) + .ext_dma_addr_bcst_ch0_req_o(ext_dma_addr_bcst_ch0_req_o), + .ext_dma_addr_bcst_ch0_resp_i(ext_dma_addr_bcst_ch0_resp_i) ); memory_subsystem #( @@ -357,8 +357,8 @@ ${pad.core_v_mini_mcu_interface} .dma_read_ch0_resp_i(dma_read_ch0_resp), .dma_write_ch0_req_o(dma_write_ch0_req), .dma_write_ch0_resp_i(dma_write_ch0_resp), - .dma_addr_ch0_req_o(dma_addr_ch0_req), - .dma_addr_ch0_resp_i(dma_addr_ch0_resp), + .dma_addr_bcst_ch0_req_o(dma_addr_bcst_ch0_req), + .dma_addr_bcst_ch0_resp_i(dma_addr_bcst_ch0_resp), .dma_done_intr_o(dma_done_intr), .dma_window_intr_o(dma_window_intr), .spi_intr_event_o(spi_intr), diff --git a/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl b/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl index 660022e18..3349f1f49 100644 --- a/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl +++ b/hw/core-v-mini-mcu/include/core_v_mini_mcu_pkg.sv.tpl @@ -39,7 +39,7 @@ package core_v_mini_mcu_pkg; localparam logic [31:0] DEBUG_MASTER_IDX = 2; localparam logic [31:0] DMA_READ_CH0_IDX = 3; localparam logic [31:0] DMA_WRITE_CH0_IDX = 4; - localparam logic [31:0] DMA_ADDR_CH0_IDX = 5; + localparam logic [31:0] DMA_ADDR_BCST_CH0_IDX = 5; localparam SYSTEM_XBAR_NMASTER = 6; diff --git a/hw/core-v-mini-mcu/system_bus.sv.tpl b/hw/core-v-mini-mcu/system_bus.sv.tpl index b7dbbfdc0..757b0a23d 100644 --- a/hw/core-v-mini-mcu/system_bus.sv.tpl +++ b/hw/core-v-mini-mcu/system_bus.sv.tpl @@ -43,8 +43,8 @@ module system_bus input obi_req_t dma_write_ch0_req_i, output obi_resp_t dma_write_ch0_resp_o, - input obi_req_t dma_addr_ch0_req_i, - output obi_resp_t dma_addr_ch0_resp_o, + input obi_req_t dma_addr_bcst_ch0_req_i, + output obi_resp_t dma_addr_bcst_ch0_resp_o, // External master ports input obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_xbar_master_req_i, @@ -82,8 +82,8 @@ module system_bus output obi_req_t ext_dma_write_ch0_req_o, input obi_resp_t ext_dma_write_ch0_resp_i, - output obi_req_t ext_dma_addr_ch0_req_o, - input obi_resp_t ext_dma_addr_ch0_resp_i + output obi_req_t ext_dma_addr_bcst_ch0_req_o, + input obi_resp_t ext_dma_addr_bcst_ch0_resp_i ); import core_v_mini_mcu_pkg::*; @@ -121,7 +121,7 @@ module system_bus assign int_master_req[core_v_mini_mcu_pkg::DEBUG_MASTER_IDX] = debug_master_req_i; assign int_master_req[core_v_mini_mcu_pkg::DMA_READ_CH0_IDX] = dma_read_ch0_req_i; assign int_master_req[core_v_mini_mcu_pkg::DMA_WRITE_CH0_IDX] = dma_write_ch0_req_i; - assign int_master_req[core_v_mini_mcu_pkg::DMA_ADDR_CH0_IDX] = dma_addr_ch0_req_i; + assign int_master_req[core_v_mini_mcu_pkg::DMA_ADDR_BCST_CH0_IDX] = dma_addr_bcst_ch0_req_i; // Internal + external master requests generate @@ -144,7 +144,7 @@ module system_bus assign debug_master_resp_o = int_master_resp[core_v_mini_mcu_pkg::DEBUG_MASTER_IDX]; assign dma_read_ch0_resp_o = int_master_resp[core_v_mini_mcu_pkg::DMA_READ_CH0_IDX]; assign dma_write_ch0_resp_o = int_master_resp[core_v_mini_mcu_pkg::DMA_WRITE_CH0_IDX]; - assign dma_addr_ch0_resp_o = int_master_resp[core_v_mini_mcu_pkg::DMA_ADDR_CH0_IDX]; + assign dma_addr_bcst_ch0_resp_o = int_master_resp[core_v_mini_mcu_pkg::DMA_ADDR_BCST_CH0_IDX]; // External master responses if (EXT_XBAR_NMASTER == 0) begin @@ -171,7 +171,7 @@ module system_bus assign ext_debug_master_req_o = demux_xbar_req[DEBUG_MASTER_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; assign ext_dma_read_ch0_req_o = demux_xbar_req[DMA_READ_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; assign ext_dma_write_ch0_req_o = demux_xbar_req[DMA_WRITE_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; - assign ext_dma_addr_ch0_req_o = demux_xbar_req[DMA_ADDR_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; + assign ext_dma_addr_bcst_ch0_req_o = demux_xbar_req[DMA_ADDR_BCST_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX]; // Internal slave responses assign int_slave_resp[core_v_mini_mcu_pkg::ERROR_IDX] = error_slave_resp; @@ -189,7 +189,7 @@ module system_bus assign demux_xbar_resp[DEBUG_MASTER_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_debug_master_resp_i; assign demux_xbar_resp[DMA_READ_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_read_ch0_resp_i; assign demux_xbar_resp[DMA_WRITE_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_write_ch0_resp_i; - assign demux_xbar_resp[DMA_ADDR_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_addr_ch0_resp_i; + assign demux_xbar_resp[DMA_ADDR_BCST_CH0_IDX][DEMUX_XBAR_EXT_SLAVE_IDX] = ext_dma_addr_bcst_ch0_resp_i; `ifndef SYNTHESIS always_ff @(posedge clk_i, negedge rst_ni) begin : check_out_of_bound diff --git a/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv b/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv index de6ab4582..dc078ce4a 100644 --- a/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv +++ b/hw/fpga/xilinx_core_v_mini_mcu_wrapper.sv @@ -123,8 +123,8 @@ module xilinx_core_v_mini_mcu_wrapper .ext_dma_read_ch0_resp_i('0), .ext_dma_write_ch0_req_o(), .ext_dma_write_ch0_resp_i('0), - .ext_dma_addr_ch0_req_o(), - .ext_dma_addr_ch0_resp_i('0), + .ext_dma_addr_bcst_ch0_req_o(), + .ext_dma_addr_bcst_ch0_resp_i('0), .ext_peripheral_slave_req_o(), .ext_peripheral_slave_resp_i('0), .external_subsystem_powergate_switch_no(), diff --git a/hw/ip/dma/data/dma.hjson b/hw/ip/dma/data/dma.hjson index d37d92f71..fb136200c 100644 --- a/hw/ip/dma/data/dma.hjson +++ b/hw/ip/dma/data/dma.hjson @@ -25,12 +25,12 @@ { bits: "31:0", name: "PTR_OUT", desc: "Output data pointer (word aligned)" } ] }, - { name: "ADDR_PTR", - desc: "Addess data pointer (word aligned)", + { name: "ADDR_BCST_PTR", + desc: "Addess/Broadcast data pointer (word aligned)", swaccess: "rw", hwaccess: "hro", fields: [ - { bits: "31:0", name: "PTR_ADDR", desc: "Address data pointer (word aligned) - used only in Address mode" } + { bits: "31:0", name: "PTR_ADDR", desc: "Address/Broadcast data pointer (word aligned) - used only in Address and Broadcast modes" } ] }, { name: "SIZE", @@ -68,6 +68,11 @@ name: "DST_PTR_INC", desc: "Destination pointer increment", resval:4 + }, + { bits: "23:16", + name: "BCST_PTR_INC", + desc: "Broadcast pointer increment", + resval:4 } ] }, @@ -87,6 +92,22 @@ } ] }, + { name: "BSLOT", + desc: '''The DMA will wait for the signal + connected to the selected trigger_slots to be high + on the read and write side respectivly''', + swaccess: "rw", + hwaccess: "hro", + resval: 0, + fields: [ + { bits: "15:0", name: "BX_TRIGGER_SLOT", + desc: "Broadcast slot selection mask" + }, + { bits: "31:16", name: "DX_TRIGGER_SLOT", + desc: "Dummy slot selection mask" + } + ] + }, { name: "DATA_TYPE", desc: '''Width/type of the data to transfer''', swaccess: "rw", @@ -115,6 +136,7 @@ { value: "0", name: "LINEAR_MODE", desc: "Transfers data linearly"}, { value: "1", name: "CIRCULAR_MODE", desc: "Transfers data in circular mode"}, { value: "2", name: "ADDRESS_MODE" , desc: "Transfers data using as destination address the data from ADD_PTR"}, + { value: "3", name: "BROADCAST_MODE" , desc: "Equivalent to LINEAR_MODE but writing at two destinations simultaneously"}, ] } ] diff --git a/hw/ip/dma/rtl/dma.sv b/hw/ip/dma/rtl/dma.sv index c4f5e2eac..6a67c8338 100644 --- a/hw/ip/dma/rtl/dma.sv +++ b/hw/ip/dma/rtl/dma.sv @@ -24,8 +24,8 @@ module dma #( output obi_req_t dma_write_ch0_req_o, input obi_resp_t dma_write_ch0_resp_i, - output obi_req_t dma_addr_ch0_req_o, - input obi_resp_t dma_addr_ch0_resp_i, + output obi_req_t dma_addr_bcst_ch0_req_o, + input obi_resp_t dma_addr_bcst_ch0_resp_i, input logic [SLOT_NUM-1:0] trigger_slot_i, @@ -42,7 +42,7 @@ module dma #( dma_hw2reg_t hw2reg; logic [ 31:0] read_ptr_reg; - logic [ 31:0] addr_ptr_reg; + logic [ 31:0] addr_bcst_ptr_reg; logic [ 31:0] read_ptr_valid_reg; logic [ 31:0] write_ptr_reg; logic [ 31:0] write_address; @@ -69,13 +69,15 @@ module dma #( logic data_in_rvalid; logic [ 31:0] data_in_rdata; - logic data_addr_in_req; - logic data_addr_in_we; - logic [ 3:0] data_addr_in_be; - logic [ 31:0] data_addr_in_addr; - logic data_addr_in_gnt; - logic data_addr_in_rvalid; - logic [ 31:0] data_addr_in_rdata; + logic data_addr_bcst_inout_req; + logic data_addr_bcst_inout_we; + logic [ 3:0] data_addr_bcst_inout_be; + logic [ 31:0] data_addr_bcst_inout_addr; + logic data_addr_bcst_inout_gnt; + logic data_addr_bcst_inout_rvalid; + logic [ 31:0] data_addr_bcst_inout_rdata; + + logic [ 31:0] data_addr_bcst_inout_wdata; logic data_out_req; logic data_out_we; @@ -105,12 +107,16 @@ module dma #( logic [31:0] fifo_addr_output; logic [ 3:0] byte_enable_out; + logic [ 3:0] bcst_byte_enable_out; logic circular_mode; logic address_mode; + logic broadcast_mode; logic dma_start_pending; + logic broadcast_pop, data_out_gnt_q, data_addr_bcst_inout_q; + enum { DMA_READY, DMA_STARTING, @@ -132,6 +138,7 @@ module dma #( } dma_write_fsm_state, dma_write_fsm_n_state; + // READ channel assign dma_read_ch0_req_o.req = data_in_req; assign dma_read_ch0_req_o.we = data_in_we; assign dma_read_ch0_req_o.be = data_in_be; @@ -142,16 +149,18 @@ module dma #( assign data_in_rvalid = dma_read_ch0_resp_i.rvalid; assign data_in_rdata = dma_read_ch0_resp_i.rdata; - assign dma_addr_ch0_req_o.req = data_addr_in_req; - assign dma_addr_ch0_req_o.we = data_addr_in_we; - assign dma_addr_ch0_req_o.be = data_addr_in_be; - assign dma_addr_ch0_req_o.addr = data_addr_in_addr; - assign dma_addr_ch0_req_o.wdata = 32'h0; + // ADDRESS+BROADCAST channel + assign dma_addr_bcst_ch0_req_o.req = data_addr_bcst_inout_req; + assign dma_addr_bcst_ch0_req_o.we = data_addr_bcst_inout_we; + assign dma_addr_bcst_ch0_req_o.be = data_addr_bcst_inout_be; + assign dma_addr_bcst_ch0_req_o.addr = data_addr_bcst_inout_addr; + assign dma_addr_bcst_ch0_req_o.wdata = data_addr_bcst_inout_wdata; - assign data_addr_in_gnt = dma_addr_ch0_resp_i.gnt; - assign data_addr_in_rvalid = dma_addr_ch0_resp_i.rvalid; - assign data_addr_in_rdata = dma_addr_ch0_resp_i.rdata; + assign data_addr_bcst_inout_gnt = dma_addr_bcst_ch0_resp_i.gnt; + assign data_addr_bcst_inout_rvalid = dma_addr_bcst_ch0_resp_i.rvalid; + assign data_addr_bcst_inout_rdata = dma_addr_bcst_ch0_resp_i.rdata; + // WRITE channel assign dma_write_ch0_req_o.req = data_out_req; assign dma_write_ch0_req_o.we = data_out_we; assign dma_write_ch0_req_o.be = data_out_be; @@ -177,6 +186,7 @@ module dma #( assign circular_mode = reg2hw.mode.q == 1; assign address_mode = reg2hw.mode.q == 2; + assign broadcast_mode = reg2hw.mode.q == 3; assign write_address = address_mode ? fifo_addr_output : write_ptr_reg; @@ -257,12 +267,14 @@ module dma #( // Store address data pointer and increment everytime read request is granted - only in address mode always_ff @(posedge clk_i or negedge rst_ni) begin : proc_ptr_addr_reg if (~rst_ni) begin - addr_ptr_reg <= '0; + addr_bcst_ptr_reg <= '0; end else begin - if (dma_start == 1'b1 && address_mode) begin - addr_ptr_reg <= reg2hw.addr_ptr.q; - end else if (data_addr_in_gnt == 1'b1 && address_mode) begin - addr_ptr_reg <= addr_ptr_reg + 32'h4; //always continuos in 32b + if (dma_start == 1'b1 && (address_mode || broadcast_mode)) begin + addr_bcst_ptr_reg <= reg2hw.addr_bcst_ptr.q; + end else if (data_addr_bcst_inout_gnt == 1'b1 && address_mode) begin + addr_bcst_ptr_reg <= addr_bcst_ptr_reg + 32'h4; //always continuos in 32b + end else if (data_addr_bcst_inout_gnt == 1'b1 && broadcast_mode) begin + addr_bcst_ptr_reg <= addr_bcst_ptr_reg + {24'h0, reg2hw.ptr_inc.bcst_ptr_inc.q}; end end end @@ -313,7 +325,7 @@ module dma #( end else begin if (dma_start == 1'b1 && address_mode) begin dma_addr_cnt <= reg2hw.size.q; - end else if (data_addr_in_gnt == 1'b1 && address_mode) begin + end else if (data_addr_bcst_inout_gnt == 1'b1 && address_mode) begin dma_addr_cnt <= dma_addr_cnt - 32'h4; //address always 32b end end @@ -352,6 +364,31 @@ module dma #( ; // case (data_type) end + always_comb begin : proc_byte_enable_out_broadcast + case (data_type) // Data type 00 Word, 01 Half word, 11,10 byte + 2'b00: bcst_byte_enable_out = 4'b1111; // Writing a word (32 bits) + + 2'b01: begin // Writing a half-word (16 bits) + case (addr_bcst_ptr_reg[1]) + 1'b0: bcst_byte_enable_out = 4'b0011; + 1'b1: bcst_byte_enable_out = 4'b1100; + endcase + ; // case(write_address[1:0]) + end + + 2'b10, 2'b11: begin // Writing a byte (8 bits) + case (addr_bcst_ptr_reg[1:0]) + 2'b00: bcst_byte_enable_out = 4'b0001; + 2'b01: bcst_byte_enable_out = 4'b0010; + 2'b10: bcst_byte_enable_out = 4'b0100; + 2'b11: bcst_byte_enable_out = 4'b1000; + endcase + ; // case(write_address[1:0]) + end + endcase + ; // case (data_type) + end + // Output data shift always_comb begin : proc_output_data @@ -374,7 +411,36 @@ module dma #( endcase end - assign fifo_addr_input = data_addr_in_rdata; //never misaligned, always 32b + // Output data shift (broadcast) + always_comb begin : proc_output_data_broadcast + + if (broadcast_mode) begin + + data_addr_bcst_inout_wdata[7:0] = fifo_output[7:0]; + data_addr_bcst_inout_wdata[15:8] = fifo_output[15:8]; + data_addr_bcst_inout_wdata[23:16] = fifo_output[23:16]; + data_addr_bcst_inout_wdata[31:24] = fifo_output[31:24]; + + case (write_address[1:0]) + 2'b00: ; + + 2'b01: data_addr_bcst_inout_wdata[15:8] = fifo_output[7:0]; + + 2'b10: begin + data_addr_bcst_inout_wdata[23:16] = fifo_output[7:0]; + data_addr_bcst_inout_wdata[31:24] = fifo_output[15:8]; + end + + 2'b11: data_addr_bcst_inout_wdata[31:24] = fifo_output[7:0]; + endcase + + end else begin + data_addr_bcst_inout_wdata = 32'd0; + end + + end + + assign fifo_addr_input = data_addr_bcst_inout_rdata; //never misaligned, always 32b // Input data shift: shift the input data to be on the LSB of the fifo always_comb begin : proc_input_data @@ -413,7 +479,7 @@ module dma #( outstanding_req <= outstanding_req + (data_in_req && data_in_gnt) - data_in_rvalid; if (address_mode) - outstanding_addr_req <= outstanding_addr_req + (data_addr_in_req && data_addr_in_gnt) - data_addr_in_rvalid; + outstanding_addr_req <= outstanding_addr_req + (data_addr_bcst_inout_req && data_addr_bcst_inout_gnt) - data_addr_bcst_inout_rvalid; end end @@ -460,15 +526,15 @@ module dma #( endcase end - // Read address master FSM + // Read address master & Write broadcast master FSM always_comb begin : proc_dma_addr_read_fsm_logic dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; - data_addr_in_req = '0; - data_addr_in_we = '0; - data_addr_in_be = '0; - data_addr_in_addr = '0; + data_addr_bcst_inout_req = '0; + data_addr_bcst_inout_we = '0; + data_addr_bcst_inout_be = '0; + data_addr_bcst_inout_addr = '0; fifo_addr_flush = 1'b0; @@ -476,26 +542,45 @@ module dma #( DMA_READ_FSM_IDLE: begin // Wait for start signal - if (dma_start == 1'b1 && address_mode) begin + if (address_mode && dma_start == 1'b1) begin dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; fifo_addr_flush = 1'b1; + end else if (broadcast_mode && dma_start == 1'b1) begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; end else begin dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; end end // Read one word DMA_READ_FSM_ON: begin - // If all input data read exit - if (|dma_addr_cnt == 1'b0) begin - dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; - end else begin - dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; - // Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1). - if (fifo_addr_full == 1'b0 && fifo_addr_alm_full == 1'b0) begin - data_addr_in_req = 1'b1; - data_addr_in_we = 1'b0; - data_addr_in_be = 4'b1111; // always read all bytes - data_addr_in_addr = addr_ptr_reg; + if (address_mode) begin + // If all input data read exit + if (|dma_addr_cnt == 1'b0) begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE; + end else begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; + // Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1). + if (fifo_addr_full == 1'b0 && fifo_addr_alm_full == 1'b0) begin + data_addr_bcst_inout_req = 1'b1; + data_addr_bcst_inout_we = 1'b0; + data_addr_bcst_inout_be = 4'b1111; // always read all bytes + data_addr_bcst_inout_addr = addr_bcst_ptr_reg; + end + end + end + if (broadcast_mode) begin + // If all input data read exit + if (fifo_empty == 1'b1 && dma_read_fsm_state == DMA_READ_FSM_IDLE) begin + dma_read_addr_fsm_n_state = dma_done ? DMA_READ_FSM_IDLE : DMA_READ_FSM_ON; + end else begin + dma_read_addr_fsm_n_state = DMA_READ_FSM_ON; + // Wait if fifo is empty or if the SPI TX is not ready for new data (only in SPI mode 2). + if (fifo_empty == 1'b0 && wait_for_tx == 1'b0 && fifo_addr_empty_check == 1'b0) begin + data_addr_bcst_inout_req = 1'b1; + data_addr_bcst_inout_we = 1'b1; + data_addr_bcst_inout_be = bcst_byte_enable_out; + data_addr_bcst_inout_addr = addr_bcst_ptr_reg; + end end end end @@ -559,7 +644,7 @@ module dma #( .push_i(data_in_rvalid), // as long as the queue is not empty we can pop new elements .data_o(fifo_output), - .pop_i(data_out_gnt) + .pop_i((!broadcast_mode && data_out_gnt) || (broadcast_mode && broadcast_pop)) ); fifo_v3 #( @@ -575,7 +660,7 @@ module dma #( .usage_o(fifo_addr_usage), // as long as the queue is not full we can push new data .data_i(fifo_addr_input), - .push_i(data_addr_in_rvalid), + .push_i(data_addr_bcst_inout_rvalid), // as long as the queue is not empty we can pop new elements .data_o(fifo_addr_output), .pop_i(data_out_gnt && address_mode) @@ -594,6 +679,36 @@ module dma #( .devmode_i(1'b1) ); + // In BROADCAST mode, awaits both locations to be written + // before popping a new element from the read FIFO. + always_ff @(posedge clk_i, negedge rst_ni) begin + if (~rst_ni) begin + broadcast_pop <= 0; + data_out_gnt_q <= 0; + data_addr_bcst_inout_q <= 0; + end else begin + + if (data_out_gnt) begin + data_out_gnt_q <= 1; + end + + if (data_addr_bcst_inout_gnt) begin + data_addr_bcst_inout_q <= 1; + end + + if ( (data_out_gnt || data_out_gnt_q) && (data_addr_bcst_inout_gnt || data_addr_bcst_inout_q) ) begin + broadcast_pop <= 1; + data_addr_bcst_inout_q <= 0; + data_out_gnt_q <= 0; + end + + if (broadcast_pop == 1) begin + broadcast_pop <= 0; + end + + end + end + // WINDOW EVENT // Count gnt write transaction and generate event pulse if WINDOW_SIZE is reached assign dma_window_event = |reg2hw.window_size.q & data_out_gnt & (window_counter + 'h1 >= reg2hw.window_size.q); diff --git a/hw/ip/dma/rtl/dma_reg_pkg.sv b/hw/ip/dma/rtl/dma_reg_pkg.sv index e4e31fe25..37e30a1a8 100644 --- a/hw/ip/dma/rtl/dma_reg_pkg.sv +++ b/hw/ip/dma/rtl/dma_reg_pkg.sv @@ -17,7 +17,7 @@ package dma_reg_pkg; typedef struct packed {logic [31:0] q;} dma_reg2hw_dst_ptr_reg_t; - typedef struct packed {logic [31:0] q;} dma_reg2hw_addr_ptr_reg_t; + typedef struct packed {logic [31:0] q;} dma_reg2hw_addr_bcst_ptr_reg_t; typedef struct packed { logic [31:0] q; @@ -38,6 +38,7 @@ package dma_reg_pkg; typedef struct packed { struct packed {logic [7:0] q;} src_ptr_inc; struct packed {logic [7:0] q;} dst_ptr_inc; + struct packed {logic [7:0] q;} bcst_ptr_inc; } dma_reg2hw_ptr_inc_reg_t; typedef struct packed { @@ -45,6 +46,11 @@ package dma_reg_pkg; struct packed {logic [15:0] q;} tx_trigger_slot; } dma_reg2hw_slot_reg_t; + typedef struct packed { + struct packed {logic [15:0] q;} bx_trigger_slot; + struct packed {logic [15:0] q;} dx_trigger_slot; + } dma_reg2hw_bslot_reg_t; + typedef struct packed {logic [1:0] q;} dma_reg2hw_data_type_reg_t; typedef struct packed {logic [1:0] q;} dma_reg2hw_mode_reg_t; @@ -70,13 +76,14 @@ package dma_reg_pkg; // Register -> HW type typedef struct packed { - dma_reg2hw_src_ptr_reg_t src_ptr; // [250:219] - dma_reg2hw_dst_ptr_reg_t dst_ptr; // [218:187] - dma_reg2hw_addr_ptr_reg_t addr_ptr; // [186:155] - dma_reg2hw_size_reg_t size; // [154:122] - dma_reg2hw_status_reg_t status; // [121:118] - dma_reg2hw_ptr_inc_reg_t ptr_inc; // [117:102] - dma_reg2hw_slot_reg_t slot; // [101:70] + dma_reg2hw_src_ptr_reg_t src_ptr; // [290:259] + dma_reg2hw_dst_ptr_reg_t dst_ptr; // [258:227] + dma_reg2hw_addr_bcst_ptr_reg_t addr_bcst_ptr; // [226:195] + dma_reg2hw_size_reg_t size; // [194:162] + dma_reg2hw_status_reg_t status; // [161:158] + dma_reg2hw_ptr_inc_reg_t ptr_inc; // [157:134] + dma_reg2hw_slot_reg_t slot; // [133:102] + dma_reg2hw_bslot_reg_t bslot; // [101:70] dma_reg2hw_data_type_reg_t data_type; // [69:68] dma_reg2hw_mode_reg_t mode; // [67:66] dma_reg2hw_window_size_reg_t window_size; // [65:34] @@ -93,16 +100,17 @@ package dma_reg_pkg; // Register offsets parameter logic [BlockAw-1:0] DMA_SRC_PTR_OFFSET = 6'h0; parameter logic [BlockAw-1:0] DMA_DST_PTR_OFFSET = 6'h4; - parameter logic [BlockAw-1:0] DMA_ADDR_PTR_OFFSET = 6'h8; + parameter logic [BlockAw-1:0] DMA_ADDR_BCST_PTR_OFFSET = 6'h8; parameter logic [BlockAw-1:0] DMA_SIZE_OFFSET = 6'hc; parameter logic [BlockAw-1:0] DMA_STATUS_OFFSET = 6'h10; parameter logic [BlockAw-1:0] DMA_PTR_INC_OFFSET = 6'h14; parameter logic [BlockAw-1:0] DMA_SLOT_OFFSET = 6'h18; - parameter logic [BlockAw-1:0] DMA_DATA_TYPE_OFFSET = 6'h1c; - parameter logic [BlockAw-1:0] DMA_MODE_OFFSET = 6'h20; - parameter logic [BlockAw-1:0] DMA_WINDOW_SIZE_OFFSET = 6'h24; - parameter logic [BlockAw-1:0] DMA_WINDOW_COUNT_OFFSET = 6'h28; - parameter logic [BlockAw-1:0] DMA_INTERRUPT_EN_OFFSET = 6'h2c; + parameter logic [BlockAw-1:0] DMA_BSLOT_OFFSET = 6'h1c; + parameter logic [BlockAw-1:0] DMA_DATA_TYPE_OFFSET = 6'h20; + parameter logic [BlockAw-1:0] DMA_MODE_OFFSET = 6'h24; + parameter logic [BlockAw-1:0] DMA_WINDOW_SIZE_OFFSET = 6'h28; + parameter logic [BlockAw-1:0] DMA_WINDOW_COUNT_OFFSET = 6'h2c; + parameter logic [BlockAw-1:0] DMA_INTERRUPT_EN_OFFSET = 6'h30; // Reset values for hwext registers and their fields parameter logic [1:0] DMA_STATUS_RESVAL = 2'h1; @@ -113,11 +121,12 @@ package dma_reg_pkg; typedef enum int { DMA_SRC_PTR, DMA_DST_PTR, - DMA_ADDR_PTR, + DMA_ADDR_BCST_PTR, DMA_SIZE, DMA_STATUS, DMA_PTR_INC, DMA_SLOT, + DMA_BSLOT, DMA_DATA_TYPE, DMA_MODE, DMA_WINDOW_SIZE, @@ -126,19 +135,20 @@ package dma_reg_pkg; } dma_id_e; // Register width information to check illegal writes - parameter logic [3:0] DMA_PERMIT[12] = '{ + parameter logic [3:0] DMA_PERMIT[13] = '{ 4'b1111, // index[ 0] DMA_SRC_PTR 4'b1111, // index[ 1] DMA_DST_PTR - 4'b1111, // index[ 2] DMA_ADDR_PTR + 4'b1111, // index[ 2] DMA_ADDR_BCST_PTR 4'b1111, // index[ 3] DMA_SIZE 4'b0001, // index[ 4] DMA_STATUS - 4'b0011, // index[ 5] DMA_PTR_INC + 4'b0111, // index[ 5] DMA_PTR_INC 4'b1111, // index[ 6] DMA_SLOT - 4'b0001, // index[ 7] DMA_DATA_TYPE - 4'b0001, // index[ 8] DMA_MODE - 4'b1111, // index[ 9] DMA_WINDOW_SIZE - 4'b1111, // index[10] DMA_WINDOW_COUNT - 4'b0001 // index[11] DMA_INTERRUPT_EN + 4'b1111, // index[ 7] DMA_BSLOT + 4'b0001, // index[ 8] DMA_DATA_TYPE + 4'b0001, // index[ 9] DMA_MODE + 4'b1111, // index[10] DMA_WINDOW_SIZE + 4'b1111, // index[11] DMA_WINDOW_COUNT + 4'b0001 // index[12] DMA_INTERRUPT_EN }; endpackage diff --git a/hw/ip/dma/rtl/dma_reg_top.sv b/hw/ip/dma/rtl/dma_reg_top.sv index 4a3ff6d02..9c33cc9fd 100644 --- a/hw/ip/dma/rtl/dma_reg_top.sv +++ b/hw/ip/dma/rtl/dma_reg_top.sv @@ -74,9 +74,9 @@ module dma_reg_top #( logic [31:0] dst_ptr_qs; logic [31:0] dst_ptr_wd; logic dst_ptr_we; - logic [31:0] addr_ptr_qs; - logic [31:0] addr_ptr_wd; - logic addr_ptr_we; + logic [31:0] addr_bcst_ptr_qs; + logic [31:0] addr_bcst_ptr_wd; + logic addr_bcst_ptr_we; logic [31:0] size_qs; logic [31:0] size_wd; logic size_we; @@ -90,12 +90,21 @@ module dma_reg_top #( logic [7:0] ptr_inc_dst_ptr_inc_qs; logic [7:0] ptr_inc_dst_ptr_inc_wd; logic ptr_inc_dst_ptr_inc_we; + logic [7:0] ptr_inc_bcst_ptr_inc_qs; + logic [7:0] ptr_inc_bcst_ptr_inc_wd; + logic ptr_inc_bcst_ptr_inc_we; logic [15:0] slot_rx_trigger_slot_qs; logic [15:0] slot_rx_trigger_slot_wd; logic slot_rx_trigger_slot_we; logic [15:0] slot_tx_trigger_slot_qs; logic [15:0] slot_tx_trigger_slot_wd; logic slot_tx_trigger_slot_we; + logic [15:0] bslot_bx_trigger_slot_qs; + logic [15:0] bslot_bx_trigger_slot_wd; + logic bslot_bx_trigger_slot_we; + logic [15:0] bslot_dx_trigger_slot_qs; + logic [15:0] bslot_dx_trigger_slot_wd; + logic bslot_dx_trigger_slot_we; logic [1:0] data_type_qs; logic [1:0] data_type_wd; logic data_type_we; @@ -168,19 +177,19 @@ module dma_reg_top #( ); - // R[addr_ptr]: V(False) + // R[addr_bcst_ptr]: V(False) prim_subreg #( .DW (32), .SWACCESS("RW"), .RESVAL (32'h0) - ) u_addr_ptr ( + ) u_addr_bcst_ptr ( .clk_i (clk_i), .rst_ni(rst_ni), // from register interface - .we(addr_ptr_we), - .wd(addr_ptr_wd), + .we(addr_bcst_ptr_we), + .wd(addr_bcst_ptr_wd), // from internal hardware .de(1'b0), @@ -188,10 +197,10 @@ module dma_reg_top #( // to internal hardware .qe(), - .q (reg2hw.addr_ptr.q), + .q (reg2hw.addr_bcst_ptr.q), // to register interface (read) - .qs(addr_ptr_qs) + .qs(addr_bcst_ptr_qs) ); @@ -308,6 +317,32 @@ module dma_reg_top #( ); + // F[bcst_ptr_inc]: 23:16 + prim_subreg #( + .DW (8), + .SWACCESS("RW"), + .RESVAL (8'h4) + ) u_ptr_inc_bcst_ptr_inc ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(ptr_inc_bcst_ptr_inc_we), + .wd(ptr_inc_bcst_ptr_inc_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.ptr_inc.bcst_ptr_inc.q), + + // to register interface (read) + .qs(ptr_inc_bcst_ptr_inc_qs) + ); + + // R[slot]: V(False) // F[rx_trigger_slot]: 15:0 @@ -362,6 +397,60 @@ module dma_reg_top #( ); + // R[bslot]: V(False) + + // F[bx_trigger_slot]: 15:0 + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_bslot_bx_trigger_slot ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(bslot_bx_trigger_slot_we), + .wd(bslot_bx_trigger_slot_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.bslot.bx_trigger_slot.q), + + // to register interface (read) + .qs(bslot_bx_trigger_slot_qs) + ); + + + // F[dx_trigger_slot]: 31:16 + prim_subreg #( + .DW (16), + .SWACCESS("RW"), + .RESVAL (16'h0) + ) u_bslot_dx_trigger_slot ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + // from register interface + .we(bslot_dx_trigger_slot_we), + .wd(bslot_dx_trigger_slot_wd), + + // from internal hardware + .de(1'b0), + .d ('0), + + // to internal hardware + .qe(), + .q (reg2hw.bslot.dx_trigger_slot.q), + + // to register interface (read) + .qs(bslot_dx_trigger_slot_qs) + ); + + // R[data_type]: V(False) prim_subreg #( @@ -525,21 +614,22 @@ module dma_reg_top #( - logic [11:0] addr_hit; + logic [12:0] addr_hit; always_comb begin addr_hit = '0; addr_hit[0] = (reg_addr == DMA_SRC_PTR_OFFSET); addr_hit[1] = (reg_addr == DMA_DST_PTR_OFFSET); - addr_hit[2] = (reg_addr == DMA_ADDR_PTR_OFFSET); + addr_hit[2] = (reg_addr == DMA_ADDR_BCST_PTR_OFFSET); addr_hit[3] = (reg_addr == DMA_SIZE_OFFSET); addr_hit[4] = (reg_addr == DMA_STATUS_OFFSET); addr_hit[5] = (reg_addr == DMA_PTR_INC_OFFSET); addr_hit[6] = (reg_addr == DMA_SLOT_OFFSET); - addr_hit[7] = (reg_addr == DMA_DATA_TYPE_OFFSET); - addr_hit[8] = (reg_addr == DMA_MODE_OFFSET); - addr_hit[9] = (reg_addr == DMA_WINDOW_SIZE_OFFSET); - addr_hit[10] = (reg_addr == DMA_WINDOW_COUNT_OFFSET); - addr_hit[11] = (reg_addr == DMA_INTERRUPT_EN_OFFSET); + addr_hit[7] = (reg_addr == DMA_BSLOT_OFFSET); + addr_hit[8] = (reg_addr == DMA_DATA_TYPE_OFFSET); + addr_hit[9] = (reg_addr == DMA_MODE_OFFSET); + addr_hit[10] = (reg_addr == DMA_WINDOW_SIZE_OFFSET); + addr_hit[11] = (reg_addr == DMA_WINDOW_COUNT_OFFSET); + addr_hit[12] = (reg_addr == DMA_INTERRUPT_EN_OFFSET); end assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0; @@ -558,7 +648,8 @@ module dma_reg_top #( (addr_hit[ 8] & (|(DMA_PERMIT[ 8] & ~reg_be))) | (addr_hit[ 9] & (|(DMA_PERMIT[ 9] & ~reg_be))) | (addr_hit[10] & (|(DMA_PERMIT[10] & ~reg_be))) | - (addr_hit[11] & (|(DMA_PERMIT[11] & ~reg_be))))); + (addr_hit[11] & (|(DMA_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(DMA_PERMIT[12] & ~reg_be))))); end assign src_ptr_we = addr_hit[0] & reg_we & !reg_error; @@ -567,8 +658,8 @@ module dma_reg_top #( assign dst_ptr_we = addr_hit[1] & reg_we & !reg_error; assign dst_ptr_wd = reg_wdata[31:0]; - assign addr_ptr_we = addr_hit[2] & reg_we & !reg_error; - assign addr_ptr_wd = reg_wdata[31:0]; + assign addr_bcst_ptr_we = addr_hit[2] & reg_we & !reg_error; + assign addr_bcst_ptr_wd = reg_wdata[31:0]; assign size_we = addr_hit[3] & reg_we & !reg_error; assign size_wd = reg_wdata[31:0]; @@ -583,25 +674,34 @@ module dma_reg_top #( assign ptr_inc_dst_ptr_inc_we = addr_hit[5] & reg_we & !reg_error; assign ptr_inc_dst_ptr_inc_wd = reg_wdata[15:8]; + assign ptr_inc_bcst_ptr_inc_we = addr_hit[5] & reg_we & !reg_error; + assign ptr_inc_bcst_ptr_inc_wd = reg_wdata[23:16]; + assign slot_rx_trigger_slot_we = addr_hit[6] & reg_we & !reg_error; assign slot_rx_trigger_slot_wd = reg_wdata[15:0]; assign slot_tx_trigger_slot_we = addr_hit[6] & reg_we & !reg_error; assign slot_tx_trigger_slot_wd = reg_wdata[31:16]; - assign data_type_we = addr_hit[7] & reg_we & !reg_error; + assign bslot_bx_trigger_slot_we = addr_hit[7] & reg_we & !reg_error; + assign bslot_bx_trigger_slot_wd = reg_wdata[15:0]; + + assign bslot_dx_trigger_slot_we = addr_hit[7] & reg_we & !reg_error; + assign bslot_dx_trigger_slot_wd = reg_wdata[31:16]; + + assign data_type_we = addr_hit[8] & reg_we & !reg_error; assign data_type_wd = reg_wdata[1:0]; - assign mode_we = addr_hit[8] & reg_we & !reg_error; + assign mode_we = addr_hit[9] & reg_we & !reg_error; assign mode_wd = reg_wdata[1:0]; - assign window_size_we = addr_hit[9] & reg_we & !reg_error; + assign window_size_we = addr_hit[10] & reg_we & !reg_error; assign window_size_wd = reg_wdata[31:0]; - assign interrupt_en_transaction_done_we = addr_hit[11] & reg_we & !reg_error; + assign interrupt_en_transaction_done_we = addr_hit[12] & reg_we & !reg_error; assign interrupt_en_transaction_done_wd = reg_wdata[0]; - assign interrupt_en_window_done_we = addr_hit[11] & reg_we & !reg_error; + assign interrupt_en_window_done_we = addr_hit[12] & reg_we & !reg_error; assign interrupt_en_window_done_wd = reg_wdata[1]; // Read data return @@ -617,7 +717,7 @@ module dma_reg_top #( end addr_hit[2]: begin - reg_rdata_next[31:0] = addr_ptr_qs; + reg_rdata_next[31:0] = addr_bcst_ptr_qs; end addr_hit[3]: begin @@ -630,8 +730,9 @@ module dma_reg_top #( end addr_hit[5]: begin - reg_rdata_next[7:0] = ptr_inc_src_ptr_inc_qs; - reg_rdata_next[15:8] = ptr_inc_dst_ptr_inc_qs; + reg_rdata_next[7:0] = ptr_inc_src_ptr_inc_qs; + reg_rdata_next[15:8] = ptr_inc_dst_ptr_inc_qs; + reg_rdata_next[23:16] = ptr_inc_bcst_ptr_inc_qs; end addr_hit[6]: begin @@ -640,22 +741,27 @@ module dma_reg_top #( end addr_hit[7]: begin - reg_rdata_next[1:0] = data_type_qs; + reg_rdata_next[15:0] = bslot_bx_trigger_slot_qs; + reg_rdata_next[31:16] = bslot_dx_trigger_slot_qs; end addr_hit[8]: begin - reg_rdata_next[1:0] = mode_qs; + reg_rdata_next[1:0] = data_type_qs; end addr_hit[9]: begin - reg_rdata_next[31:0] = window_size_qs; + reg_rdata_next[1:0] = mode_qs; end addr_hit[10]: begin - reg_rdata_next[31:0] = window_count_qs; + reg_rdata_next[31:0] = window_size_qs; end addr_hit[11]: begin + reg_rdata_next[31:0] = window_count_qs; + end + + addr_hit[12]: begin reg_rdata_next[0] = interrupt_en_transaction_done_qs; reg_rdata_next[1] = interrupt_en_window_done_qs; end diff --git a/hw/system/x_heep_system.sv.tpl b/hw/system/x_heep_system.sv.tpl index c88bdacad..5873a56ae 100644 --- a/hw/system/x_heep_system.sv.tpl +++ b/hw/system/x_heep_system.sv.tpl @@ -33,8 +33,8 @@ module x_heep_system input obi_resp_t ext_dma_read_ch0_resp_i, output obi_req_t ext_dma_write_ch0_req_o, input obi_resp_t ext_dma_write_ch0_resp_i, - output obi_req_t ext_dma_addr_ch0_req_o, - input obi_resp_t ext_dma_addr_ch0_resp_i, + output obi_req_t ext_dma_addr_bcst_ch0_req_o, + input obi_resp_t ext_dma_addr_bcst_ch0_resp_i, output reg_req_t ext_peripheral_slave_req_o, input reg_rsp_t ext_peripheral_slave_resp_i, @@ -124,8 +124,8 @@ ${pad.core_v_mini_mcu_bonding} .ext_dma_read_ch0_resp_i, .ext_dma_write_ch0_req_o, .ext_dma_write_ch0_resp_i, - .ext_dma_addr_ch0_req_o, - .ext_dma_addr_ch0_resp_i, + .ext_dma_addr_bcst_ch0_req_o, + .ext_dma_addr_bcst_ch0_resp_i, .ext_peripheral_slave_req_o, .ext_peripheral_slave_resp_i, .cpu_subsystem_powergate_switch_no(cpu_subsystem_powergate_switch_n), diff --git a/sw/applications/example_dma/main.c b/sw/applications/example_dma/main.c index bbab36980..f7bfd87e6 100644 --- a/sw/applications/example_dma/main.c +++ b/sw/applications/example_dma/main.c @@ -17,6 +17,8 @@ #define TEST_WINDOW #define TEST_ADDRESS_MODE #define TEST_ADDRESS_MODE_EXTERNAL_DEVICE +#define TEST_HALFWORD2WORD +#define TEST_BROADCAST #define TEST_DATA_SIZE 16 #define TEST_DATA_LARGE 1024 @@ -73,7 +75,11 @@ int main(int argc, char *argv[]) static uint32_t test_data_4B[TEST_DATA_SIZE] __attribute__ ((aligned (4))) = { 0x76543210, 0xfedcba98, 0x579a6f90, 0x657d5bee, 0x758ee41f, 0x01234567, 0xfedbca98, 0x89abcdef, 0x679852fe, 0xff8252bb, 0x763b4521, 0x6875adaa, 0x09ac65bb, 0x666ba334, 0x55446677, 0x65ffba98}; static uint32_t copied_data_4B[TEST_DATA_LARGE] __attribute__ ((aligned (4))) = { 0 }; + static uint16_t broadcast_data_4B[4*TEST_DATA_SIZE] __attribute__ ((aligned (4))) = { 0 }; static uint32_t test_data_large[TEST_DATA_LARGE] __attribute__ ((aligned (4))) = { 0 }; + + static uint16_t test_data_halfword_4B[TEST_DATA_SIZE] __attribute__ ((aligned (4))) = { + 0x6420, 0xeca8, 0x7af0, 0x5dbe, 0x5e4f, 0x1357, 0xeba8, 0x9bdf, 0x782e, 0xf22b, 0x6b51, 0x85da, 0x9c5b, 0x6b34, 0x5467, 0x5fa8}; // this array will contain the even address of copied_data_4B uint32_t* test_addr_4B_PTR = &test_data_large[0]; @@ -399,6 +405,137 @@ int main(int argc, char *argv[]) #endif // TEST_WINDOW +#ifdef TEST_HALFWORD2WORD + + tgt_src.ptr = test_data_halfword_4B; + tgt_src.inc_du = 1; + tgt_src.size_du = TEST_DATA_SIZE; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_HALF_WORD; + + tgt_dst.ptr = copied_data_4B; + tgt_dst.inc_du = 1; + tgt_dst.size_du = TEST_DATA_SIZE; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_WORD; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.mode = DMA_TRANS_MODE_SINGLE; + trans.win_du = 0; + trans.end = DMA_TRANS_END_INTR; + + PRINTF("\n\n\r===================================\n\n\r"); + PRINTF(" TESTING HALF WORD TO WORD "); + PRINTF("\n\n\r===================================\n\n\r"); + + res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + PRINTF("tran: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res = dma_load_transaction(&trans); + PRINTF("load: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res = dma_launch(&trans); + PRINTF("laun: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); + + while( ! dma_is_ready()) { + // disable_interrupts + // this does not prevent waking up the core as this is controlled by the MIP register + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if ( dma_is_ready() == 0 ) { + wait_for_interrupt(); + //from here we wake up even if we did not jump to the ISR + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + PRINTF(">> Finished transaction. \n\r"); + + for(uint32_t i = 0; i < trans.size_b; i++ ) { + if ( ((uint8_t*)copied_data_4B)[i] != ((uint8_t*)test_data_halfword_4B)[i] ) { + PRINTF("ERROR [%d]: %04x != %04x\n\r", i, ((uint8_t*)copied_data_4B)[i], ((uint8_t*)test_data_halfword_4B)[i]); + errors++; + } + } + + if (errors == 0) { + PRINTF("DMA halfword to word success.\n\r"); + } else { + PRINTF("DMA halfword to word failure: %d errors out of %d bytes checked\n\r", errors, trans.size_b ); + return EXIT_FAILURE; + } + +#endif // TEST_HALFWORD2WORD + +#ifdef TEST_BROADCAST + + tgt_src.ptr = test_data_halfword_4B; + tgt_src.inc_du = 1; + tgt_src.size_du = TEST_DATA_SIZE; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_HALF_WORD; + + tgt_dst.ptr = copied_data_4B; + tgt_dst.inc_du = 1; + tgt_dst.size_du = TEST_DATA_SIZE; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_WORD; + + dma_target_t tgt_bcst = { + .ptr = broadcast_data_4B, + .inc_du = 1, + .size_du = TEST_DATA_SIZE, + .trig = DMA_TRIG_MEMORY, + .type = DMA_DATA_TYPE_HALF_WORD + }; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.dst_bcst = &tgt_bcst; + trans.mode = DMA_TRANS_MODE_BROADCAST; + trans.win_du = 0; + trans.end = DMA_TRANS_END_INTR; + + PRINTF("\n\n\r===================================\n\n\r"); + PRINTF(" TESTING BROADCAST "); + PRINTF("\n\n\r===================================\n\n\r"); + + res = dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY ); + PRINTF("tran: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res = dma_load_transaction(&trans); + PRINTF("load: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); + res = dma_launch(&trans); + PRINTF("laun: %u \t%s\n\r", res, res == DMA_CONFIG_OK ? "Ok!" : "Error!"); + + while( ! dma_is_ready()) { + // disable_interrupts + // this does not prevent waking up the core as this is controlled by the MIP register + CSR_CLEAR_BITS(CSR_REG_MSTATUS, 0x8); + if ( dma_is_ready() == 0 ) { + wait_for_interrupt(); + //from here we wake up even if we did not jump to the ISR + } + CSR_SET_BITS(CSR_REG_MSTATUS, 0x8); + } + PRINTF(">> Finished transaction. \n\r"); + + for(uint32_t i = 0; i < trans.size_b; i++ ) { + if ( ((uint8_t*)copied_data_4B)[i] != ((uint8_t*)test_data_halfword_4B)[i] ) { + PRINTF("ERROR [%d]: %04x != %04x\n\r", i, ((uint8_t*)copied_data_4B)[i], ((uint8_t*)test_data_halfword_4B)[i]); + errors++; + } + if ( ((uint8_t*)broadcast_data_4B)[i] != ((uint8_t*)test_data_halfword_4B)[i] ) { + PRINTF("BROADCAST ERROR [%d]: %04x != %04x\n\r", i, ((uint8_t*)broadcast_data_4B)[i], ((uint8_t*)test_data_halfword_4B)[i]); + errors++; + } + } + + if (errors == 0) { + PRINTF("DMA broadcast success.\n\r"); + } else { + PRINTF("DMA broadcast failure: %d errors out of %d bytes checked\n\r", errors, trans.size_b ); + return EXIT_FAILURE; + } + +#endif // TEST_BROADCAST + return EXIT_SUCCESS; } diff --git a/sw/applications/example_iffifo_broadcast/main.c b/sw/applications/example_iffifo_broadcast/main.c new file mode 100644 index 000000000..2b1e38b1f --- /dev/null +++ b/sw/applications/example_iffifo_broadcast/main.c @@ -0,0 +1,129 @@ +// Copyright EPFL contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + + +#include "dma.h" +#include "core_v_mini_mcu.h" +#include "x-heep.h" +#include "csr.h" +#include "rv_plic.h" +#include "iffifo_regs.h" + +/* By default, printfs are activated for FPGA and disabled for simulation. */ +#define PRINTF_IN_FPGA 1 +#define PRINTF_IN_SIM 0 + +#if TARGET_SIM && PRINTF_IN_SIM + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#elif TARGET_PYNQ_Z2 && PRINTF_IN_FPGA + #define PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else + #define PRINTF(...) +#endif + +#if TARGET_PYNQ_Z2 +#error This example requires the IFFIFO peripheral, instantiated in the test bench only. +#endif + +unsigned int IFFIFO_START_ADDRESS = EXT_PERIPHERAL_START_ADDRESS + 0x2000; + +int32_t src [4] __attribute__ ((aligned (4))) = { 2, 7, 3, 12 }; +int32_t dst [4] __attribute__ ((aligned (4))) = { 0, 0, 0, 0 }; +int32_t dst_bcst[4] __attribute__ ((aligned (4))) = { 0, 0, 0, 0 }; + +static dma_target_t tgt_src; +static dma_target_t tgt_dst; +static dma_target_t tgt_dst_bcst; +static dma_trans_t trans; + +void print_fifo_array(void) { + + PRINTF("src = {"); + for (int i = 0; i < 4; i+=1) { + PRINTF("%d",src[i]); + if(i != 4-1) {PRINTF(", ");}; + } + PRINTF("}\n"); + + PRINTF("dst = {"); + for (int i = 0; i < 4; i+=1) { + PRINTF("%d",dst[i]); + if(i != 4-1) {PRINTF(", ");}; + } + PRINTF("}\n"); + + PRINTF("dst_bcst = {"); + for (int i = 0; i < 4; i+=1) { + PRINTF("%d",dst_bcst[i]); + if(i != 4-1) {PRINTF(", ");}; + } + PRINTF("}\n"); + +} + +int main(int argc, char *argv[]) +{ + + dma_init(NULL); + tgt_src.ptr = src; + tgt_src.inc_du = 1; + tgt_src.trig = DMA_TRIG_MEMORY; + tgt_src.type = DMA_DATA_TYPE_WORD; + tgt_src.size_du = 4; + + tgt_dst.ptr = dst; + tgt_dst.inc_du = 1; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_dst.type = DMA_DATA_TYPE_WORD; + + tgt_dst_bcst.ptr = IFFIFO_START_ADDRESS + IFFIFO_FIFO_IN_REG_OFFSET; + tgt_dst_bcst.inc_du = 0; + tgt_dst_bcst.trig = DMA_TRIG_SLOT_EXT_TX; + tgt_dst_bcst.type = DMA_DATA_TYPE_WORD; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.dst_bcst = &tgt_dst_bcst; + trans.mode = DMA_TRANS_MODE_BROADCAST; + trans.end = DMA_TRANS_END_INTR; + + if (dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY )) {return EXIT_FAILURE;} + if (dma_load_transaction(&trans)) {return EXIT_FAILURE;} + + print_fifo_array(); + + PRINTF("Launch DMA SRC > DST >> IFFIFO transaction\n"); + if (dma_launch( &trans )) {return EXIT_FAILURE;} + + print_fifo_array(); + + dma_init(NULL); + tgt_src.ptr = IFFIFO_START_ADDRESS + IFFIFO_FIFO_OUT_REG_OFFSET; + tgt_src.inc_du = 0; + tgt_src.trig = DMA_TRIG_SLOT_EXT_RX; + tgt_src.type = DMA_DATA_TYPE_WORD; + tgt_src.size_du = 4; + + tgt_dst.ptr = dst_bcst; + tgt_dst.inc_du = 1; + tgt_dst.trig = DMA_TRIG_MEMORY; + tgt_dst.type = DMA_DATA_TYPE_WORD; + + trans.src = &tgt_src; + trans.dst = &tgt_dst; + trans.end = DMA_TRANS_END_INTR; + + if (dma_validate_transaction( &trans, DMA_ENABLE_REALIGN, DMA_PERFORM_CHECKS_INTEGRITY )) {return EXIT_FAILURE;} + if (dma_load_transaction(&trans)) {return EXIT_FAILURE;} + + PRINTF("Launch IFFIFO > DST_BCST transaction\n"); + if (dma_launch( &trans )) {return EXIT_FAILURE;} + + print_fifo_array(); + + return EXIT_SUCCESS; +} diff --git a/sw/device/lib/drivers/dma/dma.c b/sw/device/lib/drivers/dma/dma.c index c30b6105a..f0c7fdcbc 100644 --- a/sw/device/lib/drivers/dma/dma.c +++ b/sw/device/lib/drivers/dma/dma.c @@ -275,6 +275,7 @@ void dma_init( dma *peri ) /* Clear all values in the DMA registers. */ dma_cb.peri->SRC_PTR = 0; dma_cb.peri->DST_PTR = 0; + dma_cb.peri->ADDR_BCST_PTR = 0; dma_cb.peri->SIZE = 0; dma_cb.peri->PTR_INC = 0; dma_cb.peri->SLOT = 0; @@ -699,26 +700,17 @@ dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans ) from the address port */ dma_cb.peri->DST_PTR = dma_cb.trans->dst->ptr; - } - else - { - dma_cb.peri->ADDR_PTR = dma_cb.trans->src_addr->ptr; - } - if(dma_cb.trans->mode != DMA_TRANS_MODE_ADDRESS) - { - /* - Write to the destination pointers only if we are not in address mode, - otherwise the destination address is read in a separate port in parallel with the data - from the address port - */ - dma_cb.peri->DST_PTR = dma_cb.trans->dst->ptr; + // Populates ADDR_BCST_PTR (pointer to broadcast destination register) + if (dma_cb.trans->mode == DMA_TRANS_MODE_BROADCAST) { + dma_cb.peri->ADDR_BCST_PTR = dma_cb.trans->dst_bcst->ptr; + } } else { - dma_cb.peri->ADDR_PTR = dma_cb.trans->src_addr->ptr; + dma_cb.peri->ADDR_BCST_PTR = dma_cb.trans->src_addr->ptr; } - + /* * SET THE INCREMENTS */ @@ -742,10 +734,20 @@ dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans ) if(dma_cb.trans->mode != DMA_TRANS_MODE_ADDRESS) { - write_register( get_increment_b( dma_cb.trans->dst ), + + write_register( get_increment_b( dma_cb.trans->dst ), DMA_PTR_INC_REG_OFFSET, DMA_PTR_INC_DST_PTR_INC_MASK, DMA_PTR_INC_DST_PTR_INC_OFFSET ); + + // Populates BCST_PTR_INC (broadcast destination increment) + if (dma_cb.trans->mode == DMA_TRANS_MODE_BROADCAST) { + write_register( get_increment_b( dma_cb.trans->dst_bcst ), + DMA_PTR_INC_REG_OFFSET, + DMA_PTR_INC_BCST_PTR_INC_MASK, + DMA_PTR_INC_BCST_PTR_INC_OFFSET ); + } + } @@ -764,16 +766,25 @@ dma_config_flags_t dma_load_transaction( dma_trans_t *p_trans ) /* * SET TRIGGER SLOTS AND DATA TYPE */ + + // RX_TRIGGER_SLOT (Source) write_register( dma_cb.trans->src->trig, DMA_SLOT_REG_OFFSET, DMA_SLOT_RX_TRIGGER_SLOT_MASK, DMA_SLOT_RX_TRIGGER_SLOT_OFFSET ); + // TX_TRIGGER_SLOT (Destination) write_register( dma_cb.trans->dst->trig, DMA_SLOT_REG_OFFSET, DMA_SLOT_TX_TRIGGER_SLOT_MASK, DMA_SLOT_TX_TRIGGER_SLOT_OFFSET ); + // BX_TRIGGER_SLOT (Broadcast destination) + write_register( dma_cb.trans->dst_bcst->trig, + DMA_BSLOT_REG_OFFSET, + DMA_BSLOT_BX_TRIGGER_SLOT_MASK, + DMA_BSLOT_BX_TRIGGER_SLOT_OFFSET ); + write_register( dma_cb.trans->type, DMA_DATA_TYPE_REG_OFFSET, DMA_DATA_TYPE_DATA_TYPE_MASK, @@ -1166,4 +1177,4 @@ static inline uint32_t get_increment_b( dma_target_t * p_tgt ) /** **/ /* EOF */ /** **/ -/****************************************************************************/ \ No newline at end of file +/****************************************************************************/ diff --git a/sw/device/lib/drivers/dma/dma.h b/sw/device/lib/drivers/dma/dma.h index 85ee64751..0946eb6ac 100644 --- a/sw/device/lib/drivers/dma/dma.h +++ b/sw/device/lib/drivers/dma/dma.h @@ -182,7 +182,7 @@ typedef enum parameters. This generates a circular mode in the source and/or destination pointing to memory. */ DMA_TRANS_MODE_ADDRESS = DMA_MODE_MODE_VALUE_ADDRESS_MODE, /*!< In this mode, the destination address is read from the address port! */ - + DMA_TRANS_MODE_BROADCAST = DMA_MODE_MODE_VALUE_BROADCAST_MODE, DMA_TRANS_MODE__size, /*!< Not used, only for sanity checks. */ } dma_trans_mode_t; @@ -304,6 +304,8 @@ typedef struct copied. */ dma_target_t* src_addr; /*!< Target from where the dst address will be copied. - only valid in address mode */ + dma_target_t* dst_bcst; /*!< Target to where the data will be + copied. */ uint16_t inc_b; /*!< A common increment in case both targets need to use one same increment. */ uint32_t size_b; /*!< The size of the transfer, in bytes (in diff --git a/sw/device/lib/drivers/dma/dma_regs.h b/sw/device/lib/drivers/dma/dma_regs.h index ce6169c16..7a8555189 100644 --- a/sw/device/lib/drivers/dma/dma_regs.h +++ b/sw/device/lib/drivers/dma/dma_regs.h @@ -22,8 +22,8 @@ extern "C" { // Output data pointer (word aligned) #define DMA_DST_PTR_REG_OFFSET 0x4 -// Addess data pointer (word aligned) -#define DMA_ADDR_PTR_REG_OFFSET 0x8 +// Addess/Broadcast data pointer (word aligned) +#define DMA_ADDR_BCST_PTR_REG_OFFSET 0x8 // Number of bytes to copy - Once a value is written, the copy starts #define DMA_SIZE_REG_OFFSET 0xc @@ -43,6 +43,10 @@ extern "C" { #define DMA_PTR_INC_DST_PTR_INC_OFFSET 8 #define DMA_PTR_INC_DST_PTR_INC_FIELD \ ((bitfield_field32_t) { .mask = DMA_PTR_INC_DST_PTR_INC_MASK, .index = DMA_PTR_INC_DST_PTR_INC_OFFSET }) +#define DMA_PTR_INC_BCST_PTR_INC_MASK 0xff +#define DMA_PTR_INC_BCST_PTR_INC_OFFSET 16 +#define DMA_PTR_INC_BCST_PTR_INC_FIELD \ + ((bitfield_field32_t) { .mask = DMA_PTR_INC_BCST_PTR_INC_MASK, .index = DMA_PTR_INC_BCST_PTR_INC_OFFSET }) // The DMA will wait for the signal #define DMA_SLOT_REG_OFFSET 0x18 @@ -55,8 +59,19 @@ extern "C" { #define DMA_SLOT_TX_TRIGGER_SLOT_FIELD \ ((bitfield_field32_t) { .mask = DMA_SLOT_TX_TRIGGER_SLOT_MASK, .index = DMA_SLOT_TX_TRIGGER_SLOT_OFFSET }) +// The DMA will wait for the signal +#define DMA_BSLOT_REG_OFFSET 0x1c +#define DMA_BSLOT_BX_TRIGGER_SLOT_MASK 0xffff +#define DMA_BSLOT_BX_TRIGGER_SLOT_OFFSET 0 +#define DMA_BSLOT_BX_TRIGGER_SLOT_FIELD \ + ((bitfield_field32_t) { .mask = DMA_BSLOT_BX_TRIGGER_SLOT_MASK, .index = DMA_BSLOT_BX_TRIGGER_SLOT_OFFSET }) +#define DMA_BSLOT_DX_TRIGGER_SLOT_MASK 0xffff +#define DMA_BSLOT_DX_TRIGGER_SLOT_OFFSET 16 +#define DMA_BSLOT_DX_TRIGGER_SLOT_FIELD \ + ((bitfield_field32_t) { .mask = DMA_BSLOT_DX_TRIGGER_SLOT_MASK, .index = DMA_BSLOT_DX_TRIGGER_SLOT_OFFSET }) + // Width/type of the data to transfer -#define DMA_DATA_TYPE_REG_OFFSET 0x1c +#define DMA_DATA_TYPE_REG_OFFSET 0x20 #define DMA_DATA_TYPE_DATA_TYPE_MASK 0x3 #define DMA_DATA_TYPE_DATA_TYPE_OFFSET 0 #define DMA_DATA_TYPE_DATA_TYPE_FIELD \ @@ -67,7 +82,7 @@ extern "C" { #define DMA_DATA_TYPE_DATA_TYPE_VALUE_DMA_8BIT_WORD_2 0x3 // Set the operational mode of the DMA -#define DMA_MODE_REG_OFFSET 0x20 +#define DMA_MODE_REG_OFFSET 0x24 #define DMA_MODE_MODE_MASK 0x3 #define DMA_MODE_MODE_OFFSET 0 #define DMA_MODE_MODE_FIELD \ @@ -75,15 +90,16 @@ extern "C" { #define DMA_MODE_MODE_VALUE_LINEAR_MODE 0x0 #define DMA_MODE_MODE_VALUE_CIRCULAR_MODE 0x1 #define DMA_MODE_MODE_VALUE_ADDRESS_MODE 0x2 +#define DMA_MODE_MODE_VALUE_BROADCAST_MODE 0x3 // Will trigger a every "WINDOW_SIZE" writes -#define DMA_WINDOW_SIZE_REG_OFFSET 0x24 +#define DMA_WINDOW_SIZE_REG_OFFSET 0x28 // Number of times the end of the window was reached since the beginning. -#define DMA_WINDOW_COUNT_REG_OFFSET 0x28 +#define DMA_WINDOW_COUNT_REG_OFFSET 0x2c // Interrupt Enable Register -#define DMA_INTERRUPT_EN_REG_OFFSET 0x2c +#define DMA_INTERRUPT_EN_REG_OFFSET 0x30 #define DMA_INTERRUPT_EN_TRANSACTION_DONE_BIT 0 #define DMA_INTERRUPT_EN_WINDOW_DONE_BIT 1 diff --git a/tb/ext_bus.sv b/tb/ext_bus.sv index 74755de30..66b7a0f66 100644 --- a/tb/ext_bus.sv +++ b/tb/ext_bus.sv @@ -40,8 +40,8 @@ module ext_bus #( input obi_pkg::obi_req_t heep_dma_write_ch0_req_i, output obi_pkg::obi_resp_t heep_dma_write_ch0_resp_o, - input obi_pkg::obi_req_t heep_dma_addr_ch0_req_i, - output obi_pkg::obi_resp_t heep_dma_addr_ch0_resp_o, + input obi_pkg::obi_req_t heep_dma_addr_bcst_ch0_req_i, + output obi_pkg::obi_resp_t heep_dma_addr_bcst_ch0_resp_o, // External master ports input obi_pkg::obi_req_t [EXT_XBAR_NMASTER_RND-1:0] ext_master_req_i, @@ -82,7 +82,7 @@ module ext_bus #( assign master_req[DEBUG_MASTER_IDX] = heep_debug_master_req_i; assign master_req[DMA_READ_CH0_IDX] = heep_dma_read_ch0_req_i; assign master_req[DMA_WRITE_CH0_IDX] = heep_dma_write_ch0_req_i; - assign master_req[DMA_ADDR_CH0_IDX] = heep_dma_addr_ch0_req_i; + assign master_req[DMA_ADDR_BCST_CH0_IDX] = heep_dma_addr_bcst_ch0_req_i; generate for (genvar i = 0; i < EXT_XBAR_NMASTER; i++) begin : gen_ext_master_req_map assign master_req[SYSTEM_XBAR_NMASTER+i] = demux_xbar_req[i][DEMUX_XBAR_EXT_SLAVE_IDX]; @@ -95,7 +95,7 @@ module ext_bus #( assign heep_debug_master_resp_o = master_resp[DEBUG_MASTER_IDX]; assign heep_dma_read_ch0_resp_o = master_resp[DMA_READ_CH0_IDX]; assign heep_dma_write_ch0_resp_o = master_resp[DMA_WRITE_CH0_IDX]; - assign heep_dma_addr_ch0_resp_o = master_resp[DMA_ADDR_CH0_IDX]; + assign heep_dma_addr_bcst_ch0_resp_o = master_resp[DMA_ADDR_BCST_CH0_IDX]; // X-HEEP slave requests generate diff --git a/tb/testharness.sv b/tb/testharness.sv index 74f666430..2851e7a7c 100644 --- a/tb/testharness.sv +++ b/tb/testharness.sv @@ -92,8 +92,8 @@ module testharness #( obi_resp_t heep_dma_read_ch0_resp; obi_req_t heep_dma_write_ch0_req; obi_resp_t heep_dma_write_ch0_resp; - obi_req_t heep_dma_addr_ch0_req; - obi_resp_t heep_dma_addr_ch0_resp; + obi_req_t heep_dma_addr_bcst_ch0_req; + obi_resp_t heep_dma_addr_bcst_ch0_resp; obi_req_t [EXT_XBAR_NSLAVE-1:0] ext_slave_req; obi_resp_t [EXT_XBAR_NSLAVE-1:0] ext_slave_resp; reg_req_t periph_slave_req; @@ -244,8 +244,8 @@ module testharness #( .ext_dma_read_ch0_resp_i(heep_dma_read_ch0_resp), .ext_dma_write_ch0_req_o(heep_dma_write_ch0_req), .ext_dma_write_ch0_resp_i(heep_dma_write_ch0_resp), - .ext_dma_addr_ch0_req_o(heep_dma_addr_ch0_req), - .ext_dma_addr_ch0_resp_i(heep_dma_addr_ch0_resp), + .ext_dma_addr_bcst_ch0_req_o(heep_dma_addr_bcst_ch0_req), + .ext_dma_addr_bcst_ch0_resp_i(heep_dma_addr_bcst_ch0_resp), .ext_peripheral_slave_req_o(periph_slave_req), .ext_peripheral_slave_resp_i(periph_slave_rsp), .external_subsystem_powergate_switch_no(external_subsystem_powergate_switch_n), @@ -266,28 +266,28 @@ module testharness #( .EXT_XBAR_NMASTER(EXT_XBAR_NMASTER), .EXT_XBAR_NSLAVE (EXT_XBAR_NSLAVE) ) ext_bus_i ( - .clk_i (clk_i), - .rst_ni (rst_ni), - .addr_map_i (EXT_XBAR_ADDR_RULES), - .default_idx_i (SLOW_MEMORY_IDX[LOG_EXT_XBAR_NSLAVE-1:0]), - .heep_core_instr_req_i (heep_core_instr_req), - .heep_core_instr_resp_o (heep_core_instr_resp), - .heep_core_data_req_i (heep_core_data_req), - .heep_core_data_resp_o (heep_core_data_resp), - .heep_debug_master_req_i (heep_debug_master_req), - .heep_debug_master_resp_o (heep_debug_master_resp), - .heep_dma_read_ch0_req_i (heep_dma_read_ch0_req), - .heep_dma_read_ch0_resp_o (heep_dma_read_ch0_resp), - .heep_dma_write_ch0_req_i (heep_dma_write_ch0_req), - .heep_dma_write_ch0_resp_o(heep_dma_write_ch0_resp), - .heep_dma_addr_ch0_req_i (heep_dma_addr_ch0_req), - .heep_dma_addr_ch0_resp_o (heep_dma_addr_ch0_resp), - .ext_master_req_i (ext_master_req), - .ext_master_resp_o (ext_master_resp), - .heep_slave_req_o (heep_slave_req), - .heep_slave_resp_i (heep_slave_resp), - .ext_slave_req_o (ext_slave_req), - .ext_slave_resp_i (ext_slave_resp) + .clk_i (clk_i), + .rst_ni (rst_ni), + .addr_map_i (EXT_XBAR_ADDR_RULES), + .default_idx_i (SLOW_MEMORY_IDX[LOG_EXT_XBAR_NSLAVE-1:0]), + .heep_core_instr_req_i (heep_core_instr_req), + .heep_core_instr_resp_o (heep_core_instr_resp), + .heep_core_data_req_i (heep_core_data_req), + .heep_core_data_resp_o (heep_core_data_resp), + .heep_debug_master_req_i (heep_debug_master_req), + .heep_debug_master_resp_o (heep_debug_master_resp), + .heep_dma_read_ch0_req_i (heep_dma_read_ch0_req), + .heep_dma_read_ch0_resp_o (heep_dma_read_ch0_resp), + .heep_dma_write_ch0_req_i (heep_dma_write_ch0_req), + .heep_dma_write_ch0_resp_o (heep_dma_write_ch0_resp), + .heep_dma_addr_bcst_ch0_req_i (heep_dma_addr_bcst_ch0_req), + .heep_dma_addr_bcst_ch0_resp_o(heep_dma_addr_bcst_ch0_resp), + .ext_master_req_i (ext_master_req), + .ext_master_resp_o (ext_master_resp), + .heep_slave_req_o (heep_slave_req), + .heep_slave_resp_i (heep_slave_resp), + .ext_slave_req_o (ext_slave_req), + .ext_slave_resp_i (ext_slave_resp) ); logic pdm; @@ -429,8 +429,8 @@ module testharness #( .dma_read_ch0_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER0_IDX]), .dma_write_ch0_req_o(ext_master_req[testharness_pkg::EXT_MASTER1_IDX]), .dma_write_ch0_resp_i(ext_master_resp[testharness_pkg::EXT_MASTER1_IDX]), - .dma_addr_ch0_req_o(), - .dma_addr_ch0_resp_i('0), + .dma_addr_bcst_ch0_req_o(), + .dma_addr_bcst_ch0_resp_i('0), .trigger_slot_i('0), .dma_done_intr_o(memcopy_intr), .dma_window_intr_o()