Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 74 additions & 38 deletions src/obi_atop_resolver.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ module obi_atop_resolver
// Word width of the widest RISC-V processor that can issue requests to this module.
// 32 for RV32; 64 for RV64, where both 32-bit (.W suffix) and 64-bit (.D suffix) AMOs are
// supported if `aw_strb` is set correctly.
parameter int unsigned RiscvWordWidth = 32
parameter int unsigned RiscvWordWidth = 32,
/// Number of outstanding transactions. Only relevant if downstream interface is cut
parameter int unsigned NumTxns = 1
) (
input logic clk_i,
input logic rst_ni,
Expand Down Expand Up @@ -70,8 +72,10 @@ module obi_atop_resolver
amo_state_e state_q, state_d;

logic load_amo;
obi_atop_e amo_op_q;
obi_atop_e amo_op_d, amo_op_q;
logic amo_wb;
logic rsp_happening;
logic amo_available, amo_last;
logic [SbrPortObiCfg.AddrWidth-1:0] addr_q;

logic [ SbrPortObiCfg.IdWidth-1:0] aid_q;
Expand Down Expand Up @@ -99,13 +103,17 @@ module obi_atop_resolver
);

// Store the metadata at handshake
spill_register #(
.T (logic [SbrPortObiCfg.IdWidth-1:0]),
.Bypass(1'b0)
stream_fifo #(
.T (logic [SbrPortObiCfg.IdWidth-1:0]),
.DEPTH (NumTxns),
.FALL_THROUGH (1'b0)
) i_metadata_register (
.clk_i,
.rst_ni,
.valid_i(sbr_port_req_i.req && sbr_port_rsp_o.gnt),
.flush_i ('0),
.testmode_i ('0),
.usage_o (),
.valid_i (sbr_port_req_i.req && sbr_port_rsp_o.gnt),
.ready_o(meta_ready),
.data_i (sbr_port_req_i.a.aid),
.valid_o(meta_valid),
Expand All @@ -117,7 +125,7 @@ module obi_atop_resolver
logic rdata_full, rdata_empty;
logic rdata_usage;

assign rdata_ready = !rdata_usage && !rdata_full;
assign rdata_ready = !rdata_full;
assign rdata_valid = !rdata_empty;

logic sc_successful_or_lr_d, sc_successful_or_lr_q;
Expand Down Expand Up @@ -163,11 +171,11 @@ module obi_atop_resolver
.flush_i(1'b0),
.full_o (rdata_full),
.empty_o(rdata_empty),
.usage_o(rdata_usage),
.usage_o( ),
.data_i (out_buf_fifo_in),
.push_i (~last_amo_wb & mgr_port_rsp_i.rvalid),
.push_i (~last_amo_wb & rsp_happening),
.data_o (out_buf_fifo_out),
.pop_i (pop_resp & ~rdata_empty)
.pop_i (pop_resp)
);

// In case of a SC we must forward SC result from the cycle earlier.
Expand All @@ -177,7 +185,7 @@ module obi_atop_resolver

// Ready to output data if both meta and read data
// are available (the read data will always be last)
assign sbr_port_rsp_o.rvalid = meta_valid & rdata_valid;
assign sbr_port_rsp_o.rvalid = meta_valid & rdata_valid & ~amo_wb;
// Only pop the data from the registers once both registers are ready
if (SbrPortObiCfg.UseRReady) begin : gen_pop_rready
assign pop_resp = sbr_port_rsp_o.rvalid & sbr_port_req_i.rready;
Expand All @@ -186,7 +194,7 @@ module obi_atop_resolver
end

// Buffer amo_wb signal to ensure wb rdata is not used
`FFL(last_amo_wb, amo_wb, mgr_port_req_o.req, 1'b0, clk_i, rst_ni);
`FF(last_amo_wb, amo_wb, 1'b0, clk_i, rst_ni);

// ----------------
// LR/SC
Expand Down Expand Up @@ -332,10 +340,16 @@ module obi_atop_resolver
assign a_optional = '0;
end

if (SbrPortObiCfg.UseRReady) begin : gen_rsp_happening
assign rsp_happening = mgr_port_rsp_i.rvalid & mgr_port_req_o.rready;
end else begin : gen_rsp_norready
assign rsp_happening = mgr_port_rsp_i.rvalid;
end

always_comb begin
// feed-through
sbr_port_rsp_o.gnt = rdata_ready & mgr_port_rsp_i.gnt;
mgr_port_req_o.req = sbr_port_req_i.req & rdata_ready;
sbr_port_rsp_o.gnt = rdata_ready & mgr_port_rsp_i.gnt & amo_available;
mgr_port_req_o.req = sbr_port_req_i.req & rdata_ready & amo_available;
mgr_port_req_o.a.addr = sbr_port_req_i.a.addr;
mgr_port_req_o.a.we = obi_atop_e'(sbr_port_req_i.a.a_optional.atop) != ATOPSC ?
sbr_port_req_i.a.we : sc_successful_or_lr_d;
Expand All @@ -346,7 +360,8 @@ module obi_atop_resolver

state_d = state_q;
load_amo = 1'b0;
amo_wb = 1'b0;
amo_wb = last_amo_wb & ~rsp_happening;
amo_op_d = amo_op_q;

unique case (state_q)
Idle: begin
Expand All @@ -355,39 +370,45 @@ module obi_atop_resolver
!((obi_atop_e'(sbr_port_req_i.a.a_optional.atop) inside {ATOPLR, ATOPSC}) ||
!sbr_port_req_i.a.a_optional.atop[5])) begin
load_amo = 1'b1;
amo_op_d = obi_atop_e'(sbr_port_req_i.a.a_optional.atop);
state_d = DoAMO;
if (obi_atop_e'(sbr_port_req_i.a.a_optional.atop) inside {AMOSWAP, AMOADD, AMOXOR,
AMOAND, AMOOR, AMOMIN, AMOMAX,
AMOMINU, AMOMAXU}) begin
mgr_port_req_o.a.we = 1'b0;
end
end

end
// Claim the memory interface
DoAMO, WriteBackAMO: begin
sbr_port_rsp_o.gnt = 1'b0;
if (mgr_port_rsp_i.gnt) begin
state_d = (RegisterAmo && state_q != WriteBackAMO) ? WriteBackAMO : Idle;
end
// Commit AMO
amo_wb = 1'b1;
mgr_port_req_o.req = 1'b1;
mgr_port_req_o.a.we = 1'b1;
mgr_port_req_o.a.addr = addr_q;
mgr_port_req_o.a.aid = aid_q;
mgr_port_req_o.a.be = '0;
// serve from register if we cut the path
if (RegisterAmo) begin
mgr_port_req_o.a.wdata = amo_result_q;
mgr_port_req_o.a.be = {RiscvWordWidth/8{1'b1}} <<
(amo_operand_addr_q * RiscvWordWidth/8);
end else begin
mgr_port_req_o.a.wdata = amo_result;
mgr_port_req_o.a.be = {RiscvWordWidth/8{1'b1}} <<
(amo_operand_addr * RiscvWordWidth/8);
mgr_port_req_o.req = 1'b0;
if (amo_last && rsp_happening) begin
if (mgr_port_rsp_i.gnt) begin
state_d = (RegisterAmo && state_q != WriteBackAMO) ? WriteBackAMO : Idle;
end
// Commit AMO
amo_op_d = ATOPNONE;
amo_wb = 1'b1;
mgr_port_req_o.req = 1'b1;
mgr_port_req_o.a.we = 1'b1;
mgr_port_req_o.a.addr = addr_q;
mgr_port_req_o.a.aid = aid_q;
mgr_port_req_o.a.be = '0;
// serve from register if we cut the path
if (RegisterAmo) begin
mgr_port_req_o.req = (state_q == WriteBackAMO);
mgr_port_req_o.a.wdata = amo_result_q;
mgr_port_req_o.a.be = {RiscvWordWidth/8{1'b1}} <<
(amo_operand_addr_q * RiscvWordWidth/8);
end else begin
mgr_port_req_o.a.wdata = amo_result;
mgr_port_req_o.a.be = {RiscvWordWidth/8{1'b1}} <<
(amo_operand_addr * RiscvWordWidth/8);
end
end
end
default: ;
default:;
endcase
end

Expand All @@ -399,6 +420,20 @@ module obi_atop_resolver
assign amo_operand_addr_q = '0;
end

credit_counter #(
.NumCredits (NumTxns)
) i_credit_counter (
.clk_i,
.rst_ni,
.credit_o (),
.credit_give_i(rsp_happening),
.credit_take_i(mgr_port_req_o.req & mgr_port_rsp_i.gnt),
.credit_init_i('0),
.credit_left_o(amo_available),
.credit_crit_o(amo_last),
.credit_full_o()
);

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
state_q <= Idle;
Expand All @@ -409,14 +444,15 @@ module obi_atop_resolver
aid_q <= '0;
end else begin
state_q <= state_d;
amo_op_q <= amo_op_d;
if (load_amo) begin
amo_op_q <= obi_atop_e'(sbr_port_req_i.a.a_optional.atop);
// amo_op_q <= obi_atop_e'(sbr_port_req_i.a.a_optional.atop);
addr_q <= sbr_port_req_i.a.addr;
be_q <= sbr_port_req_i.a.be;
aid_q <= sbr_port_req_i.a.aid;
amo_operand_b_q <= sbr_port_req_i.a.wdata;
end else begin
amo_op_q <= ATOPNONE;
// amo_op_q <= ATOPNONE;
end
end
end
Expand Down