diff --git a/designs/controller_dma_connective/tests/tb_control_dma_behav.wcfg b/designs/controller_dma_connective/tests/tb_control_dma_behav.wcfg new file mode 100644 index 0000000..16048c6 --- /dev/null +++ b/designs/controller_dma_connective/tests/tb_control_dma_behav.wcfg @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + dac_clk_in + dac_clk_in + #FFA500 + true + + + adc_clk_in + adc_clk_in + + + rst_n + rst_n + #800080 + true + + + rst_soft + rst_soft + #008080 + true + + + start + start + #E0FFFF + true + + + adc_start_pulse + adc_start_pulse + + + dac_start_pulse + dac_start_pulse + + + busy + busy + #E0FFFF + true + + + finish + finish + #FAAFBE + true + + + finish_pulse + finish_pulse + + + cfg_bus_valid + cfg_bus_valid + #FF0080 + true + + + cfg_bus_input[159:0] + cfg_bus_input[159:0] + #FF0080 + true + + + dac_pulse_width[31:0] + dac_pulse_width[31:0] + #FFA500 + true + + + dac_pulse_period[31:0] + dac_pulse_period[31:0] + #FFA500 + true + + + dac_pulse_height[11:0] + dac_pulse_height[11:0] + #FFA500 + true + HEXRADIX + + + dac_pulse_num[15:0] + dac_pulse_num[15:0] + #FFA500 + true + + + adc_pulse_period[31:0] + adc_pulse_period[31:0] + #FFA500 + true + + + adc_pulse_num[15:0] + adc_pulse_num[15:0] + #FFA500 + true + + + adc_window_size[31:0] + adc_window_size[31:0] + + + dac_start + dac_start + #FFA500 + true + + + adc_start + adc_start + + + dac_rst + dac_rst + #FFA500 + true + + + adc_rst + adc_rst + + + tb signals + label + + dac_rst_count[31:0] + dac_rst_count[31:0] + #F0E68C + true + + + adc_rst_count[31:0] + adc_rst_count[31:0] + #F0E68C + true + + + dac_start_count[31:0] + dac_start_count[31:0] + #F0E68C + true + + + adc_start_count[31:0] + adc_start_count[31:0] + #F0E68C + true + + + + cfg_req_toggle_adc + cfg_req_toggle_adc + #FFFF00 + true + + + cfg_req_toggle_dac + cfg_req_toggle_dac + #FFFF00 + true + + + cfg_ack_toggle_adc + cfg_ack_toggle_adc + #FF00FF + true + + + cfg_ack_toggle_dac + cfg_ack_toggle_dac + #FF00FF + true + + + cfg_wait_adc_ack + cfg_wait_adc_ack + #0000FF + true + + + cfg_wait_dac_ack + cfg_wait_dac_ack + #0000FF + true + + + cfg_req_pulse_adc + cfg_req_pulse_adc + #808000 + true + + + cfg_req_pulse_dac + cfg_req_pulse_dac + #808000 + true + + + cfg_ack_pulse_adc + cfg_ack_pulse_adc + #DCDCDC + true + + + cfg_ack_pulse_dac + cfg_ack_pulse_dac + #DCDCDC + true + + diff --git a/designs/controller_dma_connective/tests/tb_controller_dma_wrapper_axil.sv b/designs/controller_dma_connective/tests/tb_controller_dma_wrapper_axil.sv new file mode 100644 index 0000000..1c257e1 --- /dev/null +++ b/designs/controller_dma_connective/tests/tb_controller_dma_wrapper_axil.sv @@ -0,0 +1,371 @@ + +import dma_reg_pkg::*; + +module tb_controller_wrapper_axil #( + parameter int unsigned ADDR_W = 16, + parameter int unsigned DATA_W = 32, + parameter int unsigned USER_W = 1, + + parameter int unsigned DAC_DATA_WIDTH = 12, + + parameter int unsigned AXI_DATA_WIDTH = 32, + + parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8, + parameter int unsigned AXI_ID_WIDTH = 8, + parameter int unsigned AXI_USER_WIDTH = 1, + parameter int unsigned AXI_MAX_BURST_LEN = 16, + + parameter int unsigned AXIS_DATA_WIDTH = AXI_DATA_WIDTH, + parameter int unsigned AXIS_KEEP_ENABLE = AXIS_DATA_WIDTH > 8, + parameter int unsigned AXIS_KEEP_WIDTH = AXIS_DATA_WIDTH / 8, + parameter int unsigned AXIS_LAST_ENABLE = 1, + parameter int unsigned AXIS_ID_ENABLE = 1, + parameter int unsigned AXIS_DEST_ENABLE = 0, + parameter int unsigned AXIS_USER_ENABLE = 1, + + parameter int unsigned ENABLE_SG = 0, + parameter int unsigned ENABLE_UNALIGNED = 0 +)( + input logic ctrl_clk, + input logic rst, + + input logic [ADDR_W-1:0] s_axil_awaddr, + input logic [2:0] s_axil_awprot, + input logic s_axil_awvalid, + output logic s_axil_awready, + + input logic [DATA_W-1:0] s_axil_wdata, + input logic [DATA_W/8-1:0] s_axil_wstrb, + input logic s_axil_wvalid, + output logic s_axil_wready, + + output logic [1:0] s_axil_bresp, + output logic s_axil_bvalid, + input logic s_axil_bready, + + input logic [ADDR_W-1:0] s_axil_araddr, + input logic [2:0] s_axil_arprot, + input logic s_axil_arvalid, + output logic s_axil_arready, + + output logic [DATA_W-1:0] s_axil_rdata, + output logic [1:0] s_axil_rresp, + output logic s_axil_rvalid, + input logic s_axil_rready, + + input wire [AXIS_DATA_WIDTH-1:0] s_axis_write_data_tdata, + input wire [AXIS_KEEP_WIDTH-1:0] s_axis_write_data_tkeep, + input wire s_axis_write_data_tvalid, + output wire s_axis_write_data_tready, + input wire s_axis_write_data_tlast, + input wire [AXIS_ID_WIDTH-1:0] s_axis_write_data_tid, + input wire [AXIS_DEST_WIDTH-1:0] s_axis_write_data_tdest, + input wire [AXIS_USER_WIDTH-1:0] s_axis_write_data_tuser, + + output wire [AXIS_DATA_WIDTH-1:0] m_axis_read_data_tdata, + output wire [AXIS_KEEP_WIDTH-1:0] m_axis_read_data_tkeep, + output wire m_axis_read_data_tvalid, + input wire m_axis_read_data_tready, + output wire m_axis_read_data_tlast, + output wire [AXIS_ID_WIDTH-1:0] m_axis_read_data_tid, + output wire [AXIS_DEST_WIDTH-1:0] m_axis_read_data_tdest, + output wire [AXIS_USER_WIDTH-1:0] m_axis_read_data_tuser, + + output wire [AXI_ID_WIDTH-1:0] m_axi_awid, + output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr, + output wire [7:0] m_axi_awlen, + output wire [2:0] m_axi_awsize, + output wire [1:0] m_axi_awburst, + output wire m_axi_awlock, + output wire [3:0] m_axi_awcache, + output wire [2:0] m_axi_awprot, + output wire m_axi_awvalid, + input wire m_axi_awready, + output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata, + output wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb, + output wire m_axi_wlast, + output wire m_axi_wvalid, + input wire m_axi_wready, + input wire [AXI_ID_WIDTH-1:0] m_axi_bid, + input wire [1:0] m_axi_bresp, + input wire m_axi_bvalid, + output wire m_axi_bready, + output wire [AXI_ID_WIDTH-1:0] m_axi_arid, + output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr, + output wire [7:0] m_axi_arlen, + output wire [2:0] m_axi_arsize, + output wire [1:0] m_axi_arburst, + output wire m_axi_arlock, + output wire [3:0] m_axi_arcache, + output wire [2:0] m_axi_arprot, + output wire m_axi_arvalid, + input wire m_axi_arready, + input wire [AXI_ID_WIDTH-1:0] m_axi_rid, + input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata, + input wire [1:0] m_axi_rresp, + input wire m_axi_rlast, + input wire m_axi_rvalid, + output wire m_axi_rready +); + + logic rst_n; + assign rst_n = ~rst; + + // Для минимального теста держим все clock domain-ы на одном clock. + logic dac_clk_in; + logic adc_clk_in; + assign dac_clk_in = ctrl_clk; + assign adc_clk_in = ctrl_clk; + + logic finish; + assign finish = 1'b0; + + // --------------------------------------------------------------------------- + // AXI-Lite flat -> axi4l_if + // --------------------------------------------------------------------------- + + axi4l_if #( + .ADDR_W(ADDR_W), + .DATA_W(DATA_W), + .USER_W(USER_W) + ) axil_bus ( + .aclk(ctrl_clk), + .aresetn(rst_n) + ); + + axi4l_flat_to_if #( + .ADDR_W(ADDR_W), + .DATA_W(DATA_W), + .USER_W(USER_W) + ) u_axil_flat_to_if ( + .s_axil_awaddr (s_axil_awaddr), + .s_axil_awprot (s_axil_awprot), + .s_axil_awvalid(s_axil_awvalid), + .s_axil_awready(s_axil_awready), + + .s_axil_wdata (s_axil_wdata), + .s_axil_wstrb (s_axil_wstrb), + .s_axil_wvalid (s_axil_wvalid), + .s_axil_wready (s_axil_wready), + + .s_axil_bresp (s_axil_bresp), + .s_axil_bvalid (s_axil_bvalid), + .s_axil_bready (s_axil_bready), + + .s_axil_araddr (s_axil_araddr), + .s_axil_arprot (s_axil_arprot), + .s_axil_arvalid(s_axil_arvalid), + .s_axil_arready(s_axil_arready), + + .s_axil_rdata (s_axil_rdata), + .s_axil_rresp (s_axil_rresp), + .s_axil_rvalid (s_axil_rvalid), + .s_axil_rready (s_axil_rready), + + .m_axil(axil_bus) + ); + + // --------------------------------------------------------------------------- + // AXIS interfaces for the updated controller_wrapper_axil + // --------------------------------------------------------------------------- + +// AXIS READ DMA MASTER output + axis_if #( + .DATA_W (AXIS_DATA_WIDTH), + .KEEP_W (AXIS_KEEP_WIDTH), + .ID_W (AXIS_ID_WIDTH), + .DEST_W (AXIS_DEST_WIDTH), + .USER_W (AXIS_USER_WIDTH) + ) dma_read_data ( + .aclk(ctrl_clk), + .aresetn(rst_n) + ); + +logic [AXIS_KEEP_WIDTH-1:0] unused_read_tstrb; + +axis_if_to_flat #( + .DATA_W (AXIS_DATA_WIDTH), + .KEEP_W (AXIS_KEEP_WIDTH), + .ID_W (AXIS_ID_WIDTH), + .DEST_W (AXIS_DEST_WIDTH), + .USER_W (AXIS_USER_WIDTH) +) u_read_data_if_to_flat ( + .s_axis(dma_read_data), + + .m_axis_tdata (m_axis_read_data_tdata), + .m_axis_tkeep (m_axis_read_data_tkeep), + .m_axis_tstrb (unused_read_tstrb), + .m_axis_tlast (m_axis_read_data_tlast), + .m_axis_tid (m_axis_read_data_tid), + .m_axis_tdest (m_axis_read_data_tdest), + .m_axis_tuser (m_axis_read_data_tuser), + .m_axis_tvalid(m_axis_read_data_tvalid), + .m_axis_tready(m_axis_read_data_tready) +); + +// AXIS WRITE DMA SLAVE input + axis_if #( + .DATA_W (AXIS_DATA_WIDTH), + .KEEP_W (AXIS_KEEP_WIDTH), + .ID_W (AXIS_ID_WIDTH), + .DEST_W (AXIS_DEST_WIDTH), + .USER_W (AXIS_USER_WIDTH) + ) dma_write_data ( + .aclk(ctrl_clk), + .aresetn(rst_n) + ); + + +axis_flat_to_if #( + .DATA_W (AXIS_DATA_WIDTH), + .KEEP_W (AXIS_KEEP_WIDTH), + .ID_W (AXIS_ID_WIDTH), + .DEST_W (AXIS_DEST_WIDTH), + .USER_W (AXIS_USER_WIDTH) +) u_write_data_flat_to_if ( + .s_axis_tdata (s_axis_write_data_tdata), + .s_axis_tkeep (s_axis_write_data_tkeep), + .s_axis_tstrb (s_axis_write_data_tkeep), + .s_axis_tlast (s_axis_write_data_tlast), + .s_axis_tid (s_axis_write_data_tid), + .s_axis_tdest (s_axis_write_data_tdest), + .s_axis_tuser (s_axis_write_data_tuser), + .s_axis_tvalid(s_axis_write_data_tvalid), + .s_axis_tready(s_axis_write_data_tready), + + .m_axis(dma_write_data) +); + +// AXI4 MASTER DMA + +axi4_if #( + .ADDR_W(dma_reg_pkg::AXI_ADDR_WIDTH), + .DATA_W(AXI_DATA_WIDTH), + .ID_W (AXI_ID_WIDTH), + .USER_W(AXI_USER_WIDTH) +) s_axi ( + .aclk(ctrl_clk), + .aresetn(rst_n) +); + +logic [AXI_USER_WIDTH-1:0] unused_awuser; +logic [AXI_USER_WIDTH-1:0] unused_wuser; +logic [AXI_USER_WIDTH-1:0] unused_aruser; + +axi4_if_to_flat #( + .ADDR_W (dma_reg_pkg::AXI_ADDR_WIDTH), + .DATA_W (AXI_DATA_WIDTH), + .ID_W (AXI_ID_WIDTH), + .USER_W (AXI_USER_WIDTH) +) u_axi_if_to_flat ( + .s_axi(s_axi), + + .m_axi_awid (m_axi_awid), + .m_axi_awaddr (m_axi_awaddr), + .m_axi_awlen (m_axi_awlen), + .m_axi_awsize (m_axi_awsize), + .m_axi_awburst (m_axi_awburst), + .m_axi_awlock (m_axi_awlock), + .m_axi_awcache (m_axi_awcache), + .m_axi_awprot (m_axi_awprot), + .m_axi_awqos (), + .m_axi_awregion(), + .m_axi_awuser (unused_awuser), + .m_axi_awvalid (m_axi_awvalid), + .m_axi_awready (m_axi_awready), + + .m_axi_wdata (m_axi_wdata), + .m_axi_wstrb (m_axi_wstrb), + .m_axi_wlast (m_axi_wlast), + .m_axi_wuser (unused_wuser), + .m_axi_wvalid (m_axi_wvalid), + .m_axi_wready (m_axi_wready), + + .m_axi_bid (m_axi_bid), + .m_axi_bresp (m_axi_bresp), + .m_axi_buser ({AXI_USER_WIDTH{1'b0}}), + .m_axi_bvalid (m_axi_bvalid), + .m_axi_bready (m_axi_bready), + + .m_axi_arid (m_axi_arid), + .m_axi_araddr (m_axi_araddr), + .m_axi_arlen (m_axi_arlen), + .m_axi_arsize (m_axi_arsize), + .m_axi_arburst (m_axi_arburst), + .m_axi_arlock (m_axi_arlock), + .m_axi_arcache (m_axi_arcache), + .m_axi_arprot (m_axi_arprot), + .m_axi_arqos (), + .m_axi_arregion(), + .m_axi_aruser (unused_aruser), + .m_axi_arvalid (m_axi_arvalid), + .m_axi_arready (m_axi_arready), + + .m_axi_rid (m_axi_rid), + .m_axi_rdata (m_axi_rdata), + .m_axi_rresp (m_axi_rresp), + .m_axi_rlast (m_axi_rlast), + .m_axi_ruser ({AXI_USER_WIDTH{1'b0}}), + .m_axi_rvalid (m_axi_rvalid), + .m_axi_rready (m_axi_rready) +); + + + // Controller ADC/DAC outputs. + logic [31:0] adc_window_size; + logic [31:0] dac_pulse_width; + logic [31:0] dac_pulse_period; + logic [DAC_DATA_WIDTH-1:0] dac_pulse_height; + logic [15:0] dac_pulse_num; + logic [31:0] adc_pulse_period; + logic [15:0] adc_pulse_num; + logic dac_start; + logic adc_start; + logic dac_rst; + logic adc_rst; + + wrapper_controller_dma #( + .ADDR_W(ADDR_W), + .DATA_W(DATA_W), + .USER_W(USER_W), + .DAC_DATA_WIDTH(DAC_DATA_WIDTH), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH), + .AXI_ID_WIDTH(AXI_ID_WIDTH), + .AXI_USER_WIDTH(AXI_USER_WIDTH), + .AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN), + .AXIS_LAST_ENABLE(AXIS_LAST_ENABLE), + .AXIS_ID_ENABLE(AXIS_ID_ENABLE), + .AXIS_DEST_ENABLE(AXIS_DEST_ENABLE), + .AXIS_USER_ENABLE(AXIS_USER_ENABLE), + .ENABLE_SG(ENABLE_SG), + .ENABLE_UNALIGNED(ENABLE_UNALIGNED) + ) dut ( + .ctrl_clk(ctrl_clk), + .dac_clk_in(dac_clk_in), + .adc_clk_in(adc_clk_in), + .rst_n(rst_n), + .s_axil(axil_bus), + + .finish(finish), + .adc_window_size(adc_window_size), + + .dac_pulse_width(dac_pulse_width), + .dac_pulse_period(dac_pulse_period), + .dac_pulse_height(dac_pulse_height), + .dac_pulse_num(dac_pulse_num), + + .adc_pulse_period(adc_pulse_period), + .adc_pulse_num(adc_pulse_num), + + .dac_start(dac_start), + .adc_start(adc_start), + .dac_rst(dac_rst), + .adc_rst(adc_rst), + + .s_axis_read_data(dma_read_data), + .m_axis_write_data(dma_write_data), + + .s_axi(s_axi) + ); + +endmodule : tb_controller_wrapper_axil diff --git a/designs/controller_dma_connective/tests/test_controller_and_dma.py b/designs/controller_dma_connective/tests/test_controller_and_dma.py new file mode 100644 index 0000000..e1b8f4c --- /dev/null +++ b/designs/controller_dma_connective/tests/test_controller_and_dma.py @@ -0,0 +1,221 @@ +import cocotb +from cocotb.clock import Clock +from cocotb.handle import Immediate +from cocotb.triggers import RisingEdge +from cocotbext.axi import AxiLiteBus, AxiLiteMaster +from cocotbext.axi import AxiBus, AxiRam, AxiStreamBus, AxiStreamSource, AxiStreamSink + + +# Register indexes from axi4l_reg_map_controller_pkg.sv +REG_CONTROL = 0 +REG_STATUS = 1 +REG_DAC_WIDTH = 2 +REG_DAC_PERIOD = 3 +REG_DAC_PULSE_NUM = 4 +REG_DAC_PULSE_HEIGHT = 5 +REG_ADC_PERIOD = 6 +REG_WINDOW_SIZE = 7 +REG_ERROR = 8 +REG_DESC_READ_ADDR = 9 +REG_DESC_READ_LEN = 10 +REG_DESC_READ_CONFIG = 11 +REG_READ_STATUS = 12 +REG_DESC_WRITE_ADDR = 13 +REG_DESC_WRITE_LEN_AND_TAG = 14 +REG_STATUS_WRITE_LEN = 15 +REG_STATUS_WRITE_CONFIG = 16 + + +# REG_CONTROL pulse bits +CTRL_START = 0 +CTRL_RST_SOFT = 1 +CTRL_CFG_BUS_VALID = 2 +CTRL_SEND_DESC_READ = 3 +CTRL_SEND_DESC_WRITE = 4 +CTRL_TAKE_STATUS_READ = 5 +CTRL_TAKE_STATUS_WRITE = 6 + + +def reg_addr(reg_index: int) -> int: + # AXI-Lite uses byte addresses, 32-bit registers are spaced by 4 bytes. + return reg_index * 4 + + +def u32(value: int) -> bytes: + return int(value & 0xFFFFFFFF).to_bytes(4, "little") + + +class TB: + def __init__(self, dut): + self.dut = dut + + cocotb.start_soon(Clock(dut.ctrl_clk, 10, units="ns").start()) + + self.axil = AxiLiteMaster( + AxiLiteBus.from_prefix(dut, "s_axil"), + dut.ctrl_clk, + dut.rst + ) + + self.mem = AxiRam( + AxiBus.from_prefix( dut, "m_axi"), + dut.ctrl_clk, + dut.rst + ) + + self.axis_source = AxiStreamSource( + AxiStreamBus.from_prefix(dut, "s_axis_write_data"), + dut.ctrl_clk, + dut.rst + ) + + self.axis_sink = AxiStreamSink( + AxiStreamBus.from_prefix(dut, "m_axis_read_data"), + dut.ctrl_clk, + dut.rst + ) + + async def reset(self): + self.dut.rst.value = 1 + for _ in range(5): + await RisingEdge(self.dut.ctrl_clk) + + self.dut.rst.value = 0 + for _ in range(5): + await RisingEdge(self.dut.ctrl_clk) + + async def write_reg(self, reg_index: int, value: int): + await self.axil.write(reg_addr(reg_index), u32(value)) + + async def read_reg(self, reg_index: int) -> int: + resp = await self.axil.read(reg_addr(reg_index), 4) + return int.from_bytes(bytes(resp.data), "little") + + +@cocotb.test() +async def simple_axil_write_read(dut): + tb = TB(dut) + await tb.reset() + + await tb.write_reg(REG_DAC_WIDTH, 0x0000_0123) + + value = await tb.read_reg(REG_DAC_WIDTH) + assert value == 0x0000_0123 + + +@cocotb.test() +async def simple_controller_config_write(dut): + tb = TB(dut) + await tb.reset() + + await tb.write_reg(REG_DAC_WIDTH, 0x10) + await tb.write_reg(REG_DAC_PERIOD, 0x40) + await tb.write_reg(REG_DAC_PULSE_NUM, 3) + await tb.write_reg(REG_DAC_PULSE_HEIGHT, 0x7FF) + await tb.write_reg(REG_ADC_PERIOD, 0x80) + await tb.write_reg(REG_WINDOW_SIZE, 16) + + assert await tb.read_reg(REG_DAC_WIDTH) == 0x10 + assert await tb.read_reg(REG_WINDOW_SIZE) == 16 + + # write data: set cfg_bus_valid signal + await tb.write_reg(REG_CONTROL, 1 << CTRL_CFG_BUS_VALID) + + # wait + for _ in range(30): + await RisingEdge(dut.ctrl_clk) + + # check config + assert int(dut.dac_pulse_width) == 0x10 + assert int(dut.dac_pulse_period) == 0x40 + assert int(dut.dac_pulse_num) == 3 + assert int(dut.dac_pulse_height) == 0x7FF + assert int(dut.adc_pulse_period) == 0x80 + assert int(dut.adc_window_size) == 16 + + await RisingEdge(dut.ctrl_clk) + + +@cocotb.test() +async def simple_controller_start_check(dut): + tb = TB(dut) + await tb.reset() + await tb.write_reg(REG_CONTROL, 1 << CTRL_START) + + await RisingEdge(dut.dac_start) + +@cocotb.test() +async def test_dma_write(dut): + tb = TB(dut) + await tb.reset() + + data = bytes(range(64)) + + #write data into memory + + await tb.write_reg(REG_DESC_WRITE_ADDR, 0x1000) + await tb.write_reg(REG_DESC_WRITE_LEN_AND_TAG, 64) + + + await tb.write_reg(REG_CONTROL, 1 << CTRL_SEND_DESC_WRITE) + await RisingEdge(dut.ctrl_clk) + cocotb.start_soon(tb.axis_source.send(data)) + + for _ in range(200): + await tb.write_reg( REG_CONTROL, 1 << CTRL_TAKE_STATUS_WRITE) + + await RisingEdge(dut.ctrl_clk) + + status = await tb.read_reg( REG_STATUS_WRITE_LEN) + if status == 64: + break + + else: + assert False, "DMA timeout" + + + mem = await tb.mem.read( 0x1000, 64) + assert mem == data + +@cocotb.test() +async def test_dma_read(dut): + tb = TB(dut) + await tb.reset() + + data = bytes(range(64)) + + #read data from memory + + await tb.mem.write( 0x2000, data) + + await tb.write_reg( REG_DESC_READ_ADDR, 0x2000) + await tb.write_reg( REG_DESC_READ_LEN, 64) + await tb.write_reg( REG_DESC_READ_CONFIG, 1) + + await tb.write_reg( REG_CONTROL, 1 << CTRL_SEND_DESC_READ) + + frame = await tb.axis_sink.recv() + assert frame.data == data + + await tb.write_reg( + REG_CONTROL, + 1 << CTRL_TAKE_STATUS_READ + ) + + for _ in range(100): + + status = await tb.read_reg( + REG_READ_STATUS + ) + + if status != 0: + break + + await RisingEdge(dut.ctrl_clk) + else: + assert False, "DMA read status timeout" + + + + + diff --git a/designs/controller_dma_connective/tests/test_timing.xdc b/designs/controller_dma_connective/tests/test_timing.xdc new file mode 100644 index 0000000..2ecbc36 --- /dev/null +++ b/designs/controller_dma_connective/tests/test_timing.xdc @@ -0,0 +1,13 @@ +# Primary clocks +create_clock -name eth_clk -period 8.000 [get_ports eth_clk_in] +create_clock -name dac_clk -period 7.692 [get_ports dac_clk_in] +create_clock -name adc_clk -period 15.385 [get_ports adc_clk_in] + + +# Asynchronous clock groups +# eth, dac, adc are independent domains + +set_clock_groups -name ASYNC_ETH_DAC_ADC -asynchronous \ + -group [get_clocks eth_clk] \ + -group [get_clocks dac_clk] \ + -group [get_clocks adc_clk]