Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

Support co-simulating AXI MM slave memory #62

Draft
wants to merge 4 commits into
base: dev
Choose a base branch
from
Draft
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
855 changes: 855 additions & 0 deletions src/finn/data/verilog/lookup/Lookup_0.v

Large diffs are not rendered by default.

Large diffs are not rendered by default.

203 changes: 203 additions & 0 deletions src/finn/data/verilog/lookup/Lookup_0_control_s_axi.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
// ==============================================================
// Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2021.2 (64-bit)
// Copyright 1986-2021 Xilinx, Inc. All Rights Reserved.
// ==============================================================
`timescale 1ns/1ps
module Lookup_0_control_s_axi
#(parameter
C_S_AXI_ADDR_WIDTH = 5,
C_S_AXI_DATA_WIDTH = 32
)(
input wire ACLK,
input wire ARESET,
input wire ACLK_EN,
input wire [C_S_AXI_ADDR_WIDTH-1:0] AWADDR,
input wire AWVALID,
output wire AWREADY,
input wire [C_S_AXI_DATA_WIDTH-1:0] WDATA,
input wire [C_S_AXI_DATA_WIDTH/8-1:0] WSTRB,
input wire WVALID,
output wire WREADY,
output wire [1:0] BRESP,
output wire BVALID,
input wire BREADY,
input wire [C_S_AXI_ADDR_WIDTH-1:0] ARADDR,
input wire ARVALID,
output wire ARREADY,
output wire [C_S_AXI_DATA_WIDTH-1:0] RDATA,
output wire [1:0] RRESP,
output wire RVALID,
input wire RREADY,
output wire [63:0] mem,
input wire [0:0] ap_local_deadlock
);
//------------------------Address Info-------------------
// 0x00 : reserved
// 0x04 : reserved
// 0x08 : reserved
// 0x0c : reserved
// 0x10 : Data signal of mem
// bit 31~0 - mem[31:0] (Read/Write)
// 0x14 : Data signal of mem
// bit 31~0 - mem[63:32] (Read/Write)
// 0x18 : reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)

//------------------------Parameter----------------------
localparam
ADDR_MEM_DATA_0 = 5'h10,
ADDR_MEM_DATA_1 = 5'h14,
ADDR_MEM_CTRL = 5'h18,
WRIDLE = 2'd0,
WRDATA = 2'd1,
WRRESP = 2'd2,
WRRESET = 2'd3,
RDIDLE = 2'd0,
RDDATA = 2'd1,
RDRESET = 2'd2,
ADDR_BITS = 5;

//------------------------Local signal-------------------
reg [1:0] wstate = WRRESET;
reg [1:0] wnext;
reg [ADDR_BITS-1:0] waddr;
wire [C_S_AXI_DATA_WIDTH-1:0] wmask;
wire aw_hs;
wire w_hs;
reg [1:0] rstate = RDRESET;
reg [1:0] rnext;
reg [C_S_AXI_DATA_WIDTH-1:0] rdata;
wire ar_hs;
wire [ADDR_BITS-1:0] raddr;
// internal registers
reg [63:0] int_mem = 'b0;

//------------------------Instantiation------------------


//------------------------AXI write fsm------------------
assign AWREADY = (wstate == WRIDLE);
assign WREADY = (wstate == WRDATA);
assign BRESP = 2'b00; // OKAY
assign BVALID = (wstate == WRRESP);
assign wmask = { {8{WSTRB[3]}}, {8{WSTRB[2]}}, {8{WSTRB[1]}}, {8{WSTRB[0]}} };
assign aw_hs = AWVALID & AWREADY;
assign w_hs = WVALID & WREADY;

// wstate
always @(posedge ACLK) begin
if (ARESET)
wstate <= WRRESET;
else if (ACLK_EN)
wstate <= wnext;
end

// wnext
always @(*) begin
case (wstate)
WRIDLE:
if (AWVALID)
wnext = WRDATA;
else
wnext = WRIDLE;
WRDATA:
if (WVALID)
wnext = WRRESP;
else
wnext = WRDATA;
WRRESP:
if (BREADY)
wnext = WRIDLE;
else
wnext = WRRESP;
default:
wnext = WRIDLE;
endcase
end

// waddr
always @(posedge ACLK) begin
if (ACLK_EN) begin
if (aw_hs)
waddr <= AWADDR[ADDR_BITS-1:0];
end
end

//------------------------AXI read fsm-------------------
assign ARREADY = (rstate == RDIDLE);
assign RDATA = rdata;
assign RRESP = 2'b00; // OKAY
assign RVALID = (rstate == RDDATA);
assign ar_hs = ARVALID & ARREADY;
assign raddr = ARADDR[ADDR_BITS-1:0];

// rstate
always @(posedge ACLK) begin
if (ARESET)
rstate <= RDRESET;
else if (ACLK_EN)
rstate <= rnext;
end

// rnext
always @(*) begin
case (rstate)
RDIDLE:
if (ARVALID)
rnext = RDDATA;
else
rnext = RDIDLE;
RDDATA:
if (RREADY & RVALID)
rnext = RDIDLE;
else
rnext = RDDATA;
default:
rnext = RDIDLE;
endcase
end

// rdata
always @(posedge ACLK) begin
if (ACLK_EN) begin
if (ar_hs) begin
rdata <= 'b0;
case (raddr)
ADDR_MEM_DATA_0: begin
rdata <= int_mem[31:0];
end
ADDR_MEM_DATA_1: begin
rdata <= int_mem[63:32];
end
endcase
end
end
end


//------------------------Register logic-----------------
assign mem = int_mem;
// int_mem[31:0]
always @(posedge ACLK) begin
if (ARESET)
int_mem[31:0] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_MEM_DATA_0)
int_mem[31:0] <= (WDATA[31:0] & wmask) | (int_mem[31:0] & ~wmask);
end
end

// int_mem[63:32]
always @(posedge ACLK) begin
if (ARESET)
int_mem[63:32] <= 0;
else if (ACLK_EN) begin
if (w_hs && waddr == ADDR_MEM_DATA_1)
int_mem[63:32] <= (WDATA[31:0] & wmask) | (int_mem[63:32] & ~wmask);
end
end


//------------------------Memory logic-------------------

endmodule
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// ==============================================================
// Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2021.2 (64-bit)
// Copyright 1986-2021 Xilinx, Inc. All Rights Reserved.
// ==============================================================

`timescale 1 ns / 1 ps

module Lookup_0_flow_control_loop_pipe_sequential_init(
ap_clk,
ap_rst,
ap_start,
ap_ready,
ap_done,
ap_start_int,
ap_ready_int,
ap_done_int,
ap_continue_int,
ap_loop_init,
ap_loop_exit_ready,
ap_loop_exit_done
);

input ap_clk;
input ap_rst;

//Block level handshake with outside loop
input ap_start;
output ap_ready;
output ap_done;

//Block level handshake with loop body
output ap_start_int;
input ap_ready_int;
input ap_done_int;
output ap_continue_int;

//Init live in variables
output ap_loop_init;
wire ap_loop_init;
reg ap_loop_init_int;
reg ap_done;
reg ap_done_cache;

//Exit signal from loop body
input ap_loop_exit_ready;
input ap_loop_exit_done;

// power-on initialization
initial begin
#0 ap_loop_init_int = 1'b1;
#0 ap_done_cache = 1'b0;
end

assign ap_start_int = ap_start;

assign ap_continue_int = 1'b1;

assign ap_ready = ap_loop_exit_ready;

//ap_loop_init is valid for the first II
//of the first loop run so as to enable
//the init block ops which are pushed into
//the first state of the pipeline region
always @ (posedge ap_clk)
begin
if (ap_rst == 1'b1) begin
ap_loop_init_int <= 1'b1;
end else if(ap_loop_exit_done == 1'b1) begin
ap_loop_init_int <= 1'b1;
end else if(ap_ready_int == 1'b1) begin
ap_loop_init_int <= 1'b0;
end
end

assign ap_loop_init = ap_loop_init_int & ap_start;

// if no ap_continue port and current module is not top module,
// ap_done handshakes with ap_start. Internally, flow control sends out
// ap_conintue_int = 1'b1 so the ap_done_int is asserted high for 1 clock cycle.
// ap_done_cache is used to record ap_done_int, and de-assert if ap_start_int
// is asserted, so DUT can start the next run
always @(posedge ap_clk)
begin
if (ap_rst == 1'b1) begin
ap_done_cache <= 1'b0;
end else if (ap_done_int == 1'b1) begin
ap_done_cache <= 1'b1;
end else if (ap_start_int == 1'b1) begin
ap_done_cache <= 1'b0;
end
end

// if no ap_continue port and current module is not top module, ap_done handshakes with ap_start
always @(*)
begin
if ((ap_done_int == 1'b1) || ((ap_done_cache == 1'b1) && (ap_start_int == 1'b0))) begin
ap_done = 1'b1;
end else begin
ap_done = 1'b0;
end
end

endmodule
Loading