blob: 8a85e7ebf501df7e49d0bbf569377c1508228a26 [file] [log] [blame]
Michael Schaffner443352e2021-10-05 15:43:26 -07001// 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// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
6// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
7//
Rupert Swarbrick59ffe882021-11-25 14:21:47 +00008// util/design/gen-mubi.py
Michael Schaffner443352e2021-10-05 15:43:26 -07009//
10// Double-synchronizer flop for multibit signals with additional output buffers.
11
12`include "prim_assert.sv"
13
14module prim_mubi8_sync
15 import prim_mubi_pkg::*;
16#(
17 // Number of separately buffered output signals.
18 // The buffer cells have a don't touch constraint
19 // on them such that synthesis tools won't collapse
20 // all copies into one signal.
21 parameter int NumCopies = 1,
22 // This instantiates the synchronizer flops if set to 1.
23 // In special cases where the receiver is in the same clock domain as the sender,
24 // this can be set to 0. However, it is recommended to leave this at 1.
25 parameter bit AsyncOn = 1,
Timothy Chena5e32232021-11-11 15:16:36 -080026 // This controls whether the mubi module institutes stability checks when
27 // AsyncOn is set. If stability checks are on, a 3rd stage of storage is
28 // added after the synchronizers and the outputs only updated if the 3rd
29 // stage and sychronizer agree. If they do not agree, the ResetValue is
Timothy Chen41b26282021-11-11 16:32:51 -080030 // output instead.
Timothy Chena5e32232021-11-11 15:16:36 -080031 parameter bit StabilityCheck = 0,
Michael Schaffner443352e2021-10-05 15:43:26 -070032 // Reset value for the sync flops
33 parameter mubi8_t ResetValue = MuBi8False
34) (
35 input clk_i,
36 input rst_ni,
37 input mubi8_t mubi_i,
38 output mubi8_t [NumCopies-1:0] mubi_o
39);
40
41 `ASSERT_INIT(NumCopiesMustBeGreaterZero_A, NumCopies > 0)
42
43 logic [MuBi8Width-1:0] mubi;
44 if (AsyncOn) begin : gen_flops
Timothy Chena5e32232021-11-11 15:16:36 -080045 logic [MuBi8Width-1:0] mubi_sync;
Michael Schaffner443352e2021-10-05 15:43:26 -070046 prim_flop_2sync #(
47 .Width(MuBi8Width),
48 .ResetValue(MuBi8Width'(ResetValue))
49 ) u_prim_flop_2sync (
50 .clk_i,
51 .rst_ni,
Michael Schaffner50c7af22021-10-12 11:30:13 -070052 .d_i(MuBi8Width'(mubi_i)),
Timothy Chena5e32232021-11-11 15:16:36 -080053 .q_o(mubi_sync)
Michael Schaffner443352e2021-10-05 15:43:26 -070054 );
Timothy Chena5e32232021-11-11 15:16:36 -080055
56 if (StabilityCheck) begin : gen_stable_chks
57 logic [MuBi8Width-1:0] mubi_q;
58 prim_flop #(
59 .Width(MuBi8Width),
60 .ResetValue(MuBi8Width'(ResetValue))
61 ) u_prim_flop_3rd_stage (
62 .clk_i,
63 .rst_ni,
64 .d_i(mubi_sync),
65 .q_o(mubi_q)
66 );
67
68 logic [MuBi8Width-1:0] sig_unstable;
69 prim_xor2 #(
70 .Width(MuBi8Width)
71 ) u_mubi_xor (
72 .in0_i(mubi_sync),
73 .in1_i(mubi_q),
74 .out_o(sig_unstable)
75 );
76
77 logic [MuBi8Width-1:0] reset_value;
78 assign reset_value = ResetValue;
79
80 for (genvar k = 0; k < MuBi8Width; k++) begin : gen_bufs_muxes
81 logic [MuBi8Width-1:0] sig_unstable_buf;
82
83 // each mux gets its own buffered output, this ensures the OR-ing
84 // cannot be defeated in one place.
85 prim_sec_anchor_buf #(
86 .Width(MuBi8Width)
87 ) u_sig_unstable_buf (
88 .in_i(sig_unstable),
89 .out_o(sig_unstable_buf)
90 );
91
92 // if any xor indicates signal is unstable, output the reset
93 // value.
94 prim_clock_mux2 #(
95 .NoFpgaBufG(1'b1)
96 ) u_mux (
97 .clk0_i(mubi_q[k]),
98 .clk1_i(reset_value[k]),
99 .sel_i(|sig_unstable_buf),
100 .clk_o(mubi[k])
101 );
102 end
103
104 end else begin : gen_no_stable_chks
105 assign mubi = mubi_sync;
106 end
Michael Schaffner443352e2021-10-05 15:43:26 -0700107 end else begin : gen_no_flops
108 logic unused_clk;
109 logic unused_rst;
110 assign unused_clk = clk_i;
111 assign unused_rst = rst_ni;
Michael Schaffner50c7af22021-10-12 11:30:13 -0700112 assign mubi = MuBi8Width'(mubi_i);
Michael Schaffner443352e2021-10-05 15:43:26 -0700113 end
114
115 for (genvar j = 0; j < NumCopies; j++) begin : gen_buffs
116 logic [MuBi8Width-1:0] mubi_out;
117 for (genvar k = 0; k < MuBi8Width; k++) begin : gen_bits
118 prim_buf u_prim_buf (
119 .in_i(mubi[k]),
120 .out_o(mubi_out[k])
121 );
122 end
123 assign mubi_o[j] = mubi8_t'(mubi_out);
124 end
125
126 ////////////////
127 // Assertions //
128 ////////////////
129
130 // The outputs should be known at all times.
131 `ASSERT_KNOWN(OutputsKnown_A, mubi_o)
132
133 // If the multibit signal is in a transient state, we expect it
134 // to be stable again within one clock cycle.
135 // DV will exclude these three assertions by name, thus added a module name prefix to make it
136 // harder to accidentally replicate in other modules.
137 `ASSERT(PrimMubi8SyncCheckTransients_A,
138 !(mubi_i inside {MuBi8True, MuBi8False})
139 |=>
140 (mubi_i inside {MuBi8True, MuBi8False}))
141
142 // If a signal departs from passive state, we expect it to move to the active state
143 // with only one transient cycle in between.
144 `ASSERT(PrimMubi8SyncCheckTransients0_A,
145 $past(mubi_i == MuBi8False) &&
146 !(mubi_i inside {MuBi8True, MuBi8False})
147 |=>
148 (mubi_i == MuBi8True))
149
150 `ASSERT(PrimMubi8SyncCheckTransients1_A,
151 $past(mubi_i == MuBi8True) &&
152 !(mubi_i inside {MuBi8True, MuBi8False})
153 |=>
154 (mubi_i == MuBi8False))
155
156endmodule : prim_mubi8_sync