NPU 프론트엔드 모듈¶
GitHub RTL 원본
이 페이지가 참조하는 SystemVerilog 원본 파일:
hw/rtl/NPU_Controller/NPU_frontend/AXIL_CMD_IN.sv— GitHub에서 보기hw/rtl/NPU_Controller/NPU_frontend/AXIL_STAT_OUT.sv— GitHub에서 보기hw/rtl/NPU_Controller/NPU_frontend/ctrl_npu_frontend.sv— GitHub에서 보기hw/rtl/NPU_Controller/npu_interfaces.svh— GitHub에서 보기
역할¶
NPU 프론트엔드는 PS↔PL 경계의 AXI-Lite 진입점이다.
호스트 드라이버 HAL은 0x000 주소에 ISA 워드를 기록하고 0x008에 kick을 기록하며,
완료 상태는 같은 인터페이스의 읽기 채널로 폴링한다.
AXIL_CMD_IN은 호스트 write 트랜잭션을 FIFO에 수신하고,
AXIL_STAT_OUT은 엔진 완료 상태를 FIFO를 통해 호스트 읽기로 반환한다.
계층적으로 ctrl_npu_frontend의 상위는 AXI-Lite 버스, 하위는 컨트롤러의
디코더/디스패처(NPU 컨트롤러 모듈)이다.
AXIL_CMD_IN¶
호스트 write 트랜잭션을 수신하여 명령어를 CMD_IN FIFO에 저장한다.
파라미터 FIFO_DEPTH(기본값 8)가 FIFO 깊이를 결정한다.
FIFO가 가득 차면 s_awready가 자동으로 디어서트되어 호스트에 백프레셔를 건다.
등록 주소는 두 곳이다: 0x000은 ISA 명령어 워드를 직접 FIFO에 삽입하고,
0x008은 bit63 = 1인 kick 마커를 삽입한다.
kick 마커는 하위 디스패처가 배치 경계를 감지하는 데 사용된다.
OUT_valid && IN_decoder_ready 핸드셰이크가 성립하는 사이클마다 FIFO에서 팝이 일어난다.
/*─────────────────────────────────────────────
Register Address Map
───────────────────────────────────────────────*/
localparam ADDR_INST = 12'h000;
localparam ADDR_KICK = 12'h008;
AXIL_STAT_OUT¶
엔진 완료 시 상위 모듈이 IN_valid를 어서트하여 상태 워드를 STAT_OUT FIFO에 푸시한다.
파라미터 FIFO_DEPTH(기본값 8)가 적용된다.
FIFO가 가득 차면 IN_valid가 무시된다. 완료 워드는 엔진에서 동일한 값으로 재전송되므로
누락은 재폴링으로 복구된다.
호스트가 AR 채널로 읽기를 요청하면 FIFO 헤드를 rdata_r에 래치하고 s_rvalid를
어서트한다. s_rready가 도착하면 rvalid를 해제한다.
s_arready는 FIFO가 비어 있거나 R 응답이 아직 진행 중일 때 디어서트된다.
/*─────────────────────────────────────────────
FIFO (simple synchronous, FIFO_DEPTH entries)
Push : IN_valid from upper module
Pop : AXI4-Lite read handshake with CPU
───────────────────────────────────────────────*/
localparam PTR_W = $clog2(FIFO_DEPTH);
logic [`ISA_WIDTH-1:0] mem[0:FIFO_DEPTH-1];
logic [PTR_W:0] wr_ptr, rd_ptr;
logic fifo_empty, fifo_full;
assign fifo_empty = (wr_ptr == rd_ptr);
assign fifo_full = (wr_ptr[PTR_W] != rd_ptr[PTR_W]) && (wr_ptr[PTR_W-1:0] == rd_ptr[PTR_W-1:0]);
logic fifo_ren;
always_ff @(posedge clk) begin
if (!rst_n || IN_clear) begin
wr_ptr <= '0;
rd_ptr <= '0;
end else begin
// push : upper module feeds status continuously
if (IN_valid && !fifo_full) begin
mem[wr_ptr[PTR_W-1:0]] <= IN_data;
wr_ptr <= wr_ptr + 1'b1;
end
// pop : CPU consumed the data
if (fifo_ren && !fifo_empty) rd_ptr <= rd_ptr + 1'b1;
end
end
/*─────────────────────────────────────────────
AXI4-Lite Read Path
Wait for AR, then pop one entry from FIFO and return it.
Hold rvalid until CPU acknowledges with rready.
───────────────────────────────────────────────*/
logic [`ISA_WIDTH-1:0] rdata_r;
logic rvalid_r;
assign s_rdata = rdata_r;
assign s_rresp = 2'b00;
assign s_rvalid = rvalid_r;
assign s_arready = ~rvalid_r && ~fifo_empty; // ready only when FIFO has data
assign fifo_ren = s_arvalid && s_arready; // pop on AR handshake
always_ff @(posedge clk) begin
if (!rst_n || IN_clear) begin
rdata_r <= '0;
rvalid_r <= 1'b0;
end else begin
// AR handshake → latch FIFO head and assert rvalid
if (s_arvalid && s_arready) begin
rdata_r <= mem[rd_ptr[PTR_W-1:0]];
rvalid_r <= 1'b1;
end
// R handshake → CPU consumed data, release
if (rvalid_r && s_rready) rvalid_r <= 1'b0;
end
end
ctrl_npu_frontend¶
ctrl_npu_frontend는 axil_if.slave 인터페이스를 통해 AXI-Lite 신호를
AXIL_CMD_IN(write 채널)과 AXIL_STAT_OUT(read 채널)에 배선하는 wrapper 모듈이다.
CMD_IN의 출력(cmd_data, cmd_valid)은 OUT_RAW_instruction과 OUT_kick으로
컨트롤러에 전달된다. OUT_kick은 cmd_valid & IN_fetch_ready의 조합논리로 생성된다.
STAT_OUT 방향은 IN_enc_stat / IN_enc_valid를 인코더 FSM으로부터 직접 수신한다.
ctrl_npu_interface.sv는 향후 코어별 인터페이스 집계를 위한 플레이스홀더다.
AXIL_CMD_IN #(
.FIFO_DEPTH(8)
) u_cmd_in (
.clk (clk),
.rst_n (rst_n),
.IN_clear(IN_clear), // FIXED: Typo i_clear -> IN_clear
// AXI4-Lite Write channels directly routed from the interface
.s_awaddr (S_AXIL_CTRL.awaddr),
.s_awvalid(S_AXIL_CTRL.awvalid),
.s_awready(S_AXIL_CTRL.awready),
.s_wdata (S_AXIL_CTRL.wdata),
.s_wvalid (S_AXIL_CTRL.wvalid),
.s_wready (S_AXIL_CTRL.wready),
.s_bresp (S_AXIL_CTRL.bresp),
.s_bvalid (S_AXIL_CTRL.bvalid),
.s_bready (S_AXIL_CTRL.bready),
.OUT_data(cmd_data),
.OUT_valid(cmd_valid),
.IN_decoder_ready(IN_fetch_ready)
);
/*─────────────────────────────────────────────
[1-2] Communication OUT : NPU -> CPU (Using Read Channels)
───────────────────────────────────────────────*/
AXIL_STAT_OUT #(
.FIFO_DEPTH(8)
) u_stat_out (
.clk (clk),
.rst_n (rst_n),
.IN_clear(IN_clear), // FIXED: Typo i_clear -> IN_clear
.IN_data (IN_enc_stat), // FIXED: Typo i_enc_stat -> IN_enc_stat
.IN_valid(IN_enc_valid), // FIXED: Typo i_enc_valid -> IN_enc_valid
// AXI4-Lite Read channels directly routed from the interface
.s_araddr (S_AXIL_CTRL.araddr),
.s_arvalid(S_AXIL_CTRL.arvalid),
.s_arready(S_AXIL_CTRL.arready),
.s_rdata (S_AXIL_CTRL.rdata),
.s_rresp (S_AXIL_CTRL.rresp),
.s_rvalid (S_AXIL_CTRL.rvalid),
.s_rready (S_AXIL_CTRL.rready)
);
인터페이스 명세¶
npu_interfaces.svh에 axil_if와 axis_if 두 인터페이스가 정의된다.
axil_if는 ADDR_W=12, DATA_W=64 기본값으로 AW/W/B/AR/R 5개 채널을 모두 포함하고,
slave와 master modport를 제공한다.
ctrl_npu_frontend는 axil_if.slave modport를 사용한다.
axis_if는 tdata/tvalid/tready/tlast/tkeep의 AXI-Stream 인터페이스로,
데이터 경로 모듈이 사용한다.
interface axis_if #(
parameter DATA_WIDTH = 128
) ();
logic [ DATA_WIDTH-1:0] tdata;
logic tvalid;
logic tready;
logic tlast;
logic [(DATA_WIDTH/8)-1:0] tkeep;
// Slave Side (NPU Perspective: Input)
modport slave(input tdata, tvalid, tlast, tkeep, output tready);
// Master Side (NPU Perspective: Output)
modport master(output tdata, tvalid, tlast, tkeep, input tready);
endinterface
// axil_if.sv
interface axil_if #(
parameter int ADDR_W = 12,
parameter int DATA_W = 64
) (
input logic clk,
input logic rst_n
);
// AW Channel
logic [ADDR_W-1:0] awaddr;
logic [ 2:0] awprot;
logic awvalid, awready;
// W Channel
logic [ DATA_W-1:0] wdata;
logic [(DATA_W/8)-1:0] wstrb;
logic wvalid, wready;
// B Channel
logic [1:0] bresp;
logic bvalid, bready;
// AR Channel
logic [ADDR_W-1:0] araddr;
logic [ 2:0] arprot;
logic arvalid, arready;
// R Channel
logic [DATA_W-1:0] rdata;
logic [ 1:0] rresp;
logic rvalid, rready;
modport slave(
input awaddr, awprot, awvalid, wdata, wstrb, wvalid, bready,
input araddr, arprot, arvalid, rready,
output awready, wready, bresp, bvalid, arready, rdata, rresp, rvalid
);
modport master(
output awaddr, awprot, awvalid, wdata, wstrb, wvalid, bready,
output araddr, arprot, arvalid, rready,
input awready, wready, bresp, bvalid, arready, rdata, rresp, rvalid
);
endinterface
마지막 검증 대상
커밋 8c09e5e @ pccxai/pccx-FPGA-NPU-LLM-kv260 (2026-04-29).