-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #129 from zeroasiccorp/ali/axiumi
UMI to AXI4-Lite converters and testbenches
- Loading branch information
Showing
6 changed files
with
5,518 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,319 @@ | ||
/******************************************************************************* | ||
* Copyright 2023 Zero ASIC Corporation | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* ---- | ||
* | ||
* Documentation: | ||
* - AXI4-Lite to UMI converter | ||
* | ||
******************************************************************************/ | ||
|
||
`default_nettype wire | ||
|
||
module axilite2umi #( | ||
parameter CW = 32, // command width | ||
parameter AW = 64, // address width | ||
parameter DW = 64, // umi packet width | ||
parameter IDW = 16 // chip ID width | ||
) | ||
( | ||
input clk, | ||
input nreset, | ||
input [IDW-1:0] chipid, | ||
input [15:0] local_routing, | ||
|
||
// AXI4Lite Interface | ||
input [AW-1:0] axi_awaddr, | ||
input [2:0] axi_awprot, | ||
input axi_awvalid, | ||
output axi_awready, | ||
|
||
input [DW-1:0] axi_wdata, | ||
input [(DW/8)-1:0] axi_wstrb, | ||
input axi_wvalid, | ||
output axi_wready, | ||
|
||
output [1:0] axi_bresp, | ||
output axi_bvalid, | ||
input axi_bready, | ||
|
||
input [AW-1:0] axi_araddr, | ||
input [2:0] axi_arprot, | ||
input axi_arvalid, | ||
output axi_arready, | ||
|
||
output [DW-1:0] axi_rdata, | ||
output [1:0] axi_rresp, | ||
output axi_rvalid, | ||
input axi_rready, | ||
|
||
// Host port (per clink) | ||
output uhost_req_valid, | ||
output [CW-1:0] uhost_req_cmd, | ||
output [AW-1:0] uhost_req_dstaddr, | ||
output [AW-1:0] uhost_req_srcaddr, | ||
output [DW-1:0] uhost_req_data, | ||
input uhost_req_ready, | ||
|
||
input uhost_resp_valid, | ||
input [CW-1:0] uhost_resp_cmd, | ||
input [AW-1:0] uhost_resp_dstaddr, | ||
input [AW-1:0] uhost_resp_srcaddr, | ||
input [DW-1:0] uhost_resp_data, | ||
output uhost_resp_ready | ||
); | ||
|
||
`include "umi_messages.vh" | ||
|
||
localparam DWLOG = $clog2(DW/8); | ||
|
||
// Additional UMI signals | ||
wire [4:0] umi_req_cmd_opcode; | ||
wire [7:0] umi_req_cmd_len; | ||
wire [1:0] umi_req_cmd_prot; | ||
|
||
wire reset_done; | ||
|
||
la_drsync la_drsync_i ( | ||
.clk (clk), | ||
.nreset (nreset), | ||
.in (1'b1), | ||
.out (reset_done) | ||
); | ||
|
||
reg write_in_flight; | ||
reg read_in_flight; | ||
|
||
always @(posedge clk or negedge nreset) begin | ||
if (~nreset) | ||
write_in_flight <= 1'b0; | ||
else if (axi_awvalid & axi_awready) | ||
write_in_flight <= 1'b1; | ||
else if (axi_bvalid & axi_bready) | ||
write_in_flight <= 1'b0; | ||
end | ||
|
||
always @(posedge clk or negedge nreset) begin | ||
if (~nreset) | ||
read_in_flight <= 1'b0; | ||
else if (axi_arvalid & axi_arready) | ||
read_in_flight <= 1'b1; | ||
else if (axi_rvalid & axi_rready) | ||
read_in_flight <= 1'b0; | ||
end | ||
|
||
// Write Address | ||
reg [AW-1:0] axi_awaddr_r; | ||
reg [2:0] axi_awprot_r; | ||
reg axi_awvalid_r; | ||
|
||
always @(posedge clk or negedge nreset) begin | ||
if (~nreset) begin | ||
axi_awaddr_r <= 'b0; | ||
axi_awprot_r <= 'b0; | ||
end | ||
else if (axi_awvalid & axi_awready) begin | ||
axi_awaddr_r <= axi_awaddr; | ||
axi_awprot_r <= axi_awprot; | ||
end | ||
end | ||
|
||
always @(posedge clk or negedge nreset) begin | ||
if (~nreset) | ||
axi_awvalid_r <= 1'b0; | ||
else if (axi_awvalid & axi_awready) | ||
axi_awvalid_r <= 1'b1; | ||
else if (uhost_req_valid & uhost_req_ready & (umi_req_cmd_opcode == UMI_REQ_WRITE)) | ||
axi_awvalid_r <= 1'b0; | ||
end | ||
|
||
// Write data prep | ||
integer i; | ||
reg [DWLOG:0] axi_wstrb_ctr; | ||
reg [(DW/8)-1:0] axi_wstrb_cml_one; | ||
reg [DWLOG-1:0] axi_wdata_byte_shift; | ||
|
||
always @* begin | ||
axi_wstrb_ctr = {(DWLOG + 1){1'b0}}; | ||
for (i = 0; i < (DW/8); i = i + 1) begin | ||
axi_wstrb_ctr = axi_wstrb_ctr + {{(DWLOG){1'b0}}, axi_wstrb[i]}; | ||
end | ||
|
||
axi_wstrb_cml_one[0] = axi_wstrb[0]; | ||
for (i = 1; i < (DW/8); i = i + 1) begin | ||
axi_wstrb_cml_one[i] = axi_wstrb[i] | axi_wstrb_cml_one[i-1]; | ||
end | ||
|
||
axi_wdata_byte_shift = {(DWLOG){1'b0}}; | ||
for (i = 1; i < (DW/8); i = i + 1) begin | ||
if (axi_wstrb[i] & !axi_wstrb_cml_one[i-1]) | ||
axi_wdata_byte_shift = axi_wdata_byte_shift | i[DWLOG-1:0]; | ||
end | ||
end | ||
|
||
assign axi_awready = !(write_in_flight | read_in_flight) & reset_done; | ||
|
||
// Write data | ||
reg [DW-1:0] axi_wdata_r; | ||
reg [(DW/8)-1:0] axi_wstrb_r; | ||
reg [DWLOG:0] axi_wstrb_ctr_r; | ||
reg [AW-1:0] axi_addr_offset; | ||
reg axi_wvalid_r; | ||
|
||
always @(posedge clk or negedge nreset) begin | ||
if (~nreset) begin | ||
axi_wdata_r <= 'b0; | ||
axi_wstrb_r <= 'b0; | ||
axi_wstrb_ctr_r <= 'b0; | ||
axi_addr_offset <= 'b0; | ||
end | ||
else if (axi_wvalid & axi_wready) begin | ||
axi_wdata_r <= axi_wdata >> ({3'b000, axi_wdata_byte_shift} << 3); | ||
axi_wstrb_r <= axi_wstrb; | ||
axi_wstrb_ctr_r <= axi_wstrb_ctr; | ||
axi_addr_offset <= {{(AW-DWLOG){1'b0}}, axi_wdata_byte_shift}; | ||
end | ||
end | ||
|
||
always @(posedge clk or negedge nreset) begin | ||
if (~nreset) | ||
axi_wvalid_r <= 1'b0; | ||
else if (axi_wvalid & axi_wready) | ||
axi_wvalid_r <= 1'b1; | ||
else if (uhost_req_valid & uhost_req_ready & (umi_req_cmd_opcode == UMI_REQ_WRITE)) | ||
axi_wvalid_r <= 1'b0; | ||
end | ||
|
||
assign axi_wready = axi_awvalid_r & !axi_wvalid_r & reset_done; | ||
|
||
// Read address | ||
reg [AW-1:0] axi_araddr_r; | ||
reg [2:0] axi_arprot_r; | ||
reg axi_arvalid_r; | ||
|
||
always @(posedge clk or negedge nreset) begin | ||
if (~nreset) begin | ||
axi_araddr_r <= 'b0; | ||
axi_arprot_r <= 'b0; | ||
end | ||
else if (axi_arvalid & axi_arready) begin | ||
axi_araddr_r <= axi_araddr; | ||
axi_arprot_r <= axi_arprot; | ||
end | ||
end | ||
|
||
always @(posedge clk or negedge nreset) begin | ||
if (~nreset) | ||
axi_arvalid_r <= 1'b0; | ||
else if (axi_arvalid & axi_arready) | ||
axi_arvalid_r <= 1'b1; | ||
else if (uhost_req_valid & uhost_req_ready & (umi_req_cmd_opcode == UMI_REQ_READ)) | ||
axi_arvalid_r <= 1'b0; | ||
end | ||
|
||
assign axi_arready = !(write_in_flight | read_in_flight) & reset_done; | ||
|
||
// UMI request | ||
|
||
assign umi_req_cmd_opcode = write_in_flight ? | ||
UMI_REQ_WRITE : | ||
UMI_REQ_READ; | ||
assign umi_req_cmd_len = write_in_flight ? | ||
(axi_wstrb_ctr_r-1) : | ||
((DW/8)-1); | ||
assign umi_req_cmd_prot = write_in_flight ? | ||
axi_awprot_r[1:0] : | ||
axi_arprot_r[1:0]; | ||
|
||
umi_pack #( | ||
.CW (CW) | ||
) umi_req_pack ( | ||
.cmd_opcode (umi_req_cmd_opcode), | ||
.cmd_size (3'b0), | ||
.cmd_len (umi_req_cmd_len), | ||
.cmd_atype (8'b0), | ||
.cmd_prot (umi_req_cmd_prot), | ||
.cmd_qos (4'b0), | ||
.cmd_eom (1'b1), | ||
.cmd_eof (1'b0), | ||
.cmd_user (2'b0), | ||
.cmd_err (2'b00), | ||
.cmd_ex (1'b0), | ||
.cmd_hostid (5'b0), | ||
.cmd_user_extended (24'b0), | ||
|
||
.packet_cmd (uhost_req_cmd) | ||
); | ||
|
||
wire [23:0] chip_address = {{(24-IDW){1'b0}}, chipid}; | ||
|
||
assign uhost_req_dstaddr = write_in_flight ? | ||
(axi_awaddr_r + axi_addr_offset) : | ||
axi_araddr_r; | ||
assign uhost_req_srcaddr = {chip_address, local_routing, 24'b0}; | ||
assign uhost_req_data = axi_wdata_r; | ||
assign uhost_req_valid = write_in_flight ? | ||
(axi_awvalid_r & axi_wvalid_r & reset_done) : | ||
(axi_arvalid_r & reset_done); | ||
|
||
// UMI response | ||
wire [4:0] umi_resp_cmd_opcode; | ||
wire [2:0] umi_resp_cmd_size; | ||
wire [7:0] umi_resp_cmd_len; | ||
wire umi_resp_cmd_eom; | ||
wire [1:0] umi_resp_cmd_err; | ||
|
||
umi_unpack #( | ||
.CW (CW) | ||
) axilite2umi_resp_unpack ( | ||
// Input CMD | ||
.packet_cmd (uhost_resp_cmd), | ||
|
||
// Output Fields | ||
.cmd_opcode (umi_resp_cmd_opcode), | ||
.cmd_size (umi_resp_cmd_size), | ||
.cmd_len (umi_resp_cmd_len), | ||
.cmd_atype (), | ||
.cmd_qos (), | ||
.cmd_prot (), | ||
.cmd_eom (umi_resp_cmd_eom), | ||
.cmd_eof (), | ||
.cmd_ex (), | ||
.cmd_user (), | ||
.cmd_user_extended (), | ||
.cmd_err (umi_resp_cmd_err), | ||
.cmd_hostid () | ||
); | ||
|
||
assign uhost_resp_ready = write_in_flight ? | ||
(axi_bready & reset_done) : | ||
(axi_rready & reset_done); | ||
|
||
// Read response | ||
assign axi_rdata = uhost_resp_data; | ||
assign axi_rresp = umi_resp_cmd_err; | ||
assign axi_rvalid = read_in_flight & | ||
uhost_resp_valid & | ||
(umi_resp_cmd_opcode == UMI_RESP_READ) & | ||
reset_done; | ||
|
||
// Write response | ||
assign axi_bresp = umi_resp_cmd_err; | ||
assign axi_bvalid = write_in_flight & | ||
uhost_resp_valid & | ||
(umi_resp_cmd_opcode == UMI_RESP_WRITE) & | ||
reset_done; | ||
|
||
endmodule |
Oops, something went wrong.