Skip to content

Commit

Permalink
Fixups to get sims working VCS + Verilator
Browse files Browse the repository at this point in the history
  • Loading branch information
calebofearth committed Jul 25, 2024
1 parent 1ca975a commit 4536941
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 72 deletions.
212 changes: 148 additions & 64 deletions src/axi/rtl/axi_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -205,76 +215,150 @@ 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;
resp[beat] = beat_resp;
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}});
get_write_resp(resp);
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
13 changes: 5 additions & 8 deletions src/axi/rtl/axi_sub_rd.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down

0 comments on commit 4536941

Please sign in to comment.