Skip to content
Open
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions fpga_diff/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ NO_DIFF ?= 0
XDMA_LINK_WIDTH ?= X4
VIVADO_JOBS ?=
export XDMA_LINK_WIDTH VIVADO_JOBS NO_DIFF
DIFFTEST_HOSTIF ?= XDMA
ifeq ($(filter XDMA GBUS,$(DIFFTEST_HOSTIF)),)
$(error DIFFTEST_HOSTIF must be XDMA or GBUS, got $(DIFFTEST_HOSTIF))
endif
export DIFFTEST_HOSTIF
FPGA_RUNTIME ?=
REMOTE_ENV ?= source ~/.bash_profile &&
BIND_UART ?= 1
Expand Down
4 changes: 4 additions & 0 deletions fpga_diff/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Core RTL to FPGA Steps
======================

For UVHS GBus builds, see [the SRAM C2H interface and build flow](uvhs/README.md).
`DIFFTEST_HOSTIF=GBUS` keeps DiffTest output in the GBS1 on-chip SRAM window.
Workload H2C enters through the existing CPU-subsystem DMA AXI interface.

1. modify Makefile, assign CORE_DIR

2. make vivado CPU=XXX
Expand Down
798 changes: 692 additions & 106 deletions fpga_diff/src/rtl/common/core_def_xdma.sv

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions fpga_diff/src/rtl/common/uvhs_async_fifo.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
`timescale 1ns/1ps

// Generic dual-clock ready/valid FIFO. Payload and pointer CDC use the same
// Gray-pointer structure as the proven GBus AXI-stream FIFO.
module uvhs_async_fifo #(
parameter integer WIDTH = 32,
parameter integer ADDR_WIDTH = 3
) (
input wire s_clk,
input wire s_rstn,
input wire [WIDTH-1:0] s_data,
input wire s_valid,
output wire s_ready,

input wire m_clk,
input wire m_rstn,
output wire [WIDTH-1:0] m_data,
output wire m_valid,
input wire m_ready
);
localparam integer PTR_WIDTH = ADDR_WIDTH + 1;
localparam integer DEPTH = 1 << ADDR_WIDTH;

(* ram_style = "distributed" *) reg [WIDTH-1:0] mem [0:DEPTH-1];
reg [PTR_WIDTH-1:0] wbin, wgray;
reg [PTR_WIDTH-1:0] rbin, rgray;
(* ASYNC_REG = "TRUE", SHREG_EXTRACT = "NO" *)
reg [PTR_WIDTH-1:0] rgray_wsync1, rgray_wsync2;
(* ASYNC_REG = "TRUE", SHREG_EXTRACT = "NO" *)
reg [PTR_WIDTH-1:0] wgray_rsync1, wgray_rsync2;
reg [WIDTH-1:0] out_data;
reg out_valid;

wire [PTR_WIDTH-1:0] wbin_next = wbin + 1'b1;
wire [PTR_WIDTH-1:0] wgray_next = (wbin_next >> 1) ^ wbin_next;
wire [PTR_WIDTH-1:0] full_compare = {
~rgray_wsync2[PTR_WIDTH-1:PTR_WIDTH-2],
rgray_wsync2[PTR_WIDTH-3:0]
};
wire full = wgray_next == full_compare;
wire not_empty = rgray != wgray_rsync2;

assign s_ready = s_rstn && !full;
assign m_data = out_data;
assign m_valid = out_valid;

always @(posedge s_clk or negedge s_rstn) begin
if (!s_rstn) begin
wbin <= 0;
wgray <= 0;
rgray_wsync1 <= 0;
rgray_wsync2 <= 0;
end else begin
rgray_wsync1 <= rgray;
rgray_wsync2 <= rgray_wsync1;
if (s_valid && s_ready) begin
mem[wbin[ADDR_WIDTH-1:0]] <= s_data;
wbin <= wbin_next;
wgray <= wgray_next;
end
end
end

always @(posedge m_clk or negedge m_rstn) begin
if (!m_rstn) begin
rbin <= 0;
rgray <= 0;
wgray_rsync1 <= 0;
wgray_rsync2 <= 0;
out_data <= 0;
out_valid <= 1'b0;
end else begin
wgray_rsync1 <= wgray;
wgray_rsync2 <= wgray_rsync1;
if (!out_valid || m_ready) begin
if (not_empty) begin
out_data <= mem[rbin[ADDR_WIDTH-1:0]];
rbin <= rbin + 1'b1;
rgray <= ((rbin + 1'b1) >> 1) ^ (rbin + 1'b1);
out_valid <= 1'b1;
end else begin
out_valid <= 1'b0;
end
end
end
end
endmodule
21 changes: 21 additions & 0 deletions fpga_diff/src/rtl/common/uvhs_async_status_sync.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module uvhs_async_status_sync #(
parameter INIT = 1'b1
) (
input wire clk,
input wire rstn,
input wire async_in,
output wire sync_out
);

(* ASYNC_REG = "TRUE", SHREG_EXTRACT = "NO" *) reg [1:0] sync_reg;

always @(posedge clk or negedge rstn) begin
if (!rstn)
sync_reg <= {2{INIT}};
else
sync_reg <= {sync_reg[0], async_in};
end

assign sync_out = sync_reg[1];

endmodule
135 changes: 135 additions & 0 deletions fpga_diff/src/rtl/common/uvhs_axi3_to_axi4_adapter.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
`timescale 1ns/1ps

// Protocol shim for the U2.2 uvw_general_bus AXI3 user port and the existing
// CPU-subsystem DMA AXI4 interface. The general-bus IP emits at most 16-beat
// AXI3 bursts; AXI4 accepts the same burst semantics with widened metadata.
module uvhs_axi3_to_axi4_adapter #(
parameter integer ADDR_WIDTH = 34,
parameter integer ID_WIDTH = 14,
parameter integer AXI3_ID_WIDTH = 8,
parameter integer DATA_WIDTH = 256
) (
input wire clk,
input wire rstn,
input wire [AXI3_ID_WIDTH-1:0] s_awid,
input wire [ADDR_WIDTH-1:0] s_awaddr,
input wire [3:0] s_awlen,
input wire [2:0] s_awsize,
input wire [1:0] s_awburst,
input wire [1:0] s_awlock,
input wire [3:0] s_awcache,
input wire [2:0] s_awprot,
input wire [3:0] s_awqos,
input wire s_awvalid,
output wire s_awready,
input wire [AXI3_ID_WIDTH-1:0] s_wid,
input wire [DATA_WIDTH-1:0] s_wdata,
input wire [DATA_WIDTH/8-1:0] s_wstrb,
input wire s_wlast,
input wire s_wvalid,
output wire s_wready,
output wire [AXI3_ID_WIDTH-1:0] s_bid,
output wire [1:0] s_bresp,
output wire s_bvalid,
input wire s_bready,
input wire [AXI3_ID_WIDTH-1:0] s_arid,
input wire [ADDR_WIDTH-1:0] s_araddr,
input wire [3:0] s_arlen,
input wire [2:0] s_arsize,
input wire [1:0] s_arburst,
input wire [1:0] s_arlock,
input wire [3:0] s_arcache,
input wire [2:0] s_arprot,
input wire [3:0] s_arqos,
input wire s_arvalid,
output wire s_arready,
output wire [AXI3_ID_WIDTH-1:0] s_rid,
output wire [DATA_WIDTH-1:0] s_rdata,
output wire [1:0] s_rresp,
output wire s_rlast,
output wire s_rvalid,
input wire s_rready,
output wire [ID_WIDTH-1:0] m_awid,
output wire [ADDR_WIDTH-1:0] m_awaddr,
output wire [7:0] m_awlen,
output wire [2:0] m_awsize,
output wire [1:0] m_awburst,
output wire m_awlock,
output wire [3:0] m_awcache,
output wire [2:0] m_awprot,
output wire [3:0] m_awqos,
output wire [3:0] m_awregion,
output wire m_awvalid,
input wire m_awready,
output wire [DATA_WIDTH-1:0] m_wdata,
output wire [DATA_WIDTH/8-1:0] m_wstrb,
output wire m_wlast,
output wire m_wvalid,
input wire m_wready,
input wire [ID_WIDTH-1:0] m_bid,
input wire [1:0] m_bresp,
input wire m_bvalid,
output wire m_bready,
output wire [ID_WIDTH-1:0] m_arid,
output wire [ADDR_WIDTH-1:0] m_araddr,
output wire [7:0] m_arlen,
output wire [2:0] m_arsize,
output wire [1:0] m_arburst,
output wire m_arlock,
output wire [3:0] m_arcache,
output wire [2:0] m_arprot,
output wire [3:0] m_arqos,
output wire [3:0] m_arregion,
output wire m_arvalid,
input wire m_arready,
input wire [ID_WIDTH-1:0] m_rid,
input wire [DATA_WIDTH-1:0] m_rdata,
input wire [1:0] m_rresp,
input wire m_rlast,
input wire m_rvalid,
output wire m_rready
);
assign m_awid = {{(ID_WIDTH-AXI3_ID_WIDTH){1'b0}}, s_awid};
assign m_awaddr = s_awaddr;
assign m_awlen = {4'b0, s_awlen};
assign m_awsize = s_awsize;
assign m_awburst = s_awburst;
assign m_awlock = s_awlock[0];
assign m_awcache = s_awcache;
assign m_awprot = s_awprot;
assign m_awqos = s_awqos;
assign m_awregion = 4'b0;
assign m_awvalid = s_awvalid;
assign s_awready = m_awready;

assign m_wdata = s_wdata;
assign m_wstrb = s_wstrb;
assign m_wlast = s_wlast;
assign m_wvalid = s_wvalid;
assign s_wready = m_wready;
assign s_bid = m_bid[AXI3_ID_WIDTH-1:0];
assign s_bresp = m_bresp;
assign s_bvalid = m_bvalid;
assign m_bready = s_bready;

assign m_arid = {{(ID_WIDTH-AXI3_ID_WIDTH){1'b0}}, s_arid};
assign m_araddr = s_araddr;
assign m_arlen = {4'b0, s_arlen};
assign m_arsize = s_arsize;
assign m_arburst = s_arburst;
assign m_arlock = s_arlock[0];
assign m_arcache = s_arcache;
assign m_arprot = s_arprot;
assign m_arqos = s_arqos;
assign m_arregion = 4'b0;
assign m_arvalid = s_arvalid;
assign s_arready = m_arready;
assign s_rid = m_rid[AXI3_ID_WIDTH-1:0];
assign s_rdata = m_rdata;
assign s_rresp = m_rresp;
assign s_rlast = m_rlast;
assign s_rvalid = m_rvalid;
assign m_rready = s_rready;

wire _unused = &{1'b0, clk, rstn, s_wid};
endmodule
94 changes: 94 additions & 0 deletions fpga_diff/src/rtl/common/uvhs_axi_async_bridge.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
`timescale 1ns/1ps

// Full AXI4 clock-domain bridge for the GBus build. Each AXI channel crosses
// through an independent ready/valid FIFO; ordering within every channel is
// preserved and backpressure may stop either clock without losing a transfer.
module uvhs_axi_async_bridge #(
parameter integer ADDR_WIDTH = 34,
parameter integer ID_WIDTH = 14,
parameter integer DATA_WIDTH = 256,
parameter integer FIFO_ADDR_WIDTH = 3
) (
input wire s_clk, input wire s_rstn,
input wire [ID_WIDTH-1:0] s_awid, input wire [ADDR_WIDTH-1:0] s_awaddr,
input wire [7:0] s_awlen, input wire [2:0] s_awsize, input wire [1:0] s_awburst,
input wire s_awlock, input wire [3:0] s_awcache, input wire [2:0] s_awprot,
input wire [3:0] s_awqos, input wire [3:0] s_awregion, input wire s_awvalid,
output wire s_awready, input wire [DATA_WIDTH-1:0] s_wdata,
input wire [DATA_WIDTH/8-1:0] s_wstrb, input wire s_wlast, input wire s_wvalid,
output wire s_wready, output wire [ID_WIDTH-1:0] s_bid, output wire [1:0] s_bresp,
output wire s_bvalid, input wire s_bready, input wire [ID_WIDTH-1:0] s_arid,
input wire [ADDR_WIDTH-1:0] s_araddr, input wire [7:0] s_arlen,
input wire [2:0] s_arsize, input wire [1:0] s_arburst, input wire s_arlock,
input wire [3:0] s_arcache, input wire [2:0] s_arprot, input wire [3:0] s_arqos,
input wire [3:0] s_arregion, input wire s_arvalid, output wire s_arready,
output wire [ID_WIDTH-1:0] s_rid, output wire [DATA_WIDTH-1:0] s_rdata,
output wire [1:0] s_rresp, output wire s_rlast, output wire s_rvalid, input wire s_rready,

input wire m_clk, input wire m_rstn,
output wire [ID_WIDTH-1:0] m_awid, output wire [ADDR_WIDTH-1:0] m_awaddr,
output wire [7:0] m_awlen, output wire [2:0] m_awsize, output wire [1:0] m_awburst,
output wire m_awlock, output wire [3:0] m_awcache, output wire [2:0] m_awprot,
output wire [3:0] m_awqos, output wire [3:0] m_awregion, output wire m_awvalid,
input wire m_awready, output wire [DATA_WIDTH-1:0] m_wdata,
output wire [DATA_WIDTH/8-1:0] m_wstrb, output wire m_wlast, output wire m_wvalid,
input wire m_wready, input wire [ID_WIDTH-1:0] m_bid, input wire [1:0] m_bresp,
input wire m_bvalid, output wire m_bready, output wire [ID_WIDTH-1:0] m_arid,
output wire [ADDR_WIDTH-1:0] m_araddr, output wire [7:0] m_arlen,
output wire [2:0] m_arsize, output wire [1:0] m_arburst, output wire m_arlock,
output wire [3:0] m_arcache, output wire [2:0] m_arprot, output wire [3:0] m_arqos,
output wire [3:0] m_arregion, output wire m_arvalid, input wire m_arready,
input wire [ID_WIDTH-1:0] m_rid, input wire [DATA_WIDTH-1:0] m_rdata,
input wire [1:0] m_rresp, input wire m_rlast, input wire m_rvalid, output wire m_rready
);
localparam integer STRB_WIDTH = DATA_WIDTH / 8;
localparam integer AW_WIDTH = ID_WIDTH + ADDR_WIDTH + 8 + 3 + 2 + 1 + 4 + 3 + 4 + 4;
localparam integer W_WIDTH = DATA_WIDTH + STRB_WIDTH + 1;
localparam integer B_WIDTH = ID_WIDTH + 2;
localparam integer AR_WIDTH = AW_WIDTH;
localparam integer R_WIDTH = ID_WIDTH + DATA_WIDTH + 2 + 1;

wire [AW_WIDTH-1:0] s_aw_payload = {s_awid, s_awaddr, s_awlen, s_awsize,
s_awburst, s_awlock, s_awcache, s_awprot, s_awqos, s_awregion};
wire [AW_WIDTH-1:0] m_aw_payload;
assign {m_awid, m_awaddr, m_awlen, m_awsize, m_awburst, m_awlock,
m_awcache, m_awprot, m_awqos, m_awregion} = m_aw_payload;
uvhs_async_fifo #(.WIDTH(AW_WIDTH), .ADDR_WIDTH(FIFO_ADDR_WIDTH)) aw_fifo (
.s_clk(s_clk), .s_rstn(s_rstn), .s_data(s_aw_payload), .s_valid(s_awvalid),
.s_ready(s_awready), .m_clk(m_clk), .m_rstn(m_rstn), .m_data(m_aw_payload),
.m_valid(m_awvalid), .m_ready(m_awready));

wire [W_WIDTH-1:0] s_w_payload = {s_wdata, s_wstrb, s_wlast};
wire [W_WIDTH-1:0] m_w_payload;
assign {m_wdata, m_wstrb, m_wlast} = m_w_payload;
uvhs_async_fifo #(.WIDTH(W_WIDTH), .ADDR_WIDTH(FIFO_ADDR_WIDTH)) w_fifo (
.s_clk(s_clk), .s_rstn(s_rstn), .s_data(s_w_payload), .s_valid(s_wvalid),
.s_ready(s_wready), .m_clk(m_clk), .m_rstn(m_rstn), .m_data(m_w_payload),
.m_valid(m_wvalid), .m_ready(m_wready));

wire [B_WIDTH-1:0] m_b_payload = {m_bid, m_bresp};
wire [B_WIDTH-1:0] s_b_payload;
assign {s_bid, s_bresp} = s_b_payload;
uvhs_async_fifo #(.WIDTH(B_WIDTH), .ADDR_WIDTH(FIFO_ADDR_WIDTH)) b_fifo (
.s_clk(m_clk), .s_rstn(m_rstn), .s_data(m_b_payload), .s_valid(m_bvalid),
.s_ready(m_bready), .m_clk(s_clk), .m_rstn(s_rstn), .m_data(s_b_payload),
.m_valid(s_bvalid), .m_ready(s_bready));

wire [AR_WIDTH-1:0] s_ar_payload = {s_arid, s_araddr, s_arlen, s_arsize,
s_arburst, s_arlock, s_arcache, s_arprot, s_arqos, s_arregion};
wire [AR_WIDTH-1:0] m_ar_payload;
assign {m_arid, m_araddr, m_arlen, m_arsize, m_arburst, m_arlock,
m_arcache, m_arprot, m_arqos, m_arregion} = m_ar_payload;
uvhs_async_fifo #(.WIDTH(AR_WIDTH), .ADDR_WIDTH(FIFO_ADDR_WIDTH)) ar_fifo (
.s_clk(s_clk), .s_rstn(s_rstn), .s_data(s_ar_payload), .s_valid(s_arvalid),
.s_ready(s_arready), .m_clk(m_clk), .m_rstn(m_rstn), .m_data(m_ar_payload),
.m_valid(m_arvalid), .m_ready(m_arready));

wire [R_WIDTH-1:0] m_r_payload = {m_rid, m_rdata, m_rresp, m_rlast};
wire [R_WIDTH-1:0] s_r_payload;
assign {s_rid, s_rdata, s_rresp, s_rlast} = s_r_payload;
uvhs_async_fifo #(.WIDTH(R_WIDTH), .ADDR_WIDTH(FIFO_ADDR_WIDTH)) r_fifo (
.s_clk(m_clk), .s_rstn(m_rstn), .s_data(m_r_payload), .s_valid(m_rvalid),
.s_ready(m_rready), .m_clk(s_clk), .m_rstn(s_rstn), .m_data(s_r_payload),
.m_valid(s_rvalid), .m_ready(s_rready));
endmodule
Loading