diff options
| author | Alejandro Soto <alejandro@34project.org> | 2024-05-05 21:29:41 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2024-05-05 21:29:41 -0600 |
| commit | e7266cad08ac6f1bcb90c5bbcc501b919882cf1a (patch) | |
| tree | 1092eeee0785ea945d7451016edcf32dc42faa33 | |
| parent | 63fc4c60a01e990858e36c3199867f3eaac481d5 (diff) | |
rtl/axilemu: implement AXI-Lite agent emulation
| -rw-r--r-- | rtl/axilemu/axilemu.sv | 70 | ||||
| -rw-r--r-- | rtl/axilemu/axilemu_if.rdl | 130 | ||||
| -rw-r--r-- | rtl/axilemu/mod.mk | 18 | ||||
| -rw-r--r-- | rtl/mod.mk | 2 |
4 files changed, 219 insertions, 1 deletions
diff --git a/rtl/axilemu/axilemu.sv b/rtl/axilemu/axilemu.sv new file mode 100644 index 0000000..e58737b --- /dev/null +++ b/rtl/axilemu/axilemu.sv @@ -0,0 +1,70 @@ +module axilemu +import axilemu_if_pkg::*; +( + input logic clk, + rst_n, + + if_axil.s agent, + driver, + + output logic irq +); + + axi4lite_intf #(.ADDR_WIDTH(AXILEMU_IF_MIN_ADDR_WIDTH)) regblock(); + + axilemu_if__in_t if_in; + axilemu_if__out_t if_out; + + assign agent.rdata = if_out.R.DATA.value; + assign agent.bvalid = if_out.B.VALID.value; + + assign if_in.CTRL.BDONE.hwset = agent.bvalid & agent.bready; + assign if_in.CTRL.RDONE.hwset = agent.rvalid & agent.rready; + assign if_in.CTRL.WVALID.next = agent.wvalid; + assign if_in.CTRL.ARVALID.next = agent.arvalid; + assign if_in.CTRL.AWVALID.next = agent.awvalid; + + assign if_in.AR.ADDR.next = agent.araddr[31:2]; + assign if_in.AR.VALID.hwset = agent.arvalid & ~agent.arready & ~if_out.AR.VALID.value; + + assign if_in.AW.ADDR.next = agent.awaddr[31:2]; + assign if_in.AW.VALID.hwset = agent.awvalid & ~agent.awready & ~if_out.AW.VALID.value; + + assign if_in.W.DATA.next = agent.wdata; + + assign if_in.B.VALID.hwclr = agent.bvalid & agent.bready; + + if_axil2regblock axil2regblock + ( + .axis(driver), + .axim(regblock.master) + ); + + axilemu_if regif + ( + .clk, + .arst_n(rst_n), + .s_axil(regblock.slave), + .hwif_in(if_in), + .hwif_out(if_out) + ); + + always_ff @(posedge clk or negedge rst_n) + if (~rst_n) begin + irq <= 0; + + agent.rvalid <= 0; + agent.wready <= 0; + agent.arready <= 0; + agent.awready <= 0; + end else begin + irq <= (if_out.CTRL.ARINT.value & agent.arvalid) + | (if_out.CTRL.AWINT.value & agent.awvalid); + + agent.rvalid <= if_out.R.DATA.swmod | (agent.rvalid & ~agent.rready); + agent.wready <= agent.wvalid & if_out.W.DATA.swacc; + agent.arready <= agent.arvalid & if_out.AR.VALID.swmod; + agent.awready <= agent.awvalid & if_out.AW.VALID.swmod; + end + +endmodule diff --git a/rtl/axilemu/axilemu_if.rdl b/rtl/axilemu/axilemu_if.rdl new file mode 100644 index 0000000..99283cf --- /dev/null +++ b/rtl/axilemu/axilemu_if.rdl @@ -0,0 +1,130 @@ +addrmap axilemu_if { + name = "AXI-Lite agent emulation interface"; + + default hw = w; + default sw = r; + default regwidth = 32; + default precedence = hw; + + reg { + name = "Agent control register"; + + field { + desc = "Enable interrupt on pending read"; + + hw = r; + sw = rw; + } ARINT[0:0] = 0; + + field { + desc = "Enable interrupt on pending write"; + + hw = r; + sw = rw; + } AWINT[1:1] = 0; + + field { + desc = "Read command is pending"; + } ARVALID[8:8] = 0; + + field { + desc = "Write command is pending"; + } AWVALID[9:9] = 0; + + field { + desc = "Last read data acknowledged"; + + hw = na; + + rclr; + hwset; + } RDONE[10:10] = 0; + + field { + desc = "Write data is pending"; + } WVALID[11:11] = 0; + + field { + desc = "Last write response acknowledged"; + + hw = na; + + rclr; + hwset; + } BDONE[12:12] = 0; + } CTRL @ 0x00; + + reg { + name = "Read command channel"; + + field { + desc = "Read is pending"; + + hw = r; + + rclr; + hwset; + swmod; + } VALID[0:0] = 0; + + field { + desc = "Read address"; + } ADDR[31:2]; + } AR @ 0x04; + + reg { + name = "Write command channel"; + + field { + desc = "Write is pending"; + + hw = r; + + rclr; + hwset; + swmod; + } VALID[0:0] = 0; + + field { + desc = "Write address"; + } ADDR[31:2]; + } AW @ 0x08; + + reg { + name = "Read data channel"; + + field { + desc = "Read data"; + + hw = r; + sw = rw; + + swmod; + } DATA[31:0]; + } R @ 0x0c; + + reg { + name = "Write data channel"; + + field { + desc = "Write data"; + + swacc; + } DATA[31:0]; + } W @ 0x10; + + reg { + name = "Write response channel"; + + field { + desc = "Valid response"; + + hw = r; + sw = rw; + + hwclr; + woset; + } VALID[0:0]; + } B @ 0x14; +}; + diff --git a/rtl/axilemu/mod.mk b/rtl/axilemu/mod.mk new file mode 100644 index 0000000..60747a7 --- /dev/null +++ b/rtl/axilemu/mod.mk @@ -0,0 +1,18 @@ +cores := axilemu_if + +define core + $(this)/deps := axilemu_if if_common + + $(this)/rtl_top := axilemu + $(this)/rtl_dirs := . + $(this)/rtl_files := axilemu.sv +endef + +define core/axilemu_if + $(this)/hooks := regblock + + $(this)/regblock_rdl := axilemu_if.rdl + $(this)/regblock_top := axilemu_if + $(this)/regblock_args := --default-reset arst_n + $(this)/regblock_cpuif := axi4-lite +endef @@ -1,5 +1,5 @@ cores := config debounce intc -subdirs := cache core dma_axi32 if_common fpu gfx legacy_gfx perf picorv32 pkt_switch smp top wb2axip +subdirs := axilemu cache core dma_axi32 if_common fpu gfx legacy_gfx perf picorv32 pkt_switch smp top wb2axip define core/config $(this)/rtl_include_dirs := . |
