hw/ip/prim/rtl/prim_subreg.sv Cov: 72.1%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // Register slice conforming to Comportibility guide.
6:
7: module prim_subreg #(
8: parameter int DW = 32 ,
9: parameter SWACCESS = "RW", // {RW, RO, WO, W1C, W1S, W0C, RC}
10: parameter logic [DW-1:0] RESVAL = '0 // Reset value
11: ) (
12: input clk_i,
13: input rst_ni,
14:
15: // From SW: valid for RW, WO, W1C, W1S, W0C, RC
16: // In case of RC, Top connects Read Pulse to we
17: input we,
18: input [DW-1:0] wd,
19:
20: // From HW: valid for HRW, HWO
21: input de,
22: input [DW-1:0] d,
23:
24: // output to HW and Reg Read
25: output logic qe,
26: output logic [DW-1:0] q,
27: output logic [DW-1:0] qs
28: );
29:
30: logic wr_en ;
31: logic [DW-1:0] wr_data;
32:
33: if ((SWACCESS == "RW") || (SWACCESS == "WO")) begin : gen_w
34: assign wr_en = we | de ;
35: assign wr_data = (we == 1'b1) ? wd : d ; // SW higher priority
36: end else if (SWACCESS == "RO") begin : gen_ro
37: // Unused we, wd
38: assign wr_en = de ;
39: assign wr_data = d ;
40: end else if (SWACCESS == "W1S") begin : gen_w1s
41: // If SWACCESS is W1S, then assume hw tries to clear.
42: // So, give a chance HW to clear when SW tries to set.
43: // If both try to set/clr at the same bit pos, SW wins.
44: assign wr_en = we | de ;
45: assign wr_data = (de ? d : q) | (we ? wd : '0);
46: end else if (SWACCESS == "W1C") begin : gen_w1c
47: // If SWACCESS is W1C, then assume hw tries to set.
48: // So, give a chance HW to set when SW tries to clear.
49: // If both try to set/clr at the same bit pos, SW wins.
50: assign wr_en = we | de ;
51: assign wr_data = (de ? d : q) & (we ? ~wd : '1);
52: end else if (SWACCESS == "W0C") begin : gen_w0c
53: assign wr_en = we | de ;
54: assign wr_data = (de ? d : q) & (we ? wd : '1);
55: end else if (SWACCESS == "RC") begin : gen_rc
56: // This swtype is not recommended but exists for compatibility.
57: // WARN: we signal is actually read signal not write enable.
58: assign wr_en = we | de ;
59: assign wr_data = (de ? d : q) & (we ? '0 : '1);
60: end else begin : gen_hw
61: assign wr_en = de ;
62: assign wr_data = d ;
63: end
64:
65: always_ff @(posedge clk_i or negedge rst_ni) begin
66: if (!rst_ni) qe <= 1'b0;
67: else qe <= we ;
68: end
69:
70: always_ff @(posedge clk_i or negedge rst_ni) begin
71: if (!rst_ni) q <= RESVAL ;
72: else if (wr_en) q <= wr_data;
73: end
74: assign qs = q;
75:
76: endmodule
77: