RISC-V MCU中文社区

【分享】 蜂鸟NICE协处理器sbuf和lbuf指令verilog代码分析

发表于 开源蜂鸟E203 2022-05-21 12:48:26
0
218
0

/* custom3_sbuf的指令执行单元—存储数据 **/
wire [ROWBUF_IDX_W-1:0] sbuf_cnt_r; //当前存储数据的索引
wire [ROWBUF_IDX_W-1:0] sbuf_cnt_nxt; //下一存储数据的索引
wire sbuf_cnt_clr; //索引清零标志
wire sbuf_cnt_incr; //索引增标志
wire sbuf_cnt_ena; //索引更新 DFF 的使能位
wire sbuf_cnt_last; //当前索引为最大 标志位
wire sbuf_icb_cmd_hsked; //sbuf指令下 存储器请求通道 握手成功标志
wire sbuf_icb_rsp_hsked; //sbuf指令下 存储器反馈通道 握手成功标志
wire nice_rsp_valid_sbuf; //sbuf指令下 反馈通道发送反馈请求信号 (协→主)
wire nice_icb_cmd_valid_sbuf; //sbuf指令下 存储器请求通道发送存储器读写请求 (协→主)
wire nice_icb_cmd_hsked; //存储器请求通道 握手成功标志

assign sbuf_icb_cmd_hsked = (state_is_sbuf | (state_is_idle & custom3_sbuf)) & nice_icb_cmd_hsked;
//两种情况分别为IDLE时的留一手; SBUF时的正常握手成功标志
assign sbuf_icb_rsp_hsked = state_is_sbuf & nice_icb_rsp_hsked;
assign sbuf_icb_rsp_hsked_last = sbuf_icb_rsp_hsked & sbuf_cnt_last; //配合NICE状态机状态转换,与生成state_lbuf_exit_ena信号有关
assign sbuf_cnt_last = (sbuf_cnt_r == clonum); //索引为 2 时 为最大
//assign sbuf_cnt_clr = custom3_sbuf & nice_req_hsked;
assign sbuf_cnt_clr = sbuf_icb_rsp_hsked_last; //在将要离开SBUF状态时清零(与lsuf不同但无影响)
assign sbuf_cnt_incr = sbuf_icb_rsp_hsked & ~sbuf_cnt_last; //索引增 标志位
assign sbuf_cnt_ena = sbuf_cnt_clr | sbuf_cnt_incr; //索引DFF变化使能位—索引清零 和 索引增 标志下都会使能索引变化
//当前为索引增状态则下一索引为 当前索引+1;为索引清零状态则为2’b00
assign sbuf_cnt_nxt = ({ROWBUF_IDX_W{sbuf_cnt_clr }} & {ROWBUF_IDX_W{1’b0}})
| ({ROWBUF_IDX_W{sbuf_cnt_incr}} & (sbuf_cnt_r + 1’b1) )
;
//索引更新DFF #(位宽为2) (使能,下一索引,当前索引,时钟,复位)
sirv_gnrl_dfflr #(ROWBUF_IDX_W) sbuf_cnt_dfflr (sbuf_cnt_ena, sbuf_cnt_nxt, sbuf_cnt_r, nice_clk, nice_rst_n);

//sbuf指令下 反馈通道 发送 反馈请求信号 (协→主) — 当前指令为sbuf & 存储到最后一位了 & 协处理器在存储器反馈通道请求反馈
assign nice_rsp_valid_sbuf = state_is_sbuf & sbuf_cnt_last & nice_icb_rsp_valid;

wire [ROWBUF_IDX_W-1:0] sbuf_cmd_cnt_r; //sbuf指令 存储器访问通道 当前访问 索引
wire [ROWBUF_IDX_W-1:0] sbuf_cmd_cnt_nxt; //sbuf指令 存储器访问通道 下一访问 索引
wire sbuf_cmd_cnt_clr; //sbuf指令 存储器访问通道 索引清零 标志
wire sbuf_cmd_cnt_incr; //sbuf指令 存储器访问通道 索引增 标志
wire sbuf_cmd_cnt_ena; //sbuf指令 存储器访问通道 索引更新 使能
wire sbuf_cmd_cnt_last; //sbuf指令 存储器访问通道 索引最大 标志

assign sbuf_cmd_cnt_last = (sbuf_cmd_cnt_r == clonum); //索引 = clonum(2) 为最后一次访问寄存器(索引最大)
assign sbuf_cmd_cnt_clr = sbuf_icb_rsp_hsked_last; //存储器反馈通道为最后一次反馈时 清零标志为 1
assign sbuf_cmd_cnt_incr = sbuf_icb_cmd_hsked & ~sbuf_cmd_cnt_last; //存储器访问通道握手成功 且索引非最大时 增标志为 1
assign sbuf_cmd_cnt_ena = sbuf_cmd_cnt_clr | sbuf_cmd_cnt_incr; //增 或 清零 使能索引更新
assign sbuf_cmd_cnt_nxt = ({ROWBUF_IDX_W{sbuf_cmd_cnt_clr }} & {ROWBUF_IDX_W{1’b0}})
| ({ROWBUF_IDX_W{sbuf_cmd_cnt_incr}} & (sbuf_cmd_cnt_r + 1’b1) )
; //索引清零标志 为 1 — 索引 → 2’b00
//索引增标志 为 1 — 索引 + 1
//存储器访问通道索引更新 DFF #(位宽为2) (使能,下一索引,当前索引,时钟,复位)
sirv_gnrl_dfflr #(ROWBUF_IDX_W) sbuf_cmd_cnt_dfflr (sbuf_cmd_cnt_ena, sbuf_cmd_cnt_nxt, sbuf_cmd_cnt_r, nice_clk, nice_rst_n);
/
sbuf_cmd_cnt_r 和 sbuf_cnt_r 比较⭐:
使能信号 = 清零 或 增:
sbuf_cnt_ena = sbuf_cnt_clr | sbuf_cnt_incr; sbuf_cmd_cnt_ena = sbuf_cmd_cnt_clr | sbuf_cmd_cnt_incr;
清零标志 同步:
sbuf_cnt_clr = sbuf_icb_rsp_hsked_last; sbuf_cmd_cnt_clr = sbuf_icb_rsp_hsked_last;
增标志: sbuf_cnt_incr 比 sbuf_cmd_cnt_incr 滞后
(存储器反馈通道 握手成功) 滞后于 (存储器请求通道 握手成功)
sbuf_cnt_incr = sbuf_icb_rsp_hsked & ~sbuf_cnt_last; sbuf_cmd_cnt_incr = sbuf_icb_cmd_hsked & ~sbuf_cmd_cnt_last;
当 sbuf_cnt_r 未满 sbuf_cmd_cnt_r 已经满的时候既是 存储器请求通道握手成功 和 存储器反馈通道握手成功 之间
/
//sbuf指令 存储器请求 — 为了完成类似P288页的时序,最后一次访问存储器时,存储器反馈通道握手成功后,存储器请求通道便不再请求握手
assign nice_icb_cmd_valid_sbuf = (state_is_sbuf & (sbuf_cmd_cnt_r <= clonum) & (sbuf_cnt_r != clonum));

/*/
/ * 行数据缓存 rowbuf **/
// rowbuf access list:
// 1. lbuf will write to rowbuf, write data comes from memory, data length is defined by clonum
// 2. sbuf will read from rowbuf, and store it to memory, data length is defined by clonum
// 3. rowsum will accumulate data, and store to rowbuf, data length is defined by clonum
wire [E203_XLEN-1:0] rowbuf_r [ROWBUF_DP-1:0]; // ⭐⭐⭐16字节(4个数据)行缓存--rowbuf // [ROWBUF_DP-1:0]为定义ROWBUF_DP(4)个位宽为32的数据 wire [E203_XLEN-1:0] rowbuf_wdat [ROWBUF_DP-1:0]; //将要加载到行缓存数据上的值,中间计算用
wire [ROWBUF_DP-1:0] rowbuf_we; //行缓存数据更新使能位—-rowbuf_dfflr 触发器的使能位
wire [ROWBUF_IDX_W-1:0] rowbuf_idx_mux; //idx—索引;mux—多路复用;行缓存的索引,rowsum和sbuf多路复用
wire [`E203_XLEN-1:0] rowbuf_wdat_mux; //向 rowbuf 中写入的数据(多路复用)
wire rowbuf_wr_mux; //rowbuf 的 写使能(多路复用)

// lbuf指令 向rowbuf中写
wire [ROWBUF_IDX_W-1:0] lbuf_idx = lbuf_cnt_r; //lbuf指令 向rowbuf中写数据 索引
wire lbuf_wr = lbuf_icb_rsp_hsked; //lbuf指令 向rowbuf中写数据 使能
wire [`E203_XLEN-1:0] lbuf_wdata = nice_icb_rsp_rdata; //lbuf指令 向rowbuf中写的数据 (内存 → 协处理器)

// rowsum指令 向rowbuf中写 (列累加数据)(column accumulated data)
wire [ROWBUF_IDX_W-1:0] rowsum_idx = rcv_data_buf_idx; //rowsum指令 向rowbuf中写数据 索引
wire rowsum_wr = rcv_data_buf_valid; //rowsum指令 向rowbuf中写数据 使能
wire [`E203_XLEN-1:0] rowsum_wdata = rowbuf_r[rowsum_idx] + rcv_data_buf; //rowsum指令 向rowbuf中写的数据 (内存 → 协处理器)

//向rowbuf中写的数据—多路复用相关信号
assign rowbuf_wdat_mux =
({ E203_XLEN{lbuf_wr }} & lbuf_wdata )|({E203_XLEN{rowsum_wr}} & rowsum_wdata) //数据多路复用
;
assign rowbuf_wr_mux = lbuf_wr | rowsum_wr; //使能多路复用
assign rowbuf_idx_mux = ({ROWBUF_IDX_W{lbuf_wr }} & lbuf_idx ) //索引多路复用
| ({ROWBUF_IDX_W{rowsum_wr}} & rowsum_idx)
;

// rowbuf inst
genvar i;
generate //i = 0、1、2,for循环的循环次数为3
for (i=0; i assign rowbuf_we[i] = (rowbuf_wr_mux & (rowbuf_idx_mux == i[ROWBUF_IDX_W-1:0]))
; //i[ROWBUF_IDX_W-1:0]:i类似一个多位的信号,i[1:0]表示i的最低2位
//也就是for循环的每一次对应判断rowbuf的每一位

assign rowbuf_wdat[i] = ({E203_XLEN{rowbuf_we[i]}} & rowbuf_wdat_mux ) ; sirv_gnrl_dfflr #(E203_XLEN) rowbuf_dfflr (rowbuf_we[i], rowbuf_wdat[i], rowbuf_r[i], nice_clk, nice_rst_n);
end
endgenerate

/*/

喜欢0
用户评论
CC2197

CC2197 未通过实名认证

二白

积分
问答
粉丝
关注
  • RV-STAR 开发板
  • RISC-V处理器设计系列课程
  • 培养RISC-V大学土壤 共建RISC-V教育生态
RV-STAR 开发板