// Copyright 2018 ETH Zurich and University of Bologna. // Copyright and related rights are licensed under the Solderpad Hardware // License, Version 0.51 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law // or agreed to in writing, software, hardware and materials distributed under // this 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. // // Author: Florian Zaruba, ETH Zurich // Date: 05.05.2017 // Description: Buffer to hold CSR address, this acts like a functional unit // to the scoreboard. module csr_buffer import ariane_pkg::*; #( parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, parameter type fu_data_t = logic ) ( // Subsystem Clock - SUBSYSTEM input logic clk_i, // Asynchronous reset active low - SUBSYSTEM input logic rst_ni, // Flush CSR - CONTROLLER input logic flush_i, // FU data needed to execute instruction - ISSUE_STAGE input fu_data_t fu_data_i, // CSR FU is ready - ISSUE_STAGE output logic csr_ready_o, // CSR instruction is valid - ISSUE_STAGE input logic csr_valid_i, // CSR buffer result - ISSUE_STAGE output logic [CVA6Cfg.XLEN-1:0] csr_result_o, // commit the pending CSR OP - TO_BE_COMPLETED input logic csr_commit_i, // CSR address to write - COMMIT_STAGE output logic [11:0] csr_addr_o ); // this is a single entry store buffer for the address of the CSR // which we are going to need in the commit stage struct packed { logic [11:0] csr_address; logic valid; } csr_reg_n, csr_reg_q; // control logic, scoreboard signals assign csr_result_o = fu_data_i.operand_a; assign csr_addr_o = csr_reg_q.csr_address; // write logic always_comb begin : write csr_reg_n = csr_reg_q; // by default we are ready csr_ready_o = 1'b1; // if we have a valid uncomiited csr req or are just getting one WITHOUT a commit in, we are not ready if ((csr_reg_q.valid || csr_valid_i) && ~csr_commit_i) csr_ready_o = 1'b0; // if we got a valid from the scoreboard // store the CSR address if (csr_valid_i) begin csr_reg_n.csr_address = fu_data_i.operand_b[11:0]; csr_reg_n.valid = 1'b1; end // if we get a commit and no new valid instruction -> clear the valid bit if (csr_commit_i && ~csr_valid_i) begin csr_reg_n.valid = 1'b0; end // clear the buffer if we flushed if (flush_i) csr_reg_n.valid = 1'b0; end // sequential process always_ff @(posedge clk_i or negedge rst_ni) begin if (~rst_ni) begin csr_reg_q <= '{default: 0}; end else begin csr_reg_q <= csr_reg_n; end end endmodule