Files

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