| // Copyright 2025 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| module RvvCore #(parameter N = 4, |
| parameter CMD_BUFFER_MAX_CAPACITY = 16, |
| type RegDataT=logic [31:0], |
| type VRegDataT=logic [127:0], |
| type RegAddrT=logic [4:0], |
| type MaskT=logic [15:0] |
| ) |
| ( |
| input clk, |
| input rstn, |
| |
| input logic [`VSTART_WIDTH-1:0] vstart, |
| input logic [1:0] vxrm, |
| input logic vxsat, |
| |
| // Instruction input. |
| input logic [N-1:0] inst_valid, |
| input RVVInstruction [N-1:0] inst_data, |
| output logic [N-1:0] inst_ready, |
| |
| // Register file input |
| input logic [(2*N)-1:0] reg_read_valid, |
| input RegDataT [(2*N)-1:0] reg_read_data, |
| |
| // Scalar Regfile writeback for configuration functions. |
| output logic [N-1:0] reg_write_valid, |
| output RegAddrT [N-1:0] reg_write_addr, |
| output RegDataT [N-1:0] reg_write_data, |
| |
| // Scalar Regfile writeback for non-configuration functions. |
| output logic async_rd_valid, |
| output RegAddrT async_rd_addr, |
| output RegDataT async_rd_data, |
| input logic async_rd_ready, |
| |
| // RVV to LSU |
| output logic [`NUM_LSU-1:0] uop_lsu_valid_rvv2lsu, |
| output logic [`NUM_LSU-1:0] uop_lsu_idx_valid_rvv2lsu, |
| output RegAddrT [`NUM_LSU-1:0] uop_lsu_idx_addr_rvv2lsu, |
| output VRegDataT [`NUM_LSU-1:0] uop_lsu_idx_data_rvv2lsu, |
| output logic [`NUM_LSU-1:0] uop_lsu_vregfile_valid_rvv2lsu, |
| output RegAddrT [`NUM_LSU-1:0] uop_lsu_vregfile_addr_rvv2lsu, |
| output VRegDataT [`NUM_LSU-1:0] uop_lsu_vregfile_data_rvv2lsu, |
| output logic [`NUM_LSU-1:0] uop_lsu_v0_valid_rvv2lsu, |
| output MaskT [`NUM_LSU-1:0] uop_lsu_v0_data_rvv2lsu, |
| input logic [`NUM_LSU-1:0] uop_lsu_ready_lsu2rvv, |
| |
| // LSU to RVV |
| input logic [`NUM_LSU-1:0] uop_lsu_valid_lsu2rvv, |
| input RegAddrT [`NUM_LSU-1:0] uop_lsu_addr_lsu2rvv, |
| input VRegDataT [`NUM_LSU-1:0] uop_lsu_wdata_lsu2rvv, |
| input logic [`NUM_LSU-1:0] uop_lsu_last_lsu2rvv, |
| output logic [`NUM_LSU-1:0] uop_lsu_ready_rvv2lsu, |
| |
| // Vector CSR writeback |
| output vcsr_valid, |
| output RVVConfigState vector_csr, |
| input vcsr_ready, |
| |
| // Config state |
| output config_state_valid, |
| output RVVConfigState config_state, |
| |
| // Idle |
| output logic rvv_idle |
| ); |
| logic [N-1:0] frontend_cmd_valid; |
| RVVCmd [N-1:0] frontend_cmd_data; |
| logic [$clog2(2*N + 1)-1:0] queue_capacity; |
| RvvFrontEnd#(.N(N)) frontend( |
| .clk(clk), |
| .rstn(rstn), |
| .vstart_i(vstart), |
| .vxrm_i(vxrm), |
| .vxsat_i(vxsat), |
| .inst_valid_i(inst_valid), |
| .inst_data_i(inst_data), |
| .inst_ready_o(inst_ready), |
| .reg_read_valid_i(reg_read_valid), |
| .reg_read_data_i(reg_read_data), |
| .reg_write_valid_o(reg_write_valid), |
| .reg_write_addr_o(reg_write_addr), |
| .reg_write_data_o(reg_write_data), |
| .cmd_valid_o(frontend_cmd_valid), |
| .cmd_data_o(frontend_cmd_data), |
| .queue_capacity_i(queue_capacity), |
| .config_state_valid(config_state_valid), |
| .config_state(config_state) |
| ); |
| |
| // Backpressure from backend fifo |
| logic [$clog2(`CQ_DEPTH):0] remaining_count_cq2rvs; |
| // Back-pressure frontend |
| always_comb begin |
| if (remaining_count_cq2rvs > 2*N) begin |
| queue_capacity = 2*N; |
| end else begin |
| queue_capacity = remaining_count_cq2rvs; |
| end |
| end |
| |
| // Back-end ============================================================ |
| |
| // LSU Tie-offs |
| // RVV send LSU uop to RVS |
| UOP_RVV2LSU_t [`NUM_LSU-1:0] uop_lsu_rvv2lsu; |
| always_comb begin |
| for (int i = 0; i < `NUM_LSU; i++) begin |
| uop_lsu_idx_valid_rvv2lsu[i] = uop_lsu_rvv2lsu[i].vidx_valid; |
| uop_lsu_idx_addr_rvv2lsu[i] = uop_lsu_rvv2lsu[i].vidx_addr; |
| uop_lsu_idx_data_rvv2lsu[i] = uop_lsu_rvv2lsu[i].vidx_data; |
| uop_lsu_vregfile_valid_rvv2lsu[i] = uop_lsu_rvv2lsu[i].vregfile_read_valid; |
| uop_lsu_vregfile_addr_rvv2lsu[i] = uop_lsu_rvv2lsu[i].vregfile_read_addr; |
| uop_lsu_vregfile_data_rvv2lsu[i] = uop_lsu_rvv2lsu[i].vregfile_read_data; |
| uop_lsu_v0_valid_rvv2lsu[i] = uop_lsu_rvv2lsu[i].v0_valid; |
| uop_lsu_v0_data_rvv2lsu[i] = uop_lsu_rvv2lsu[i].v0_data; |
| end |
| end |
| |
| // LSU feedback to RVV |
| UOP_LSU2RVV_t [`NUM_LSU-1:0] uop_lsu_lsu2rvv; |
| always_comb begin |
| `ifdef TB_SUPPORT |
| uop_lsu_lsu2rvv[i].uop_pc = 0; |
| uop_lsu_lsu2rvv[i].uop_index = 0; |
| `endif |
| for (int i = 0; i < `NUM_LSU; i++) begin |
| // TODO(derekjchow): Modify me |
| uop_lsu_lsu2rvv[i].vregfile_write_valid = ( |
| uop_lsu_valid_lsu2rvv[i] && !uop_lsu_last_lsu2rvv[i]); |
| uop_lsu_lsu2rvv[i].vregfile_write_addr = uop_lsu_addr_lsu2rvv[i]; |
| uop_lsu_lsu2rvv[i].vregfile_write_data = uop_lsu_wdata_lsu2rvv[i]; |
| uop_lsu_lsu2rvv[i].lsu_vstore_last = ( |
| uop_lsu_valid_lsu2rvv[i] && uop_lsu_last_lsu2rvv[i]); |
| end |
| end |
| |
| // Scalar regfile write-back tie-offs |
| // TODO(derekjchow): Properly arbitrate write-back tie-offs by extending |
| // interface. For time being, only accept from slot 0. |
| logic [`NUM_RT_UOP-1:0] rt_xrf_valid_rvv2rvs; |
| RT2XRF_t [`NUM_RT_UOP-1:0] rt_xrf_rvv2rvs; |
| logic [`NUM_RT_UOP-1:0] rt_xrf_ready_rvs2rvv; |
| always_comb begin |
| rt_xrf_ready_rvs2rvv[0] = async_rd_ready; |
| async_rd_valid = rt_xrf_valid_rvv2rvs[0]; |
| async_rd_addr = rt_xrf_rvv2rvs[0].rt_index; |
| async_rd_data = rt_xrf_rvv2rvs[0].rt_data; |
| for (int i = 1; i < `NUM_RT_UOP; i++) begin |
| rt_xrf_ready_rvs2rvv[i] = 0; |
| end |
| end |
| |
| // Backpressure |
| logic wr_vxsat_ready; |
| always_comb begin |
| // TODO(derekjchow): Actually accept |
| wr_vxsat_ready = 1; |
| end |
| |
| // CSR Update, unused for now |
| logic wr_vxsat_valid; |
| logic [`VCSR_VXSAT_WIDTH-1:0] wr_vxsat; |
| |
| // Trap handling tie-off |
| logic trap_valid_rvs2rvv; |
| logic trap_ready_rvv2rvs; |
| always_comb begin |
| trap_valid_rvs2rvv = 0; |
| end |
| |
| logic [`ISSUE_LANE-1:0] insts_ready_cq2rvs; |
| rvv_backend backend( |
| .clk(clk), |
| .rst_n(rstn), |
| .insts_valid_rvs2cq(frontend_cmd_valid), |
| .insts_rvs2cq(frontend_cmd_data), |
| .insts_ready_cq2rvs(insts_ready_cq2rvs), |
| .remaining_count_cq2rvs(remaining_count_cq2rvs), |
| |
| .uop_lsu_valid_rvv2lsu(uop_lsu_valid_rvv2lsu), |
| .uop_lsu_rvv2lsu(uop_lsu_rvv2lsu), |
| .uop_lsu_ready_lsu2rvv(uop_lsu_ready_lsu2rvv), |
| |
| .uop_lsu_valid_lsu2rvv(uop_lsu_valid_lsu2rvv), |
| .uop_lsu_lsu2rvv(uop_lsu_lsu2rvv), |
| .uop_lsu_ready_rvv2lsu(uop_lsu_ready_rvv2lsu), |
| |
| .rt_xrf_rvv2rvs(rt_xrf_rvv2rvs), |
| .rt_xrf_valid_rvv2rvs(rt_xrf_valid_rvv2rvs), |
| .rt_xrf_ready_rvs2rvv(rt_xrf_ready_rvs2rvv), |
| .wr_vxsat_valid(wr_vxsat_valid), |
| .wr_vxsat(wr_vxsat), |
| .wr_vxsat_ready(wr_vxsat_ready), |
| .trap_valid_rvs2rvv(trap_valid_rvs2rvv), |
| .trap_ready_rvv2rvs(trap_ready_rvv2rvs), |
| .vcsr_valid(vcsr_valid), |
| .vector_csr(vector_csr), |
| .vcsr_ready(vcsr_ready), |
| .rvv_idle(rvv_idle) |
| ); |
| |
| endmodule |