xmas-snoopy/gateware/sim/sysmgr_sim.v

168 lines
2.9 KiB
Verilog

/*
* sysmgr_sim.v
*
* vim: ts=4 sw=4
*
* System Clock / Reset generation (simulated)
*
* Copyright (C) 2023 Sylvain Munaut <tnt@246tNt.com>
* SPDX-License-Identifier: CERN-OHL-P-2.0
*/
`default_nettype none
module sysmgr_sim (
// Control
input wire sys_start,
input wire sys_stop,
input wire usb_ena,
// LED clock ( 6 MHz )
output wire clk_led,
output wire rst_led,
// System clock ( 24 MHz )
output wire clk_sys,
output wire rst_sys,
// USB ( 48 MHz )
output wire clk_usb,
output wire rst_usb
);
// Signals
// -------
reg clk_base = 1'b0;
wire pll_lock;
reg [2:0] clk_div = 3'b000;
reg clk_sys_i;
wire clk_led_i;
reg [7:0] rst_cnt = 8'h00;
reg rst_i = 1;
wire rst_gbuf;
reg [2:0] sys_start_s;
reg [2:0] sys_stop_s;
wire usb_rst_trig;
reg [3:0] usb_rst_cnt;
wire usb_rst_i;
reg [3:0] usb_ena_dly;
wire usb_ena_i;
reg sys_off;
// SB_HFOSC
// -------
// Generates 48 MHz
always #10.42 clk_base = ~clk_base;
// PLL
// ---
assign clk_usb = usb_ena_i & clk_base;
assign pll_lock = usb_ena_i;
// Dividers
// --------
// Counter
always @(posedge clk_base)
clk_div <= clk_div + 1;
// SYS is div-by-2 + gated
always @(posedge clk_base)
clk_sys_i <= clk_div[0] & ~sys_off;
// LED is div-by-8
assign clk_led_i = clk_div[2];
// Global buffers
SB_GB clk_sys_gbuf_I (
.USER_SIGNAL_TO_GLOBAL_BUFFER(clk_sys_i),
.GLOBAL_BUFFER_OUTPUT(clk_sys)
);
SB_GB clk_led_gbuf_I (
.USER_SIGNAL_TO_GLOBAL_BUFFER(clk_led_i),
.GLOBAL_BUFFER_OUTPUT(clk_led)
);
// USB Enable
// ----------
// Delay falling latch signal
always @(posedge clk_base)
usb_ena_dly <= usb_ena ? 4'b1111 : { usb_ena_dly[2:0], 1'b0 };
assign usb_ena_i = usb_ena_dly[3];
// USB Reset
// ---------
// Reset trigger
assign usb_rst_trig = ~usb_ena | ~pll_lock;
// Reset counter
always @(posedge clk_usb or posedge usb_rst_trig)
if (usb_rst_trig)
usb_rst_cnt <= 4'h8;
else
usb_rst_cnt <= usb_rst_cnt + usb_rst_i;
assign usb_rst_i = usb_rst_cnt[3];
// Global buffer
SB_GB rst_usb_gbuf_I (
.USER_SIGNAL_TO_GLOBAL_BUFFER(usb_rst_i),
.GLOBAL_BUFFER_OUTPUT(rst_usb)
);
// SYS Enable
// ----------
// Synch triggers
always @(posedge clk_base)
begin
sys_start_s <= { ~sys_start_s[1] & sys_start_s[0], sys_start_s[0], sys_start };
sys_stop_s <= { ~sys_stop_s[1] & sys_stop_s[0], sys_stop_s[0], sys_stop };
end
always @(posedge clk_base)
sys_off <= (sys_off & ~rst_i & ~sys_start_s[2]) | sys_stop_s[2];
// Reset LED / SYS
// ---------------
// Counter
always @(posedge clk_led)
rst_cnt <= rst_cnt + rst_i;
always @(posedge clk_led)
rst_i <= (rst_cnt[7:4] != 4'hf);
// Global buffer
SB_GB rst_gbuf_I (
.USER_SIGNAL_TO_GLOBAL_BUFFER(rst_i),
.GLOBAL_BUFFER_OUTPUT(rst_gbuf)
);
// Distribution
assign rst_led = rst_gbuf;
assign rst_sys = rst_gbuf;
endmodule // sysmgr