Add reset synchronizer
Add a reset synchronizer to ensure synchronous reset release. There is also a glitch filter to reject spurious resets. It will reject pulses shorter than 5 ns (or around 1.25 ns per LUT). Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
parent
5f331a403c
commit
924079cabd
1
Makefile
1
Makefile
|
@ -146,6 +146,7 @@ MODULES += pcs_tx
|
||||||
MODULES += phy_core
|
MODULES += phy_core
|
||||||
MODULES += pmd_dp83223
|
MODULES += pmd_dp83223
|
||||||
MODULES += pmd_dp83223_rx
|
MODULES += pmd_dp83223_rx
|
||||||
|
MODULES += reset_sync
|
||||||
MODULES += scramble
|
MODULES += scramble
|
||||||
MODULES += uart_tx
|
MODULES += uart_tx
|
||||||
MODULES += uart_rx
|
MODULES += uart_rx
|
||||||
|
|
|
@ -204,6 +204,12 @@ entire rest of the data path up to the PCS (when we can finally align the data)
|
||||||
must handle these edge cases. However, it avoids the internal,
|
must handle these edge cases. However, it avoids the internal,
|
||||||
nebulously-specified, and limited-in-number iCE40 PLLs.
|
nebulously-specified, and limited-in-number iCE40 PLLs.
|
||||||
|
|
||||||
|
=== `reset_sync`
|
||||||
|
|
||||||
|
This module synchronizes external reset signals (asynchronous assert and
|
||||||
|
release) into the local clock domain (asynchronous assert, desynchronous
|
||||||
|
release). A glitch filter suppresses spurious resets.
|
||||||
|
|
||||||
=== `scramble`
|
=== `scramble`
|
||||||
|
|
||||||
This module implements a scrambler as described in ANSI X3.264-1995 section
|
This module implements a scrambler as described in ANSI X3.264-1995 section
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-Only
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
`include "common.vh"
|
||||||
|
|
||||||
|
module reset_sync (
|
||||||
|
input clk,
|
||||||
|
input rst_in,
|
||||||
|
output reg rst_out
|
||||||
|
);
|
||||||
|
|
||||||
|
wire rst;
|
||||||
|
reg rst_last;
|
||||||
|
initial rst_last = 1;
|
||||||
|
initial rst_out = 1;
|
||||||
|
|
||||||
|
`ifdef SYNTHESIS
|
||||||
|
/* Filter out glitches */
|
||||||
|
|
||||||
|
wire [3:0] rst_delay;
|
||||||
|
assign rst_delay[0] = rst_in;
|
||||||
|
assign rst = &rst_delay;
|
||||||
|
|
||||||
|
genvar i;
|
||||||
|
generate for (i = 0; i < 3; i = i + 1) begin
|
||||||
|
(* keep *)
|
||||||
|
SB_LUT4 #(
|
||||||
|
.LUT_INIT(16'hff00)
|
||||||
|
) filter (
|
||||||
|
.I3(rst_delay[i]),
|
||||||
|
.O(rst_delay[i + 1])
|
||||||
|
);
|
||||||
|
end endgenerate
|
||||||
|
`else
|
||||||
|
assign rst = rst_in;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
always @(posedge clk, posedge rst) begin
|
||||||
|
if (rst) begin
|
||||||
|
rst_last <= 1;
|
||||||
|
rst_out <= 1;
|
||||||
|
end else begin
|
||||||
|
rst_last <= rst;
|
||||||
|
rst_out <= rst_last;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,45 @@
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-Only
|
||||||
|
# Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
|
||||||
|
|
||||||
|
import cocotb
|
||||||
|
from cocotb.binary import BinaryValue
|
||||||
|
from cocotb.clock import Clock
|
||||||
|
from cocotb.triggers import ReadOnly, RisingEdge, Timer
|
||||||
|
|
||||||
|
@cocotb.test(timeout_time=100, timeout_unit='us')
|
||||||
|
async def test_bridge(sync):
|
||||||
|
sync.clk.value = BinaryValue('Z')
|
||||||
|
sync.rst_in.value = 0
|
||||||
|
|
||||||
|
await Timer(1)
|
||||||
|
assert sync.rst_out.value
|
||||||
|
await cocotb.start(Clock(sync.clk, 8, units='ns').start())
|
||||||
|
|
||||||
|
await RisingEdge(sync.clk)
|
||||||
|
assert sync.rst_out.value
|
||||||
|
|
||||||
|
await RisingEdge(sync.clk)
|
||||||
|
assert sync.rst_out.value
|
||||||
|
|
||||||
|
await RisingEdge(sync.clk)
|
||||||
|
assert not sync.rst_out.value
|
||||||
|
|
||||||
|
await Timer(1)
|
||||||
|
assert not sync.rst_out.value
|
||||||
|
sync.rst_in.value = 1
|
||||||
|
|
||||||
|
await ReadOnly()
|
||||||
|
assert sync.rst_out.value
|
||||||
|
|
||||||
|
await Timer(1)
|
||||||
|
sync.rst_in.value = 0
|
||||||
|
assert sync.rst_out.value
|
||||||
|
|
||||||
|
await RisingEdge(sync.clk)
|
||||||
|
assert sync.rst_out.value
|
||||||
|
|
||||||
|
await RisingEdge(sync.clk)
|
||||||
|
assert sync.rst_out.value
|
||||||
|
|
||||||
|
await RisingEdge(sync.clk)
|
||||||
|
assert not sync.rst_out.value
|
Loading…
Reference in New Issue