NICE的Verilog代码
一、端口说明
// System input nice_clk ,input nice_rst_n ,output nice_active ,output nice_mem_holdup ,//avoid memory read or write by other devices// Control cmd_reqinput nice_req_valid ,//E203 send a nice requestoutput nice_req_ready ,//nice can receive requestinput [`E203_XLEN-1:0] nice_req_inst ,//custom instructioninput [`E203_XLEN-1:0] nice_req_rs1 ,//the register 1input [`E203_XLEN-1:0] nice_req_rs2 ,//the register 2// Control cmd_rsp output nice_rsp_valid ,//nice send responseinput nice_rsp_ready ,//e203 can receive responseoutput [`E203_XLEN-1:0] nice_rsp_rdat ,//compute result output nice_rsp_err , //nice has error// Memory lsu_req output nice_icb_cmd_valid ,//nice send a memory requestinput nice_icb_cmd_ready ,//e203 can receive memory requestoutput [`E203_ADDR_SIZE-1:0] nice_icb_cmd_addr ,//memory request addressoutput nice_icb_cmd_read ,//0:write 1:read output [`E203_XLEN-1:0] nice_icb_cmd_wdata ,//write data requestoutput [1:0] nice_icb_cmd_size ,//00:byte 01:half-word 10:word 11:reserved// Memory lsu_rsp input nice_icb_rsp_valid ,//e203 send memory responseoutput nice_icb_rsp_ready ,//nice can receive memoryinput [`E203_XLEN-1:0] nice_icb_rsp_rdata ,//the data read from memoryinput nice_icb_rsp_err //error during memory access
二、RISC-V的指令
其中opcode有4个可自行扩展
NICE使用了custom3,如下
wire opcode_custom3 = (opcode == 7'b1111011);
三、代码中的定义
1、指令相关
①
定义opcode为指令的{6->0},rv32_func3为{14->12}, rv32_func7为{31->25}
wire [6:0] opcode = {7{nice_req_valid}} & nice_req_inst[6:0]; //nice_req_valid=1, op == construcion[6:0]
wire [2:0] rv32_func3 = {3{nice_req_valid}} & nice_req_inst[14:12];//nice_req_valid=1, func3 == construcion[14:12]
wire [6:0] rv32_func7 = {7{nice_req_valid}} & nice_req_inst[31:25];//nice_req_valid=1, func7 == construcion[31:25]
②
定义扩展模式custom3 = 7'h3b
wire opcode_custom3 = (opcode == 7'b1111011);
③
定义func3和func7相关
wire rv32_func3_000 = (rv32_func3 == 3'b000); wire rv32_func3_001 = (rv32_func3 == 3'b001); wire rv32_func3_010 = (rv32_func3 == 3'b010); wire rv32_func3_011 = (rv32_func3 == 3'b011); wire rv32_func3_100 = (rv32_func3 == 3'b100); wire rv32_func3_101 = (rv32_func3 == 3'b101); wire rv32_func3_110 = (rv32_func3 == 3'b110); wire rv32_func3_111 = (rv32_func3 == 3'b111); wire rv32_func7_0000000 = (rv32_func7 == 7'b0000000); wire rv32_func7_0000001 = (rv32_func7 == 7'b0000001); wire rv32_func7_0000010 = (rv32_func7 == 7'b0000010); wire rv32_func7_0000011 = (rv32_func7 == 7'b0000011); wire rv32_func7_0000100 = (rv32_func7 == 7'b0000100); wire rv32_func7_0000101 = (rv32_func7 == 7'b0000101); wire rv32_func7_0000110 = (rv32_func7 == 7'b0000110); wire rv32_func7_0000111 = (rv32_func7 == 7'b0000111);
④
定义三条自定义指令在custom3情况下与func3、func7的关系
wire custom3_lbuf = opcode_custom3 & rv32_func3_010 & rv32_func7_0000001;//the instrution is {7'h01,10'hxx,3'h2,5'hxx,7'h3b}
wire custom3_sbuf = opcode_custom3 & rv32_func3_010 & rv32_func7_0000010;//the instrution is {7'h02,10'hxx,3'h2,5'hxx,7'h3b}
wire custom3_rowsum = opcode_custom3 & rv32_func3_110 & rv32_func7_0000110;//the instrution is {7'h06,10'hxx,3'h2,5'hxx,7'h3b}
具体的来说,三条指令如下
指令 | func3 | func7 | 32位的指令 | 读取 | 写回 |
custom3_lbuf | 3'h2 | 7'h01 | {7'h01,10'hxx,3'h2,5'hxx,7'h7b} | rs1 | |
custom3_sbuf | 3'h2 | 7'h02 | {7'h02,10'hxx,3'h2,5'hxx,7'h7b} | rs1 | |
custom3_rowsum | 3'h6 | 7'h06 | {7'h06,10'hxx,3'h6,5'hxx,7'h7b} | rs1 | rd |
⑤
定义两个信号,分别代表协处理器指令和需要访问memory
// multi-cyc op wire custom_multi_cyc_op = custom3_lbuf | custom3_sbuf | custom3_rowsum;//the instrution is made by nice// need access memorywire custom_mem_op = custom3_lbuf | custom3_sbuf | custom3_rowsum;//the instrution is made by nice and need memory
2、状态机相关
①
状态机的4状态,空闲和三个指令
parameter NICE_FSM_WIDTH = 2; parameter IDLE = 2'd0; parameter LBUF = 2'd1; parameter SBUF = 2'd2; parameter ROWSUM = 2'd3;
②
定义现态和次态,以及四个状态的下个状态
wire [NICE_FSM_WIDTH-1:0] state_r; wire [NICE_FSM_WIDTH-1:0] nxt_state; wire [NICE_FSM_WIDTH-1:0] state_idle_nxt; wire [NICE_FSM_WIDTH-1:0] state_lbuf_nxt; wire [NICE_FSM_WIDTH-1:0] state_sbuf_nxt; wire [NICE_FSM_WIDTH-1:0] state_rowsum_nxt;
③
定义现在是什么状态的四个信号
wire state_is_idle = (state_r == IDLE); wire state_is_lbuf = (state_r == LBUF); wire state_is_sbuf = (state_r == SBUF); wire state_is_rowsum = (state_r == ROWSUM);
④
定义状态离开使能信号,四个状态的和真实状态的,共5个
wire state_idle_exit_ena; wire state_lbuf_exit_ena; wire state_sbuf_exit_ena; wire state_rowsum_exit_ena; wire state_ena;
⑤
不知道干什么用的,illgel_instr为0代表是协处理器指令,为1代表不是
wire nice_req_hsked;wire nice_rsp_hsked;wire nice_icb_rsp_hsked;wire illgel_instr = ~(custom_multi_cyc_op);wire lbuf_icb_rsp_hsked_last;wire sbuf_icb_rsp_hsked_last;wire rowsum_done;
四、功能
1、状态转换
①IDLE的次态选择
当指令为协处理器扩展的三条指令,则state_idle_nxt为相应的指令对应的状态,否则保持IDLE不变
assign state_idle_nxt = custom3_lbuf ? LBUF : custom3_sbuf ? SBUF :custom3_rowsum ? ROWSUM :IDLE;
②
三个指令状态的次态,都为IDLE
assign state_lbuf_nxt = IDLE;
assign state_sbuf_nxt = IDLE;
assign state_rowsum_nxt = IDLE;
③
给状态离开使能信号赋值
当现态为IDLE,并且(nice_req_hsked),并且当前为三指令之一,state_idle_exit_ena为高
assign state_idle_exit_ena = state_is_idle & nice_req_hsked & ~illgel_instr;
现态为lbuf,并且(lbuf_icb_rsp_hsked_last),state_lbuf_exit_ena为高
assign state_lbuf_exit_ena = state_is_lbuf & lbuf_icb_rsp_hsked_last;
现态为sbuf,并且(sbuf_icb_rsp_hsked_last),state_sbuf_exit_ena为高
assign state_sbuf_exit_ena = state_is_sbuf & sbuf_icb_rsp_hsked_last;
现态为rowsum,并且rowsum_done为高,state_rowsum_exit_ena为高
assign state_rowsum_exit_ena = state_is_rowsum & rowsum_done;
④次态赋值
当前状态的离开使能为高时,为其对应的次态,否则为2'b00即IDLE
assign nxt_state = ({NICE_FSM_WIDTH{state_idle_exit_ena }} & state_idle_nxt )| ({NICE_FSM_WIDTH{state_lbuf_exit_ena }} & state_lbuf_nxt ) | ({NICE_FSM_WIDTH{state_sbuf_exit_ena }} & state_sbuf_nxt ) | ({NICE_FSM_WIDTH{state_rowsum_exit_ena }} & state_rowsum_nxt ) ;
⑤
状态转换使能,为四个使能的或
assign state_ena = state_idle_exit_ena | state_lbuf_exit_ena | state_sbuf_exit_ena | state_rowsum_exit_ena;
⑥时序状态机
调用sirv_gnrl_dfflr,D触发器,实现状态机
sirv_gnrl_dfflr #(NICE_FSM_WIDTH) state_dfflr (state_ena, nxt_state, state_r, nice_clk, nice_rst_n);
2、一个lbuf的计数器
①信号定义
lbuf_cnt_r | 现在计数值 |
lbuf_cnt_nxt | 下一个计数值 |
lbuf_cnt_clr | 计数清零,使能 |
lbuf_cnt_incr | 计数增加,使能 |
lbuf_cnt_ena | 计数,D触发器,使能 |
lbuf_cnt_last | 计数到最后值 |
lbuf_icb_rsp_hsked | 状态机为lbuf,并且储存响应握手成功 |
nice_rsp_valid_lbuf | 状态机为lbuf,计数到最后值,E203发出储存响应信号 |
nice_icb_cmd_valid_lbuf | 状态机为lbuf,计数值小于最后值 |
②信号赋值
1)已知assign nice_icb_rsp_hsked = nice_icb_rsp_valid & nice_icb_rsp_ready;并且nice_icb_rsp_ready is 1'b1 always,所以nice_icb_rsp_hsked = nice_icb_rsp_valid
所以lbuf_icb_rsp_hsked,当前状态为lbuf,储存响应握手
2)lbuf_icb_rsp_hsked_last,当前状态为lbuf,储存响应握手,计数为最后值
3)lbuf_cnt_last即计数到最后值,也就是lbuf_cnt_r为clonum2‘b10
4)已知assign nice_req_hsked = nice_req_valid & nice_req_ready;
所以lbuf_cnt_clr含义为当前指令为lbuf,命令请求握手
5)lbuf_cnt_incr为当前状态为lbuf,储存响应握手,计数值不是最后值
6)lbuf_cnt_ena,当前指令为lbuf,命令请求握手;或者当前状态lbuf,储存指令握手,计数值不是最后值
7)当前指令lbuf,命令请求握手,lbuf_cnt_nxt归零;当前状态lbuf,储存响应握手,计数值不是最后值,lbuf_cnt_nxt为lbuf_cnt_r+1
8)nice_rsp_valid_lbuf,当前状态为lbuf,计数值为最后值,E203发出储存响应信号
9)nice_icb_cmd_valid_lbuf,当前状态为lbuf,且现计数值小于最后值
assign lbuf_icb_rsp_hsked = state_is_lbuf & nice_icb_rsp_hsked;assign lbuf_icb_rsp_hsked_last = lbuf_icb_rsp_hsked & lbuf_cnt_last;assign lbuf_cnt_last = (lbuf_cnt_r == clonum);assign lbuf_cnt_clr = custom3_lbuf & nice_req_hsked;assign lbuf_cnt_incr = lbuf_icb_rsp_hsked & ~lbuf_cnt_last;assign lbuf_cnt_ena = lbuf_cnt_clr | lbuf_cnt_incr;assign lbuf_cnt_nxt = ({ROWBUF_IDX_W{lbuf_cnt_clr }} & {ROWBUF_IDX_W{1'b0}})| ({ROWBUF_IDX_W{lbuf_cnt_incr}} & (lbuf_cnt_r + 1'b1) );// nice_rsp_valid wait for nice_icb_rsp_valid in LBUFassign nice_rsp_valid_lbuf = state_is_lbuf & lbuf_cnt_last & nice_icb_rsp_valid;// nice_icb_cmd_valid sets when lbuf_cnt_r is not full in LBUFassign nice_icb_cmd_valid_lbuf = (state_is_lbuf & (lbuf_cnt_r < clonum));
③D触发器构成时序计数器
时钟:nice_clk ; 复位信号:nice_rst_n ; 使能信号:lbuf_cnt_ena ;
输入数据lbuf_cnt_nxt ; 输出数据:lbuf_cnt_r
sirv_gnrl_dfflr #(ROWBUF_IDX_W) lbuf_cnt_dfflr (lbuf_cnt_ena, lbuf_cnt_nxt, lbuf_cnt_r, nice_clk, nice_rst_n);
3、sbuf计数器
①信号定义
sbuf_cnt_r | 当前计数值 |
subf_cnt_nxt | 下个计数值 |
sbuf_cnt_clr | sbuf_icb_rsp_hsked_last |
sbuf_cnt_incr | sbuf_cnt增加,使能 |
sbuf_cnt_ena | D触发器,使能 |
sbuf_cnt_last | 当前计数值为最后值 |
sbuf_icb_cmd_hsked | 当前状态为sbuf,或(状态为IDLE且指令为sbuf),储存握手成功 |
sbuf_icb_rsp_hsked | 当前状态为sbuf,储存响应握手成功 |
nice_rsp_valid_sbuf | 状态机为sbuf,计数到最后值,E203发出储存响应信号 |
nice_icb_cmd_valid_sbuf | 状态为sbuf,sbuf_cmd_cnt_r小于等于最后值,sbuf_cnt不是最后值 |
nice_icb_cmd_hsked | 储存请求握手成功 |
②信号赋值
1)sbuf_icb_cmd_hsked,当前状态为sbuf,或(idle状态指令为sbuf),储存请求握手成功
2)sbuf_icb_rsp_hsked,当前状态sbuf,储存响应握手
3)sbuf_icb_rsp_hsked_last,当前状态sbuf,储存响应握手,计数值为最后值
4)sbuf_cnt_last,计数值为最后值
5)sbuf_cnt_clr,就是sbuf_icb_rsp_hsked_last,当前状态sbuf,储存响应握手,计数值为最后值
6)sbuf_cnt_incr,当前状态sbuf,储存响应握手,计数值不是最后值
7)sbuf_cnt_ena,当前状态sbuf,储存响应握手
8)sbuf_cnt_nxt,当前状态sbuf,储存响应握手,(计数值为最后值则为2'b00;否则为现在计数值+1)
9)nice_rsp_valid_sbuf,当前状态sbuf,计数值为最后值,E203发出储存响应信号
assign sbuf_icb_cmd_hsked = (state_is_sbuf | (state_is_idle & custom3_sbuf)) & nice_icb_cmd_hsked;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;assign sbuf_cnt_last = (sbuf_cnt_r == clonum);//assign sbuf_cnt_clr = custom3_sbuf & nice_req_hsked;assign sbuf_cnt_clr = sbuf_icb_rsp_hsked_last;assign sbuf_cnt_incr = sbuf_icb_rsp_hsked & ~sbuf_cnt_last;assign sbuf_cnt_ena = sbuf_cnt_clr | sbuf_cnt_incr;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) );// nice_rsp_valid wait for nice_icb_rsp_valid in SBUFassign nice_rsp_valid_sbuf = state_is_sbuf & sbuf_cnt_last & nice_icb_rsp_valid;
③D触发器构成时序计数器
sirv_gnrl_dfflr #(ROWBUF_IDX_W) sbuf_cnt_dfflr (sbuf_cnt_ena, sbuf_cnt_nxt, sbuf_cnt_r, nice_clk, nice_rst_n);
4、sbuf_cmd计数器
①信号定义
sbuf_cmd_cnt_r | sbuf_cmd现计数值 |
sbuf_cmd_cnt_nxt | sbuf_cmd下个计数值 |
sbuf_cmd_cnt_clr | 当前状态sbuf,储存响应握手,sbuf计数值为最后值 |
sbuf_cmd_cnt_incr | 当前状态为sbuf,或(idle状态指令为sbuf),储存请求握手成功,subf_cmd计数值不是最后值 |
sbuf_cmd_cnt_ena | (当前状态sbuf,储存响应握手,sbuf计数值为最后值)或(当前状态为sbuf,或(idle状态指令为sbuf),储存请求握手成功,subf_cmd计数值不是最后值) |
sbuf_cmd_cnt_last | sbuf_cmd计数值为最后值 |
②信号赋值
1)sbuf_cmd_cnt_last,sbuf_cmd计数值为最后值
2)sbuf_cmd_cnt_clr,当前状态sbuf,储存响应握手,sbuf计数值为最后值
3)sbuf_cmd_cnt_incr,当前状态为sbuf,或(idle状态指令为sbuf),储存请求握手成功,subf_cmd计数值不是最后值
4)sbuf_cmd_cnt_ena,(当前状态sbuf,储存响应握手,sbuf计数值为最后值)或(当前状态为sbuf,或(idle状态指令为sbuf),储存请求握手成功,subf_cmd计数值不是最后值)
5)sbuf_cmd_cnt_nxt,当前状态sbuf,储存响应握手,sbuf计数为最后值,为2'b00;当前状态为sbuf,或(idle状态指令为sbuf),储存请求握手成功,sbuf_cmd计数值不是最后值,为sbuf_cmd_cnt_r+1
6)nice_icb_cmd_valid_sbuf,当前状态sbuf,sbuf_cmd小于等于最后值,sbuf不等于最后值
assign sbuf_cmd_cnt_last = (sbuf_cmd_cnt_r == clonum);assign sbuf_cmd_cnt_clr = sbuf_icb_rsp_hsked_last;assign sbuf_cmd_cnt_incr = sbuf_icb_cmd_hsked & ~sbuf_cmd_cnt_last;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) );// nice_icb_cmd_valid sets when sbuf_cmd_cnt_r is not full in SBUFassign nice_icb_cmd_valid_sbuf = (state_is_sbuf & (sbuf_cmd_cnt_r <= clonum) & (sbuf_cnt_r != clonum));
③D触发器构成时序计数器
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);
5、rowsum的rowbuf counter
①信号定义
wire [ROWBUF_IDX_W-1:0] rowbuf_cnt_r; wire [ROWBUF_IDX_W-1:0] rowbuf_cnt_nxt; wire rowbuf_cnt_clr;wire rowbuf_cnt_incr;wire rowbuf_cnt_ena;wire rowbuf_cnt_last;wire rowbuf_icb_rsp_hsked;wire rowbuf_rsp_hsked;wire nice_rsp_valid_rowsum;
②信号赋值
assign rowbuf_rsp_hsked = nice_rsp_valid_rowsum & nice_rsp_ready;assign rowbuf_icb_rsp_hsked = state_is_rowsum & nice_icb_rsp_hsked;assign rowbuf_cnt_last = (rowbuf_cnt_r == clonum);assign rowbuf_cnt_clr = rowbuf_icb_rsp_hsked & rowbuf_cnt_last;assign rowbuf_cnt_incr = rowbuf_icb_rsp_hsked & ~rowbuf_cnt_last;assign rowbuf_cnt_ena = rowbuf_cnt_clr | rowbuf_cnt_incr;assign rowbuf_cnt_nxt = ({ROWBUF_IDX_W{rowbuf_cnt_clr }} & {ROWBUF_IDX_W{1'b0}})| ({ROWBUF_IDX_W{rowbuf_cnt_incr}} & (rowbuf_cnt_r + 1'b1));
③D触发器构成时序计数器
sirv_gnrl_dfflr #(ROWBUF_IDX_W) rowbuf_cnt_dfflr (rowbuf_cnt_ena, rowbuf_cnt_nxt, rowbuf_cnt_r, nice_clk, nice_rst_n);
6、rowsum的recieve data buffer
①信号定义
wire rcv_data_buf_ena;wire rcv_data_buf_set;wire rcv_data_buf_clr;wire rcv_data_buf_valid;wire [`E203_XLEN-1:0] rcv_data_buf; wire [ROWBUF_IDX_W-1:0] rcv_data_buf_idx; wire [ROWBUF_IDX_W-1:0] rcv_data_buf_idx_nxt;
②信号赋值
assign rcv_data_buf_set = rowbuf_icb_rsp_hsked;assign rcv_data_buf_clr = rowbuf_rsp_hsked;assign rcv_data_buf_ena = rcv_data_buf_clr | rcv_data_buf_set;assign rcv_data_buf_idx_nxt = ({ROWBUF_IDX_W{rcv_data_buf_clr}} & {ROWBUF_IDX_W{1'b0}})| ({ROWBUF_IDX_W{rcv_data_buf_set}} & rowbuf_cnt_r );
③D触发器构成时序计数器
第一个是使能信号的一个时钟延迟
第二个是输入数据的缓冲
第三个是对rowbuf写入的序号
sirv_gnrl_dfflr #(1) rcv_data_buf_valid_dfflr (1'b1, rcv_data_buf_ena, rcv_data_buf_valid, nice_clk, nice_rst_n);sirv_gnrl_dfflr #(`E203_XLEN) rcv_data_buf_dfflr (rcv_data_buf_ena, nice_icb_rsp_rdata, rcv_data_buf, nice_clk, nice_rst_n);sirv_gnrl_dfflr #(ROWBUF_IDX_W) rowbuf_cnt_d_dfflr (rcv_data_buf_ena, rcv_data_buf_idx_nxt, rcv_data_buf_idx, nice_clk, nice_rst_n);
7、rowsum的累加
①信号定义
wire [`E203_XLEN-1:0] rowsum_acc_r;wire [`E203_XLEN-1:0] rowsum_acc_nxt;wire [`E203_XLEN-1:0] rowsum_acc_adder;wire rowsum_acc_ena;wire rowsum_acc_set;wire rowsum_acc_flg;wire nice_icb_cmd_valid_rowsum;wire [`E203_XLEN-1:0] rowsum_res;
②信号赋值
2)rowsum_acc_flg,rcv_data_buf_idx非零,且上个周期的状态为rowsum时(储存响应握手或E203发出nice_rsp_ready信号)
assign rowsum_acc_set = rcv_data_buf_valid & (rcv_data_buf_idx == {ROWBUF_IDX_W{1'b0}});assign rowsum_acc_flg = rcv_data_buf_valid & (rcv_data_buf_idx != {ROWBUF_IDX_W{1'b0}});assign rowsum_acc_adder = rcv_data_buf + rowsum_acc_r;assign rowsum_acc_ena = rowsum_acc_set | rowsum_acc_flg;assign rowsum_acc_nxt = ({`E203_XLEN{rowsum_acc_set}} & rcv_data_buf)| ({`E203_XLEN{rowsum_acc_flg}} & rowsum_acc_adder);assign rowsum_done = state_is_rowsum & nice_rsp_hsked;assign rowsum_res = rowsum_acc_r;// rowsum finishes when the last acc data is added to rowsum_acc_r assign nice_rsp_valid_rowsum = state_is_rowsum & (rcv_data_buf_idx == clonum) & ~rowsum_acc_flg;// nice_icb_cmd_valid sets when rcv_data_buf_idx is not full in LBUFassign nice_icb_cmd_valid_rowsum = state_is_rowsum & (rcv_data_buf_idx < clonum) & ~rowsum_acc_flg;
③D触发器构成时序
累加的时序操作
sirv_gnrl_dfflr #(`E203_XLEN) rowsum_acc_dfflr (rowsum_acc_ena, rowsum_acc_nxt, rowsum_acc_r, nice_clk, nice_rst_n);
8、rowbuf
rowbuf是数据缓存,lbuf和rowsum会写入,sbuf会读出
①信号定义
rowbuf_r | 4个32位的数据 |
rowbuf_wdata | 4个32位的数据 |
rowbuf_we | 4位宽的数据 |
rowbuf_idx_mux | rowbuf的序号选择 |
rowbuf_wdata_mux | rowbuf的写入数据选择 |
rowbuf_wr_mux | rowbuf的写入信号选择 |
lbuf_dix | lbuf写入的序号 |
lbuf_wr | lbuf写入的使能 |
lbuf_wdata | lbuf写入的数据 |
rowsum_idx | rowsum写入的序号 |
rcv_data_buf_valid | rowsum写入的使能 |
rowsum_wdata | rowsum写入的数据 |
②信号赋值
写入的选择
1)lbuf_idx,写入序号选择,为lbuf_cnt_r,即lbuf计数的时序输出,当前的计数值,从0到2
2)lbuf_wr,写入使能,为lbuf_icb_rsp_hsked,即当前状态为lbuf,储存响应握手
3)lbuf_wdata,写入数据,外部输入的从memory读取的数据
4)rowsum_dix,写入序号选择,为rcv_data_buf_idx,当前的计数值,从0到2
5)rowsum_wr,写入使能,为rcv_data_buf-valid,是rcv_data_buf_ena缓冲一个时钟
6)rowsum_wdata,写入数据,为rowbuf_r当前数据与rcv_data_buf的加和
7)rowbuf_idx_mux,写入序号选择,若lbuf_wr为高,则为luf_idx,若rowsum_wr为高,则为rowsum_dix
8)rowbuf_wr_mux,写入使能选择,lbuf_wr与rowsum_wr的或
9)rowbuf_wdat_mux,写入数据选择
// lbuf write to rowbufwire [ROWBUF_IDX_W-1:0] lbuf_idx = lbuf_cnt_r; wire lbuf_wr = lbuf_icb_rsp_hsked; wire [`E203_XLEN-1:0] lbuf_wdata = nice_icb_rsp_rdata;// rowsum write to rowbuf(column accumulated data)wire [ROWBUF_IDX_W-1:0] rowsum_idx = rcv_data_buf_idx; wire rowsum_wr = rcv_data_buf_valid; wire [`E203_XLEN-1:0] rowsum_wdata = rowbuf_r[rowsum_idx] + rcv_data_buf; // rowbuf write muxassign 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);
③D触发器构成时序
实例化4个32位的D触发器
1)rowbuf_we为使能信号,为rowbuf_wr_mux与一个表达式的与,i的低2位与rowbuf_idx_mux相等才可以
2)rowbuf_wdat为输入数据,使能时为rowbuf_wdat_mux
// rowbuf instgenvar i;generate for (i=0; i<ROWBUF_DP; i=i+1) begin:gen_rowbufassign rowbuf_we[i] = (rowbuf_wr_mux & (rowbuf_idx_mux == i[ROWBUF_IDX_W-1:0]));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);endendgenerate
9、memory的地址
①信号说明
nice_icb_cmd_hsked | 储存请求握手 |
lbuf_maddr_ena | lbuf,访问memory的使能 |
sbuf_maddr_ena | sbuf,访问memory的使能 |
rowsum_maddr_ena | rowsum,访问memory的使能 |
maddr_ena | 访问memory的使能 |
maddr_ena_dile | 访问memory的使能,且当前状态为idle |
maddr_acc_op1 | 操作数1 |
maddr_acc_op2 | 操作数2 |
maddr_acc_ena | 访问memory的使能 |
1)nice_icb_cmd_hsked,储存请求握手②信号赋值
2)lbuf_maddr_ena,(当前状态为idle,命令为lbuf,并且储存请求握手)或(当前状态lbuf,储存请求握手)
3)sbuf_maddr_ena,(当前状态为idle,命令为sbuf,并且储存请求握手)或(当前状态sbuf,储存请求握手)
4)rowsum_maddr_ena,(当前状态为idle,命令为rowsum,并且储存请求握手)或(当前状态rowsum,储存请求握手)
5)maddr_ena,(当前状态为idle,命令有效,并且储存请求握手)或(当前状态非idle,储存请求握手)
6)maddr_ena_idle,当前状态为idle,命令为有效,并且储存请求握手
7)maddr_acc_op1,当前状态为idle,命令为有效,并且储存请求握手,为寄存器1值,否则为maddr_acc_r
8)maddr_acc_op2,32/8 = 4,所以每次要加4
9)maddr_acc_next,下一个地址,为当前地址+4
10)maddr_acc_ena,为(当前状态为idle,命令有效,并且储存请求握手)或(当前状态非idle,储存请求握手)
assign nice_icb_cmd_hsked = nice_icb_cmd_valid & nice_icb_cmd_ready; // custom3_lbuf //wire [`E203_XLEN-1:0] lbuf_maddr = state_is_idle ? nice_req_rs1 : maddr_acc_r ; wire lbuf_maddr_ena = (state_is_idle & custom3_lbuf & nice_icb_cmd_hsked)| (state_is_lbuf & nice_icb_cmd_hsked);// custom3_sbuf //wire [`E203_XLEN-1:0] sbuf_maddr = state_is_idle ? nice_req_rs1 : maddr_acc_r ; wire sbuf_maddr_ena = (state_is_idle & custom3_sbuf & nice_icb_cmd_hsked)| (state_is_sbuf & nice_icb_cmd_hsked);// custom3_rowsum//wire [`E203_XLEN-1:0] rowsum_maddr = state_is_idle ? nice_req_rs1 : maddr_acc_r ; wire rowsum_maddr_ena = (state_is_idle & custom3_rowsum & nice_icb_cmd_hsked)| (state_is_rowsum & nice_icb_cmd_hsked);// maddr acc //wire maddr_incr = lbuf_maddr_ena | sbuf_maddr_ena | rowsum_maddr_ena | rbuf_maddr_ena;wire maddr_ena = lbuf_maddr_ena | sbuf_maddr_ena | rowsum_maddr_ena;wire maddr_ena_idle = maddr_ena & state_is_idle;wire [`E203_XLEN-1:0] maddr_acc_op1 = maddr_ena_idle ? nice_req_rs1 : maddr_acc_r; // not reusedwire [`E203_XLEN-1:0] maddr_acc_op2 = maddr_ena_idle ? `E203_XLEN'h4 : `E203_XLEN'h4; wire [`E203_XLEN-1:0] maddr_acc_next = maddr_acc_op1 + maddr_acc_op2;wire maddr_acc_ena = maddr_ena;
③ D触发器
使能信号:maddr_acc_ena,输入数据:maddr_acc_next,输出:maddr_acc_r
sirv_gnrl_dfflr #(`E203_XLEN) maddr_acc_dfflr (maddr_acc_ena, maddr_acc_next, maddr_acc_r, nice_clk, nice_rst_n);
10、请求响应的信号
1)nice_req_hsked,命令请求握手
2)nice_req_ready,nice发出的命令请求握手信号,当前状态是idle,且指令有效,则为nice_icb_cmd_ready,否则为1'b1
3)nice_rsp_hsked,命令响应握手
4)nice_icb_rsp_hsked,储存响应握手
5)nice_rsp_valid,(当前状态lbuf,lbuf计数值为最后值,E203发出储存响应信号)或(当前状态sbuf,sbuf计数值为最后值,E203发出储存响应信号)或(当前状态rowsum,rcv_data_buf_idx计数值为最后值,rowsum_acc_flg为低)或(rcv_data_buf_idx非零,且上个周期的状态为rowsum时(储存响应握手或E203发出nice_rsp_ready信号))
6)nice_rsp_rdat,当前状态为rowsum时为rowsum_res
7)nice_rsp_err,储存响应握手且在访问memory时出错
// Control cmd_reqassign nice_req_hsked = nice_req_valid & nice_req_ready;assign nice_req_ready = state_is_idle & (custom_mem_op ? nice_icb_cmd_ready : 1'b1);// Control cmd_rspassign nice_rsp_hsked = nice_rsp_valid & nice_rsp_ready; assign nice_icb_rsp_hsked = nice_icb_rsp_valid & nice_icb_rsp_ready;assign nice_rsp_valid = nice_rsp_valid_rowsum | nice_rsp_valid_sbuf | nice_rsp_valid_lbuf;assign nice_rsp_rdat = {`E203_XLEN{state_is_rowsum}} & rowsum_res;// memory access bus error//assign nice_rsp_err_irq = (nice_icb_rsp_hsked & nice_icb_rsp_err)// | (nice_req_hsked & illgel_instr)// ; assign nice_rsp_err = (nice_icb_rsp_hsked & nice_icb_rsp_err);
11、memory相关
1)nice_icb_rsp_ready始终为1'b1
2)sbuf_idx为subf_cmd_cnt_r
3)nice_icb_cmd_valid,(当前状态为idle且E203发出nice_req_valid且指令有效)或(状态lbuf,lbuf计数值小于最后值)或(状态sbuf,sbuf_cmd小于等于最后值且sbuf计数值不是最后值)或(状态rowsum,rcv_data_buf计数值小于最后值,且(rcv_data_buf_idx非零,且上个周期的状态为rowsum时(储存响应握手或E203发出nice_rsp_ready信号))
4)nice_icb_cmd_addr,(状态idle且命令有效)为寄存器1,否则为maddr_acc_r
5)nice_icb_cmd_read,(状态idle且为lbuf或rowsumz指令,为1,为sbuf指令,为0),或者为sbuf状态为0,否则为1
6)nice_icb_cmd_wdata,(状态idle,sbuf指令)或subf状态,为rowbuf_r[sbuf_idx],否则为0
7)nice_icb_cmd_size,为2,代表4字节32位宽数据
8)nice_mem_holdup,为非idle状态,访问memory锁
// rsp always readyassign nice_icb_rsp_ready = 1'b1; wire [ROWBUF_IDX_W-1:0] sbuf_idx = sbuf_cmd_cnt_r; assign nice_icb_cmd_valid = (state_is_idle & nice_req_valid & custom_mem_op)| nice_icb_cmd_valid_lbuf| nice_icb_cmd_valid_sbuf| nice_icb_cmd_valid_rowsum;assign nice_icb_cmd_addr = (state_is_idle & custom_mem_op) ? nice_req_rs1 :maddr_acc_r;assign nice_icb_cmd_read = (state_is_idle & custom_mem_op) ? (custom3_lbuf | custom3_rowsum) : state_is_sbuf ? 1'b0 : 1'b1;assign nice_icb_cmd_wdata = (state_is_idle & custom3_sbuf) ? rowbuf_r[sbuf_idx] :state_is_sbuf ? rowbuf_r[sbuf_idx] : `E203_XLEN'b0; //assign nice_icb_cmd_wmask = {`sirv_XLEN_MW{custom3_sbuf}} & 4'b1111;assign nice_icb_cmd_size = 2'b10;assign nice_mem_holdup = state_is_lbuf | state_is_sbuf | state_is_rowsum;
NICE的Verilog代码相关推荐
- Verilog代码规范I
Verilog代码规范I "规范"这问题 "规范"这个富含专业气息的词汇(个人感觉),其实规范这种东西,就是大家都约定熟成的东西,一旦你不遵守这个东西,专业人士 ...
- FPGA学习之路—应用程序—原码二位乘法器及Verilog代码分析
FPGA学习之路--原码二位乘法器及Verilog代码分析 原理 原码乘法可以分为原码一位乘和原码二位乘,两者在实现规则上大同小异.原码一位乘每次判断乘数的最低位,对被乘数和部分积进行相应操作.而原码 ...
- 网页版的svn怎样同步代码_学会使用Hdlbits网页版Verilog代码仿真验证平台
大家推荐一款网页版的 Verilog代码编辑仿真验证平台,这个平台是国外的一家开源FPGA学习网站,通过 "https://hdlbits.01xz.net/wiki/Main_Page&q ...
- (67)FPGA面试题-为priority encoder编写Verilog代码,实现MUX4_1
1.1 FPGA面试题-为priority encoder编写Verilog代码,实现MUX4_1 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA面试题-为pr ...
- (66)FPGA面试题-为parallel encoder编写Verilog代码,实现MUX4_1
1.1 FPGA面试题-为parallel encoder编写Verilog代码,实现MUX4_1 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA面试题-为pa ...
- 4位7段共阴数码管动态显示的verilog代码
4位7段共阴数码管动态显示的verilog代码 sn_data为输入的显示数值 clk接100MHz时钟 s为数码管位选信号,高电平有效 seg为7段共阴极数码管输出 `timescale 1ns / ...
- 基于多相滤波器的数字信道化算法详解(Python, Verilog代码已开源)
基于多相滤波器的数字信道化算法详解 推导过程 总结 仿真 本文详细介绍了基于多相滤波器的数字信道化算法的推导过程, 如果您在阅读的过程中发现算法推导过程中有任何错误, 请不吝指出. 此外, 进入我的G ...
- 异步FIFO设计:各个模块的作用及Verilog代码详解
实现原理参考:异步FIFO---Verilog实现_alangaixiaoxiao的博客-CSDN博客_异步fifo 代码参考:IC基础(一):异步FIFO_MaoChuangAn的博客-CSDN博客 ...
- 异步FIFO的原理以及可综合的Verilog代码
异步FIFO的原理以及可综合的Verilog代码 一.FIFO的定义 二.FIFO的应用场景 三.FIFO的分类 FIFO的参数 FIFO的设计难点 一.FIFO的定义 _ First In Firs ...
- 异步FIFO的verilog代码实现(包含将满和将空逻辑)
目录 异步FIFO的verilog代码实现(包含将满和将空逻辑) 异步FIFO简介 异步FIFO关键技术1 -- 读写信号跨时钟域同步 异步FIFO关键技术2 -- 读写地址的比较 异步FIFO关键技 ...
最新文章
- HSSFWorkbook 与 XSSFWorkbook
- Tornado 学习笔记
- git 基本命令记录
- PHP面试题:PHP加速模式/扩展? PHP调试模式/工具?
- 如何在SAP Spartacus里监控用户浏览了某产品明细页面的动作
- C/C++ ini配置文件的格式及如何读写ini配置文件
- 一百馒头一百僧,大僧三个更无争,小僧三人分一个大小和尚得几丁?
- oracle 11g 组合分区,Oracle数据库
- ubuntu17安装mysql后数据库乱码_linux安装MySQL数据库,设置编码为utf8
- mysql 常用操作(整理)
- 190227每日一句
- raw数据恢复之raw格式硬盘如何恢复数据?
- RHEL7的安装步骤
- Telink BDT 的使用方法
- c语言学习笔记(7)单引号,双引号和逻辑符号的用法
- 【NGUI】实现半圆形进度条,技能CD效果
- 教你如何拍好人像摄影
- java拼图游戏ai_拼图游戏和它的AI算法
- 怎样一键比较2个CAD图纸文件的不同呢?
- 软件测试助理利弊,女生做软件测试的利弊都有什么?