Skip to content
Snippets Groups Projects
Commit c52ab50d authored by Thomas B. Preußer's avatar Thomas B. Preußer
Browse files

First prototype for dynamically sized FM padding.

parent cda470c9
No related branches found
No related tags found
No related merge requests found
/******************************************************************************
* Copyright (C) 2022, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION). HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @brief Feature map padding.
* @author Thomas B. Preußer <tpreusse@amd.com>
*****************************************************************************/
module fmpadding_axi #(
int unsigned XCOUNTER_BITS,
int unsigned YCOUNTER_BITS,
int unsigned NUM_CHANNELS,
int unsigned SIMD,
int unsigned ELEM_BITS,
localparam int unsigned STREAM_BITS = 8*(1 + (SIMD*ELEM_BITS-1)/8)
)(
//- Global Control ------------------
input logic ap_clk,
input logic ap_rst_n,
/*
//- AXI Lite ------------------------
// Writing
input s_axilite_AWVALID,
output s_axilite_AWREADY,
input [2:0] s_axilite_AWADDR,
input s_axilite_WVALID,
output s_axilite_WREADY,
input [31:0] s_axilite_WDATA,
input [ 3:0] s_axilite_WSTRB,
output s_axilite_BVALID,
input s_axilite_BREADY,
output [1:0] s_axilite_BRESP,
// Reading
input s_axilite_ARVALID,
output s_axilite_ARREADY,
input [3:0] s_axilite_ARADDR,
output s_axilite_RVALID,
input s_axilite_RREADY,
output [31:0] s_axilite_RDATA,
output [ 1:0] s_axilite_RRESP,
*/
input logic we,
input logic [ 2:0] wa,
input logic [31:0] wd,
//- AXI Stream - Input --------------
output logic s_axis_tready,
input logic s_axis_tvalid,
input logic [STREAM_BITS-1:0] s_axis_tdata,
//- AXI Stream - Output -------------
input logic m_axis_tready,
output logic m_axis_tvalid,
output logic [STREAM_BITS-1:0] m_axis_tdata
);
uwire clk = ap_clk;
uwire rst = !ap_rst_n;
//-----------------------------------------------------------------------
// Dynamically configurable state
typedef logic [XCOUNTER_BITS-1:0] xcount_t;
xcount_t XEnd = 0;
xcount_t XOn = 0;
xcount_t XOff = 0;
typedef logic [YCOUNTER_BITS-1:0] ycount_t;
ycount_t YEnd = 0;
ycount_t YOn = 0;
ycount_t YOff = 0;
always_ff @(posedge clk) begin
if(we) begin
unique case(wa)
0: XOn <= wd;
1: XOff <= wd;
2: XEnd <= wd;
4: YOn <= wd;
5: YOff <= wd;
6: YEnd <= wd;
default: assert(0) else begin
$error("Illegal write address.");
$stop;
end
endcase
end
end
//-----------------------------------------------------------------------
// Cascaded enables for the nested counters: SCount, XCount, YCount
uwire sen;
uwire xen;
uwire yen;
//- S-Counter: SIMD fold ------------
initial begin
if((NUM_CHANNELS < 1) || (NUM_CHANNELS % SIMD != 0)) begin
$error("Channel count must be SIMD multiple.");
$finish;
end
end
// Count SF-2, SF-3, ..., 1, 0, -1
localparam int unsigned SF = NUM_CHANNELS/SIMD;
typedef logic [$clog2(SF-1):0] scount_t;
scount_t SCount = SF-2;
assign xen = sen && SCount[$left(SCount)];
uwire sclr = rst || xen;
always_ff @(posedge clk) begin
if(sclr) SCount <= SF-2;
else if(sen) SCount <= SCount - 1;
end
//- X-Counter: image width ----------
xcount_t XCount = 0;
assign yen = xen && (XCount == XEnd);
uwire xclr = rst || yen;
always_ff @(posedge clk) begin
if(xclr) XCount <= 0;
else if(xen) XCount <= XCount + 1;
end
uwire xfwd = (XOn <= XCount) && (XCount < XOff);
//- Y-Counter: image height ---------
ycount_t YCount = 0;
uwire yclr = rst || (yen && (YCount == YEnd));
always_ff @(posedge clk) begin
if(yclr) YCount <= 0;
else if(yen) YCount <= YCount + 1;
end
uwire yfwd = (YOn <= YCount) && (YCount < YOff);
//-----------------------------------------------------------------------
// Input forwarding and edge padding
typedef struct {
logic vld;
logic [STREAM_BITS-1:0] dat;
} buf_t;
buf_t A = '{ vld: 0, dat: 'x };
buf_t B = '{ vld: 0, dat: 'x };
uwire fwd = xfwd && yfwd;
assign sen = (m_axis_tready || !B.vld) && (s_axis_tvalid || A.vld || !fwd);
assign s_axis_tready = !A.vld;
assign m_axis_tvalid = B.vld;
assign m_axis_tdata = B.dat;
always_ff @(posedge clk) begin
if(rst) begin
B <= '{ vld: 0, dat: 'x };
end
else if(m_axis_tready || !B.vld) begin
B.vld <= s_axis_tvalid || A.vld || !fwd;
B.dat <= !fwd? '0 : A.vld? A.dat : s_axis_tdata;
end
end
always_ff @(posedge clk) begin
if(rst) begin
A <= '{ vld: 0, dat: 'x };
end
else begin
A.vld <= (A.vld || s_axis_tvalid) && ((B.vld && !m_axis_tready) || !fwd);
if(!A.vld) A.dat <= s_axis_tdata;
end
end
endmodule : fmpadding_axi
module fmpadding_axi_tb #(
int unsigned XCOUNTER_BITS = 8,
int unsigned YCOUNTER_BITS = 8,
int unsigned NUM_CHANNELS = 4,
int unsigned SIMD = 2,
int unsigned ELEM_BITS = 4
)();
localparam int unsigned STREAM_BITS = 8*(1 + (SIMD*ELEM_BITS-1)/8);
//- Global Control ------------------
logic clk = 0;
always #5ns clk = !clk;
logic rst;
// Parameter Configuration ----------
logic we;
logic [ 2:0] wa;
logic [31:0] wd;
//- AXI Stream - Input --------------
uwire s_axis_tready;
logic s_axis_tvalid;
logic [STREAM_BITS-1:0] s_axis_tdata;
//- AXI Stream - Output -------------
logic m_axis_tready;
uwire m_axis_tvalid;
uwire [STREAM_BITS-1:0] m_axis_tdata;
// DUT
fmpadding_axi #(
.XCOUNTER_BITS(XCOUNTER_BITS),
.YCOUNTER_BITS(YCOUNTER_BITS),
.NUM_CHANNELS(NUM_CHANNELS),
.SIMD(SIMD),
.ELEM_BITS(ELEM_BITS)
) dut (
.ap_clk(clk), .ap_rst_n(!rst),
.we, .wa, .wd,
.s_axis_tready, .s_axis_tvalid, .s_axis_tdata,
.m_axis_tready, .m_axis_tvalid, .m_axis_tdata
);
// Stimuli
localparam int unsigned IMAGES = 2;
localparam int unsigned XSIZE = 10;
localparam int unsigned YSIZE = 7;
localparam int unsigned PAD_LEFT = 2;
localparam int unsigned PAD_RIGHT = 3;
localparam int unsigned PAD_TOP = 1;
localparam int unsigned PAD_BOTTOM = 2;
initial begin
we = 0;
wa = 'x;
wd = 'x;
s_axis_tvalid = 0;
s_axis_tdata = 'x;
// Configure Parameters
rst = 1;
@(posedge clk);
we <= 1;
/* XOn */ wa <= 0; wd <= PAD_LEFT; @(posedge clk);
/* XOff */ wa <= 1; wd <= XSIZE - PAD_RIGHT; @(posedge clk);
/* XEnd */ wa <= 2; wd <= XSIZE - 1; @(posedge clk);
/* YOn */ wa <= 4; wd <= PAD_TOP; @(posedge clk);
/* YOff */ wa <= 5; wd <= YSIZE - PAD_BOTTOM; @(posedge clk);
/* YEnd */ wa <= 6; wd <= YSIZE - 1; @(posedge clk);
we <= 0;
wa <= 'x;
wd <= 'x;
@(posedge clk);
rst <= 0;
// Feed data input
s_axis_tvalid <= 1;
for(int unsigned i = 0; i < IMAGES * (XSIZE-PAD_LEFT-PAD_RIGHT) * (YSIZE-PAD_TOP-PAD_BOTTOM) * (NUM_CHANNELS/SIMD); i++) begin
s_axis_tdata <= i;
@(posedge clk iff s_axis_tready);
if($urandom()%5 == 0) begin
s_axis_tvalid <= 0;
s_axis_tdata <= 'x;
@(posedge clk);
s_axis_tvalid <= 1;
end
end
s_axis_tvalid <= 0;
s_axis_tdata <= 'x;
end
// Ouput Throttler
initial begin
m_axis_tready = 0;
@(posedge clk iff !rst);
m_axis_tready <= 1;
forever @(posedge clk iff m_axis_tvalid) begin
m_axis_tready <= 0;
repeat(4-$clog2(1+$urandom()%15)) @(posedge clk);
m_axis_tready <= 1;
end
end
// Output logger
initial begin
repeat(IMAGES) begin
for(int unsigned y = 0; y < YSIZE; y++) begin
for(int unsigned x = 0; x < XSIZE; x++) begin
automatic string delim = " ";
for(int unsigned s = 0; s < NUM_CHANNELS/SIMD; s++) begin
@(posedge clk iff m_axis_tvalid && m_axis_tready);
$write("%s%02X", delim, m_axis_tdata);
delim = ":";
end
end
$display();
end
$display("----");
end
$finish;
end
endmodule : fmpadding_axi_tb
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment