43 lines
1.3 KiB
Systemverilog
43 lines
1.3 KiB
Systemverilog
`default_nettype none
|
|
|
|
// Safe observation of a monotonic source-domain counter. The Gray encoding
|
|
// changes one bit per increment; two destination flops isolate metastability.
|
|
module gray_counter_sync #(
|
|
parameter int unsigned WIDTH = 64
|
|
) (
|
|
input wire logic src_clk,
|
|
input wire logic src_rst,
|
|
input wire logic [WIDTH-1:0] src_binary,
|
|
input wire logic dst_clk,
|
|
input wire logic dst_rst,
|
|
output logic [WIDTH-1:0] dst_binary
|
|
);
|
|
logic [WIDTH-1:0] src_gray;
|
|
(* ASYNC_REG = "TRUE" *) logic [WIDTH-1:0] gray_sync1;
|
|
(* ASYNC_REG = "TRUE" *) logic [WIDTH-1:0] gray_sync2;
|
|
integer i;
|
|
|
|
always_ff @(posedge src_clk) begin
|
|
if (src_rst) src_gray <= '0;
|
|
else src_gray <= (src_binary >> 1) ^ src_binary;
|
|
end
|
|
|
|
always_ff @(posedge dst_clk) begin
|
|
if (dst_rst) begin
|
|
gray_sync1 <= '0;
|
|
gray_sync2 <= '0;
|
|
end else begin
|
|
gray_sync1 <= src_gray;
|
|
gray_sync2 <= gray_sync1;
|
|
end
|
|
end
|
|
|
|
always_comb begin
|
|
dst_binary[WIDTH-1] = gray_sync2[WIDTH-1];
|
|
for (i = WIDTH-2; i >= 0; i = i - 1)
|
|
dst_binary[i] = dst_binary[i+1] ^ gray_sync2[i];
|
|
end
|
|
endmodule
|
|
|
|
`default_nettype wire
|