如何使脉动阵列架构矩阵向量乘法器的数据流控制可综合?
脉动阵列矩阵-向量乘法器综合问题改造方案
问题背景
基于8×8固定脉动阵列(PE总数64)的矩阵-向量乘法器,支持外部动态配置矩阵维度(最大64×64),仿真验证通过,但综合时数据流控制模块报错:
- ELAB-312:数组越界访问
W_reg[64](有效范围[0:63]) - ELAB-900:循环迭代次数超出综合器分析上限
核心矛盾:使用了运行时可变边界的for循环,综合器无法处理非编译期常量的迭代范围;同时存在数组维度不匹配、索引计算错误等问题。
错误根源分析
数组维度不匹配:
W_reg定义为[0:M-1](仅8个寄存器),但PE总数为64个,导致跨维度访问时触发越界;Ws、Xs的维度与PE阵列数量不匹配,引发索引访问错误。
动态循环不满足综合要求:
综合器要求for循环的迭代次数必须是编译期常量,但代码中使用M_val、cycle等运行时变量作为循环边界,导致综合器无法确定循环次数,触发ELAB-900错误。索引计算逻辑错误:
原代码中W_i[(cycle-m) + m*N_val]会出现负数索引(当cycle < m时),引发数组越界。
具体改造步骤
1. 修正数组维度匹配问题
- 保持
W_reg深度对应8行(每行1个权重输入寄存器):reg [DW-1:0] W_reg[0:M-1]; // 对应8行,每行1个权重输入寄存器 - 修正
Ws、Xs的维度,匹配64个PE的移位链需求:wire [DW-1:0] Ws[1:0][0:M*N-1]; // 64个PE的权重输入/输出 wire [DW-1:0] Xs [0:M*N]; // 向量移位链,64个PE对应65个节点
2. 将动态循环改为静态循环+条件赋值
所有使用M_val作为循环边界的代码,改为遍历编译期固定的全部索引,通过条件判断控制是否执行操作,确保循环次数固定:
例1:复位后的W_reg清零
原代码:
for(m = 0; m < M_val; m = m + 1) begin W_reg[m] <= 8'd0; end
改造后:
for(m = 0; m < M; m = m + 1) begin // M是编译期常量8 if(m < M_val) begin // 仅对前M_val行执行清零 W_reg[m] <= 8'd0; end end
例2:cycle < N_val时的权重加载
原代码:
for(m = 0; m < M_val; m = m + 1) begin W_reg[m] <= W_i[(cycle-m) + m*N_val]; end
改造后(修正索引计算,避免负数):
for(m = 0; m < M; m = m + 1) begin if(m < M_val) begin // 行优先存储,第m行第cycle列的权重索引为m*N_val + cycle W_reg[m] <= W_i[m*N_val + cycle]; end end
例3:cycle >= N_val时的权重加载
原代码:
for (m=cycle-N_val+1; m < M_val; m = m + 1) begin W_reg[m] <= W_i[(cycle-m) + m*N_val]; end
改造后(增加边界判断,避免负数索引):
for(m = 0; m < M; m = m + 1) begin // 仅当cycle >= N_val且m在有效范围内时执行赋值 if(cycle >= N_val && m >= (cycle - N_val + 1) && m < M_val) begin W_reg[m] <= W_i[m*N_val + cycle]; end end
3. 修正PE激活信号逻辑
原激活信号逻辑未正确映射到二维PE阵列,改造后确保前M_val行的所有PE被激活:
- 修正
activate_reg赋值:always@(posedge reset or posedge start_mult) begin if(!reset) activate_reg <= 64'hFFFF_FFFF_FFFF_FFFF; // 初始化全激活 else begin // 启用前M_val行,每行N个PE,共M_val*N个PE activate_reg <= (64'hFFFF_FFFF_FFFF_FFFF) >> (M*N - M_val*N); end end - 修正PE激活信号映射:
generate for (i = 0; i < M; i = i + 1) begin: PE_activators for (j = 0; j < N; j = j + 1) begin: COL_activators assign activate_pe[i*N + j] = activate_reg[i*N + j]; end end endgenerate
4. 修正PE实例化的移位连接
原PE的w_o悬空,需连接到同一行下一个PE的w_i,实现权重的脉动移位:
generate for (i = 0; i < M; i = i + 1) begin: ROWs for (j = 0; j < N; j = j + 1) begin: COLs PE #(DW) pe ( .clk(clk), .reset(reset), .activate(activate_pe[i*N + j]), .w_i(j == 0 ? W_reg[i] : Ws[0][i*N + j - 1]), // 行首PE从W_reg取权重,其余从左邻PE取 .x_i(Xs[i*N + j]), .w_o(Ws[0][i*N + j]), // 权重输出到右邻PE .x_o(Xs[i*N + j + 1]), .mac(Ys[i*N + j]) ); end end endgenerate
验证说明
改造后:
- 所有for循环的迭代次数均为编译期常量(8行或64个PE),满足综合器要求;
- 数组索引计算修正,避免越界访问;
- PE激活信号与权重移位逻辑匹配脉动阵列的数据流要求,仿真结果将与预期一致。
内容的提问来源于stack exchange,提问作者engineer1155
相关产品推荐
相关产品推荐

