From 453694150c4bc98508eee1c428a6cdae36d55a90 Mon Sep 17 00:00:00 2001 From: Caleb Whitehead Date: Tue, 18 Jun 2024 17:25:10 -0700 Subject: [PATCH] Fixups to get sims working VCS + Verilator --- src/axi/rtl/axi_if.sv | 212 ++++++++++++++++++++++++++------------ src/axi/rtl/axi_sub_rd.sv | 13 +-- 2 files changed, 153 insertions(+), 72 deletions(-) diff --git a/src/axi/rtl/axi_if.sv b/src/axi/rtl/axi_if.sv index ab727677d..daa6d45c6 100644 --- a/src/axi/rtl/axi_if.sv +++ b/src/axi/rtl/axi_if.sv @@ -156,45 +156,55 @@ interface axi_if #(parameter integer AW = 32, parameter integer DW = 32, paramet ); // Tasks + `ifdef VERILATOR + `define EQ__ = + `define TIME_ALGN #100ps + `else + `define EQ__ <= + `define TIME_ALGN + `endif task rst_mgr(); - araddr = '0; - arburst = AXI_BURST_FIXED; - arsize = '0; - arlen = '0; - aruser = '0; - arid = '0; - arlock = '0; - arvalid = '0; + araddr `EQ__ '0; + arburst `EQ__ AXI_BURST_FIXED; + arsize `EQ__ '0; + arlen `EQ__ '0; + aruser `EQ__ '0; + arid `EQ__ '0; + arlock `EQ__ '0; + arvalid `EQ__ '0; - rready = '0; + rready `EQ__ '0; - awaddr = '0; - awburst = AXI_BURST_FIXED; - awsize = '0; - awlen = '0; - awuser = '0; - awid = '0; - awlock = '0; - awvalid = '0; + awaddr `EQ__ '0; + awburst `EQ__ AXI_BURST_FIXED; + awsize `EQ__ '0; + awlen `EQ__ '0; + awuser `EQ__ '0; + awid `EQ__ '0; + awlock `EQ__ '0; + awvalid `EQ__ '0; - wdata = '0; - wstrb = '0; - wvalid = '0; - wlast = '0; + wdata `EQ__ '0; + wstrb `EQ__ '0; + wvalid `EQ__ '0; + wlast `EQ__ '0; - bready = '0; + bready `EQ__ '0; endtask // TODO: handle IDs? - task get_read_beat(ref logic [DW-1:0] data, - ref axi_resp_e resp); - rready = 1; + task get_read_beat(output logic [DW-1:0] data, + output axi_resp_e resp); + `TIME_ALGN + rready `EQ__ 1; do @(posedge clk); while (!rvalid); - data = rdata; - resp = axi_resp_e'(rresp); - rready = 0; + data `EQ__ rdata; + resp `EQ__ axi_resp_e'(rresp); + `TIME_ALGN + rready `EQ__ 0; + wait(!rready); endtask // Read: default to single beat of native data width @@ -205,22 +215,34 @@ interface axi_if #(parameter integer AW = 32, parameter integer DW = 32, paramet input logic [UW-1:0] user = UW'(0), input logic [IW-1:0] id = IW'(0), input logic lock = 1'b0, - ref logic [DW-1:0] data [], - ref axi_resp_e resp []); + output logic [DW-1:0] data [], + output axi_resp_e resp []); axi_resp_e beat_resp; logic [DW-1:0] beat_data; while(!rst_n) @(posedge clk); do begin - araddr = addr; - arburst = burst; - arsize = size; - arlen = len; - aruser = user; - arid = id; - arlock = lock; - arvalid = 1; + `TIME_ALGN + araddr `EQ__ addr; + arburst `EQ__ burst; + arsize `EQ__ size; + arlen `EQ__ len; + aruser `EQ__ user; + arid `EQ__ id; + arlock `EQ__ lock; + arvalid `EQ__ 1; @(posedge clk); end while(!arready); + `TIME_ALGN + araddr `EQ__ '0; + arburst `EQ__ AXI_BURST_FIXED; + arsize `EQ__ '0; + arlen `EQ__ '0; + aruser `EQ__ '0; + arid `EQ__ '0; + arlock `EQ__ '0; + arvalid `EQ__ '0; + data = new[len+1]; + resp = new[len+1]; for (int beat=0; beat <= len; beat++) begin get_read_beat(beat_data, beat_resp); data[beat] = beat_data; @@ -228,48 +250,89 @@ interface axi_if #(parameter integer AW = 32, parameter integer DW = 32, paramet end endtask + task axi_read_single(input logic [AW-1:0] addr, + input logic [UW-1:0] user = UW'(0), + input logic [IW-1:0] id = IW'(0), + input logic lock = 1'b0, + output logic [DW-1:0] data, + output axi_resp_e resp); + automatic axi_resp_e burst_resp[]; + automatic logic [DW-1:0] burst_data[]; + axi_read(.addr(addr), + .user(user), + .id (id ), + .lock(lock), + .data(burst_data), + .resp(burst_resp)); + data = burst_data[0]; + resp = burst_resp[0]; + endtask + task send_write_beat(input logic last, input logic [DW-1:0] data, input logic [DW/8-1:0] strb); - wvalid = 1; - wlast = last; - wdata = data; - wstrb = strb; + `TIME_ALGN + wvalid `EQ__ 1; + wlast `EQ__ last; + wdata `EQ__ data; + wstrb `EQ__ strb; do @(posedge clk); while (!wready); + `TIME_ALGN + wvalid `EQ__ '0; + wlast `EQ__ '0; + wdata `EQ__ '0; + wstrb `EQ__ '0; + wait(!wvalid); endtask // TODO handle ID task get_write_resp(output axi_resp_e resp); - bready = 1; - while(!bvalid) @(posedge clk); - resp = axi_resp_e'(bresp); + `TIME_ALGN + bready `EQ__ 1; + do + @(posedge clk); + while(!bvalid); + resp `EQ__ axi_resp_e'(bresp); + `TIME_ALGN + bready `EQ__ 0; + wait(!bready); endtask - task axi_write( input logic [AW-1:0] addr, - input axi_burst_e burst = AXI_BURST_INCR, - input logic [2:0] size = $clog2(DW/8), - input logic [7:0] len = 0, - input logic [UW-1:0] user = UW'(0), - input logic [IW-1:0] id = IW'(0), - input logic lock = 1'b0, - const ref logic [DW-1:0] data [], - input logic use_strb = 0, - const ref logic [DW/8-1:0] strb [], - output axi_resp_e resp); + task axi_write(input logic [AW-1:0] addr, + input axi_burst_e burst = AXI_BURST_INCR, + input logic [2:0] size = $clog2(DW/8), + input logic [7:0] len = 0, + input logic [UW-1:0] user = UW'(0), + input logic [IW-1:0] id = IW'(0), + input logic lock = 1'b0, + input logic [DW-1:0] data [], + input logic use_strb = 0, + input logic [DW/8-1:0] strb [], + output axi_resp_e resp); while(!rst_n) @(posedge clk); do begin - awaddr = addr; - awburst = burst; - awsize = size; - awlen = len; - awuser = user; - awid = id; - awlock = lock; - awvalid = 1; + `TIME_ALGN + awaddr `EQ__ addr; + awburst `EQ__ burst; + awsize `EQ__ size; + awlen `EQ__ len; + awuser `EQ__ user; + awid `EQ__ id; + awlock `EQ__ lock; + awvalid `EQ__ 1; @(posedge clk); end while(!awready); + `TIME_ALGN + awaddr `EQ__ '0; + awburst `EQ__ AXI_BURST_FIXED; + awsize `EQ__ '0; + awlen `EQ__ '0; + awuser `EQ__ '0; + awid `EQ__ '0; + awlock `EQ__ '0; + awvalid `EQ__ '0; fork for (int beat=0; beat <= len; beat++) send_write_beat(beat == len, data[beat], use_strb ? strb[beat] : {DW/8{1'b1}}); @@ -277,4 +340,25 @@ interface axi_if #(parameter integer AW = 32, parameter integer DW = 32, paramet join endtask + task axi_write_single(input logic [AW-1:0] addr, + input logic [UW-1:0] user = UW'(0), + input logic [IW-1:0] id = IW'(0), + input logic lock = 1'b0, + input logic [DW-1:0] data, + output axi_resp_e resp); + automatic logic [DW/8-1:0] burst_strb[] = new[1]('{{DW/8{1'b1}}}); + automatic logic [DW -1:0] burst_data[] = new[1]('{data}); + axi_write(.addr(addr), + .user(user), + .id (id ), + .lock(lock), + .data(burst_data), + .use_strb(0), + .strb(burst_strb), + .resp(resp)); + endtask + + `undef EQ__ + `undef TIME_ALGN + endinterface diff --git a/src/axi/rtl/axi_sub_rd.sv b/src/axi/rtl/axi_sub_rd.sv index 4c5c4096a..bc23c4533 100644 --- a/src/axi/rtl/axi_sub_rd.sv +++ b/src/axi/rtl/axi_sub_rd.sv @@ -139,11 +139,11 @@ module axi_sub_rd import axi_pkg::*; #( end end - // TODO reset? - always_ff@(posedge clk/* or negedge rst_n*/) begin -// if (!rst_n) begin -// txn_ctx <= '{default:0}; -// end + always_ff@(posedge clk or negedge rst_n) begin + if (!rst_n) begin + txn_ctx <= '{default:0, burst:AXI_BURST_FIXED}; + txn_cnt <= '0; + end if (s_axi_if.arvalid && s_axi_if.arready) begin txn_ctx.addr <= s_axi_if.araddr; txn_ctx.burst <= axi_burst_e'(s_axi_if.arburst); @@ -164,9 +164,6 @@ module axi_sub_rd import axi_pkg::*; #( txn_ctx.lock <= txn_ctx.lock; txn_cnt <= |txn_cnt ? txn_cnt - 1 : txn_cnt; // Prevent underflow to 255 at end to reduce switching power. Extra logic cost worth it? end - else begin - txn_ctx <= txn_ctx; - end end // Only make the request to component if we have space in the pipeline to