summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rtl/axi_timer/axi_bus.sv28
-rw-r--r--rtl/axi_timer/axi_timer.sv125
-rw-r--r--rtl/axi_timer/axi_timer_top.sv45
-rw-r--r--rtl/axi_timer/mod.mk10
-rw-r--r--rtl/axi_timer/testbench.py0
-rw-r--r--rtl/mod.mk2
6 files changed, 209 insertions, 1 deletions
diff --git a/rtl/axi_timer/axi_bus.sv b/rtl/axi_timer/axi_bus.sv
new file mode 100644
index 0000000..f1460ca
--- /dev/null
+++ b/rtl/axi_timer/axi_bus.sv
@@ -0,0 +1,28 @@
+//AXI interface bus
+interface axi_bus #(
+ parameter int unsigned AXI_ADDR_WIDTH = 32,
+ parameter int unsigned AXI_DATA_WIDTH = 32
+ );
+
+ logic [AXI_ADDR_WIDTH-1:0] ADDR;
+ logic AVALID;
+ logic AREADY;
+ logic AWRITE;
+ logic WVALID;
+ logic WREADY;
+ logic [AXI_DATA_WIDTH-1:0] WDATA;
+ logic RVALID;
+ logic RREADY;
+ logic [AXI_DATA_WIDTH-1:0] RDATA;
+
+ modport Master(
+ input AREADY, WREADY, RVALID, RDATA,
+ output ADDR, AVALID, AWRITE, WVALID, WDATA, RREADY
+ );
+
+ modport Slave(
+ input ADDR, AVALID, AWRITE, WVALID, WDATA, RREADY,
+ output AREADY, WREADY, RVALID, RDATA
+ );
+
+endinterface
diff --git a/rtl/axi_timer/axi_timer.sv b/rtl/axi_timer/axi_timer.sv
new file mode 100644
index 0000000..80a1805
--- /dev/null
+++ b/rtl/axi_timer/axi_timer.sv
@@ -0,0 +1,125 @@
+//axi_timer top file
+
+module axi_timer(
+ input i_clk,
+ input i_rst_n,
+
+ axi_bus.Slave axi_slave,
+
+ output logic o_IRQ
+ );
+
+// verilator lint_off CASEINCOMPLETE
+// verilator lint_off WIDTHEXPAND
+// verilator lint_off WIDTHTRUNC
+
+enum logic [2:0] {
+ CR_ADDR = 3'd0,
+ SR_ADDR = 3'd1,
+ PERIOD_ADDR = 3'd2,
+ COUNTER_ADDR = 3'd3,
+ IRQ_CNT_ADDR = 3'd4
+} address_map;
+
+/*Register map for axi_timer */
+//CR register
+logic enable;
+//SR register
+logic irq;
+//PERIOD register
+logic [31:0] period;
+//COUNTER register
+logic [31:0] counter;
+//IRQ_CNT register
+logic [31:0] irq_cnt;
+
+/* Native interface for access to register */
+logic addr_valid;
+logic addr;
+logic addr_ready;
+logic addr_write;
+
+logic write_valid;
+logic [31:0] wdata;
+logic write_ready;
+
+logic read_valid;
+logic [31:0] rdata;
+logic read_ready;
+
+/* Address section */
+assign addr_valid = axi_slave.AVALID;
+assign addr_write = axi_slave.AWRITE;
+assign axi_slave.AREADY = addr_ready;
+
+always_ff @ (posedge i_clk, negedge i_rst_n)
+ if(!i_rst_n)
+ addr_ready <= 1'b0;
+ else if(addr_valid & addr_write)
+ addr_ready <= 1'b1;
+ else
+ addr_ready <= 1'b0;
+
+always_ff @ (posedge i_clk, negedge i_rst_n)
+ if(!i_rst_n)
+ addr <= 'h0;
+ else if(addr_ready & addr_write)
+ addr <= axi_slave.ADDR;
+
+/*Write section */
+assign write_valid = axi_slave.WVALID;
+assign axi_slave.WREADY = write_ready;
+assign wdata = axi_slave.WDATA;
+
+always_ff @ (posedge i_clk, negedge i_rst_n)
+ if(!i_rst_n)
+ write_ready <= 1'b0;
+ else if(write_valid)
+ write_ready <= 1'b1;
+ else
+ write_ready <= 1'b0;
+
+/* registers write logic */
+always_ff @ (posedge i_clk, negedge i_rst_n)
+ if(!i_rst_n) begin
+ enable <= 1'b0;
+ period <= 32'd0;
+ irq_cnt <= 32'd0;
+ end
+ else if(write_valid) begin
+ case(addr)
+ CR_ADDR: enable <= wdata[0];
+ PERIOD_ADDR: counter <= wdata;
+ IRQ_CNT_ADDR: irq_cnt <= wdata;
+ endcase
+ end
+
+/*Read section */
+assign axi_slave.RVALID = read_valid;
+assign read_ready = axi_slave.RREADY;
+assign axi_slave.RDATA = rdata;
+
+always_ff @ (posedge i_clk, negedge i_rst_n)
+ if(!i_rst_n) begin
+ rdata <= 32'd0;
+ read_valid <= 1'b0;
+ end
+ else if(read_ready) begin
+ read_valid <= 1'b1;
+ case(addr)
+ CR_ADDR: rdata <= {31'd0, enable};
+ SR_ADDR: rdata <= {31'd0, irq};
+ PERIOD_ADDR: rdata <= period;
+ COUNTER_ADDR: rdata <= counter;
+ IRQ_CNT_ADDR: rdata <= irq_cnt;
+ endcase
+ end
+ else begin
+ read_valid <= 1'b0;
+ rdata <= 32'd0;
+ end
+
+
+
+
+endmodule //axi_timer
diff --git a/rtl/axi_timer/axi_timer_top.sv b/rtl/axi_timer/axi_timer_top.sv
new file mode 100644
index 0000000..6bd0e2a
--- /dev/null
+++ b/rtl/axi_timer/axi_timer_top.sv
@@ -0,0 +1,45 @@
+module axi_timer_top
+(
+ input logic clk,
+ rst_n,
+
+ input logic[31:0] addr,
+ input logic avalid,
+ input logic awrite,
+ output logic aready,
+
+ input logic wvalid,
+ input logic[31:0] wdata,
+ output logic wready,
+
+ input logic rready,
+ output logic[31:0] rdata,
+ output logic rvalid,
+
+ output logic irq
+);
+
+ axi_bus axi();
+
+ assign axi.Master.ADDR = addr;
+ assign axi.Master.AVALID = avalid;
+ assign axi.Master.AWRITE = awrite;
+ assign aready = axi.Master.AREADY;
+
+ assign axi.Master.WVALID = wvalid;
+ assign axi.Master.WDATA = wdata;
+ assign wready = axi.Master.WREADY;
+
+ assign axi.Master.RREADY = rready;
+ assign rdata = axi.Master.RDATA;
+ assign rvalid = axi.Master.RVALID;
+
+ axi_timer timer
+ (
+ .i_clk(clk),
+ .i_rst_n(rst_n),
+ .o_IRQ(irq),
+ .axi_slave(axi.Slave)
+ );
+
+endmodule
diff --git a/rtl/axi_timer/mod.mk b/rtl/axi_timer/mod.mk
new file mode 100644
index 0000000..2efe0f4
--- /dev/null
+++ b/rtl/axi_timer/mod.mk
@@ -0,0 +1,10 @@
+define core
+ $(this)/targets := sim test
+
+ $(this)/rtl_top := axi_timer_top
+ $(this)/rtl_dirs := .
+ $(this)/rtl_files := axi_bus.sv axi_timer_top.sv
+
+ $(this)/cocotb_paths := .
+ $(this)/cocotb_modules := testbench
+endef
diff --git a/rtl/axi_timer/testbench.py b/rtl/axi_timer/testbench.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/rtl/axi_timer/testbench.py
diff --git a/rtl/mod.mk b/rtl/mod.mk
index 0360207..be9cb44 100644
--- a/rtl/mod.mk
+++ b/rtl/mod.mk
@@ -1,5 +1,5 @@
cores := config debounce intc
-subdirs := cache core dma_axi32 fpu gfx perf picorv32 smp top wb2axip
+subdirs := axi_timer cache core dma_axi32 fpu gfx perf picorv32 smp top wb2axip
define core/config
$(this)/rtl_include_dirs := .