|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | // | 
|  | // Write enable and data arbitration logic for register slice conforming to Comportibility guide. | 
|  |  | 
|  | module prim_subreg_arb #( | 
|  | parameter int DW       = 32  , | 
|  | parameter     SWACCESS = "RW"  // {RW, RO, WO, W1C, W1S, W0C, RC} | 
|  | ) ( | 
|  | // From SW: valid for RW, WO, W1C, W1S, W0C, RC. | 
|  | // In case of RC, top connects read pulse to we. | 
|  | input          we, | 
|  | input [DW-1:0] wd, | 
|  |  | 
|  | // From HW: valid for HRW, HWO. | 
|  | input          de, | 
|  | input [DW-1:0] d, | 
|  |  | 
|  | // From register: actual reg value. | 
|  | input [DW-1:0] q, | 
|  |  | 
|  | // To register: actual write enable and write data. | 
|  | output logic          wr_en, | 
|  | output logic [DW-1:0] wr_data | 
|  | ); | 
|  |  | 
|  | if ((SWACCESS == "RW") || (SWACCESS == "WO")) begin : gen_w | 
|  | assign wr_en   = we | de; | 
|  | assign wr_data = (we == 1'b1) ? wd : d; // SW higher priority | 
|  | // Unused q - Prevent lint errors. | 
|  | logic [DW-1:0] unused_q; | 
|  | assign unused_q = q; | 
|  | end else if (SWACCESS == "RO") begin : gen_ro | 
|  | assign wr_en   = de; | 
|  | assign wr_data = d; | 
|  | // Unused we, wd, q - Prevent lint errors. | 
|  | logic          unused_we; | 
|  | logic [DW-1:0] unused_wd; | 
|  | logic [DW-1:0] unused_q; | 
|  | assign unused_we = we; | 
|  | assign unused_wd = wd; | 
|  | assign unused_q  = q; | 
|  | end else if (SWACCESS == "W1S") begin : gen_w1s | 
|  | // If SWACCESS is W1S, then assume hw tries to clear. | 
|  | // So, give a chance HW to clear when SW tries to set. | 
|  | // If both try to set/clr at the same bit pos, SW wins. | 
|  | assign wr_en   = we | de; | 
|  | assign wr_data = (de ? d : q) | (we ? wd : '0); | 
|  | end else if (SWACCESS == "W1C") begin : gen_w1c | 
|  | // If SWACCESS is W1C, then assume hw tries to set. | 
|  | // So, give a chance HW to set when SW tries to clear. | 
|  | // If both try to set/clr at the same bit pos, SW wins. | 
|  | assign wr_en   = we | de; | 
|  | assign wr_data = (de ? d : q) & (we ? ~wd : '1); | 
|  | end else if (SWACCESS == "W0C") begin : gen_w0c | 
|  | assign wr_en   = we | de; | 
|  | assign wr_data = (de ? d : q) & (we ? wd : '1); | 
|  | end else if (SWACCESS == "RC") begin : gen_rc | 
|  | // This swtype is not recommended but exists for compatibility. | 
|  | // WARN: we signal is actually read signal not write enable. | 
|  | assign wr_en  = we | de; | 
|  | assign wr_data = (de ? d : q) & (we ? '0 : '1); | 
|  | // Unused wd - Prevent lint errors. | 
|  | logic [DW-1:0] unused_wd; | 
|  | assign unused_wd = wd; | 
|  | end else begin : gen_hw | 
|  | assign wr_en   = de; | 
|  | assign wr_data = d; | 
|  | // Unused we, wd, q - Prevent lint errors. | 
|  | logic          unused_we; | 
|  | logic [DW-1:0] unused_wd; | 
|  | logic [DW-1:0] unused_q; | 
|  | assign unused_we = we; | 
|  | assign unused_wd = wd; | 
|  | assign unused_q  = q; | 
|  | end | 
|  |  | 
|  | endmodule |