// Single-class person detector — Icarus Verilog compatible // All weights from analytical least-squares. Zero training. 4,614 bytes INT8. module person_detector #( parameter FEAT_DIM = 768, parameter BIT_WIDTH = 8, parameter ACC_WIDTH = 24 )( input wire signed [BIT_WIDTH-1:0] features [0:FEAT_DIM-1], output wire signed [ACC_WIDTH-1:0] person_score, output wire signed [ACC_WIDTH-1:0] box_ltrb [0:3], output wire signed [ACC_WIDTH-1:0] centerness, output wire detection ); reg signed [BIT_WIDTH-1:0] cls_w [0:FEAT_DIM-1]; reg signed [BIT_WIDTH-1:0] reg_w [0:4*FEAT_DIM-1]; reg signed [BIT_WIDTH-1:0] ctr_w [0:FEAT_DIM-1]; initial begin $readmemh("rom/person_cls_w.hex", cls_w); $readmemh("rom/person_reg_w.hex", reg_w); $readmemh("rom/person_ctr_w.hex", ctr_w); end // Classification: sum(features[d] * cls_w[d]) reg signed [ACC_WIDTH-1:0] cls_acc; integer ci; always @(*) begin cls_acc = 0; for (ci = 0; ci < FEAT_DIM; ci = ci + 1) cls_acc = cls_acc + features[ci] * cls_w[ci]; end assign person_score = cls_acc; assign detection = (cls_acc > 0); // Box regression: 4 dot products reg signed [ACC_WIDTH-1:0] reg_acc [0:3]; integer ri, rj; always @(*) begin for (ri = 0; ri < 4; ri = ri + 1) begin reg_acc[ri] = 0; for (rj = 0; rj < FEAT_DIM; rj = rj + 1) reg_acc[ri] = reg_acc[ri] + features[rj] * reg_w[ri * FEAT_DIM + rj]; end end assign box_ltrb[0] = reg_acc[0]; assign box_ltrb[1] = reg_acc[1]; assign box_ltrb[2] = reg_acc[2]; assign box_ltrb[3] = reg_acc[3]; // Centerness: sum(features[d] * ctr_w[d]) reg signed [ACC_WIDTH-1:0] ctr_acc; integer cti; always @(*) begin ctr_acc = 0; for (cti = 0; cti < FEAT_DIM; cti = cti + 1) ctr_acc = ctr_acc + features[cti] * ctr_w[cti]; end assign centerness = ctr_acc; endmodule