mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
feat: add PLL controller and related testbench functionality
- Removed legacy clock definitions and added a dynamic PLL timing template in retrosoc_pll.sdc. - Introduced a new SystemVerilog testbench (pll_ctrl_tb.sv) for the PLL controller, including clock generation, register read/write tasks, and validation of PLL configuration and timing. - Updated sysctrl_fault_tb.sv to include PLL controller interface and initialization. - Enhanced memory map tests to verify PLL configuration and status offsets. - Added tests for PLL controller dynamic reconfiguration and fallback to safe clock.
This commit is contained in:
28 files changed
+1112
-477
No files matched your search
+12
-1
@@ -1 +1,12 @@
|
||||
--assignment_statement_alignment align --case_items_alignment align --class_member_variable_alignment align --distribution_items_alignment align --enum_assignment_statement_alignment align --formal_parameters_alignment align --module_net_variable_alignment align --named_parameter_alignment align --named_port_alignment align --port_declarations_alignment align --struct_union_members_alignment align --inplace
|
||||
--assignment_statement_alignment=align
|
||||
--case_items_alignment=align
|
||||
--class_member_variable_alignment=align
|
||||
--distribution_items_alignment=align
|
||||
--enum_assignment_statement_alignment=align
|
||||
--formal_parameters_alignment=align
|
||||
--module_net_variable_alignment=align
|
||||
--named_parameter_alignment=align
|
||||
--named_port_alignment=align
|
||||
--port_declarations_alignment=align
|
||||
--struct_union_members_alignment=align
|
||||
--inplace
|
||||
@@ -31,8 +31,6 @@ HAVE_SRAM_MACRO ?= NO
|
||||
HAVE_SVA ?= NO
|
||||
WAVE ?= NO
|
||||
|
||||
RTL_SIM_PLLEN ?= NONE
|
||||
RTL_SIM_PLLCFG ?= NONE
|
||||
RTL_SIM_CORESEL ?= 0
|
||||
RTL_SIM_TIMEOUT ?= -1
|
||||
SIM_FIRMWARE_NAME ?= $(FIRMWARE_NAME)
|
||||
|
||||
@@ -148,10 +148,13 @@
|
||||
#define RS_SOC_SYSCTRL_REG32(offset) RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, (offset))
|
||||
#define reg_sysctrl_coresel RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, UINT32_C(0x00))
|
||||
#define reg_sysctrl_ipsel RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, UINT32_C(0x04))
|
||||
#define reg_sysctrl_pll_cfg RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_CFG_OFFSET)
|
||||
#define reg_sysctrl_pll_cmd RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_CMD_OFFSET)
|
||||
/* Status: bit 0 pending (W1C), bit 1 write, bits 3:2 reason (1 unmapped, 2 reserved). */
|
||||
#define reg_sysctrl_bus_fault_status RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_STATUS_OFFSET)
|
||||
#define reg_sysctrl_bus_fault_addr RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_ADDR_OFFSET)
|
||||
#define reg_sysctrl_bus_fault_count RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_COUNT_OFFSET)
|
||||
#define reg_sysctrl_pll_status RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_STATUS_OFFSET)
|
||||
#define RS_SOC_BUS_FAULT_PENDING UINT32_C(0x00000001)
|
||||
#define RS_SOC_BUS_FAULT_WRITE UINT32_C(0x00000002)
|
||||
#define RS_SOC_BUS_FAULT_REASON_MASK UINT32_C(0x0000000C)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef RETROSOC_HAL_CLOCK_H
|
||||
#define RETROSOC_HAL_CLOCK_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <retrosoc/core/status.h>
|
||||
|
||||
typedef enum {
|
||||
RS_CLOCK_FREQ_24MHZ = 0,
|
||||
RS_CLOCK_FREQ_48MHZ = 1,
|
||||
RS_CLOCK_FREQ_72MHZ = 2,
|
||||
RS_CLOCK_FREQ_96MHZ = 3,
|
||||
RS_CLOCK_FREQ_120MHZ = 4,
|
||||
RS_CLOCK_FREQ_144MHZ = 5,
|
||||
RS_CLOCK_FREQ_168MHZ = 6,
|
||||
RS_CLOCK_FREQ_192MHZ = 7,
|
||||
} rs_clock_frequency_t;
|
||||
|
||||
typedef struct {
|
||||
rs_clock_frequency_t requested_frequency;
|
||||
rs_clock_frequency_t active_frequency;
|
||||
uint8_t error_reason;
|
||||
bool active_valid;
|
||||
bool busy;
|
||||
bool safe_clock;
|
||||
bool pll_locked;
|
||||
bool capable;
|
||||
} rs_clock_status_t;
|
||||
|
||||
rs_status_t rs_clock_get_status(rs_clock_status_t *status);
|
||||
rs_status_t rs_clock_set_frequency(rs_clock_frequency_t frequency, rs_timeout_t timeout);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include <retrosoc/core/soc.h>
|
||||
#include <retrosoc/hal/clock.h>
|
||||
|
||||
#define RS_CLOCK_CMD_APPLY UINT32_C(0x00000001)
|
||||
#define RS_CLOCK_CMD_CLEAR_ERROR UINT32_C(0x00000002)
|
||||
#define RS_CLOCK_STATUS_ACTIVE_MASK UINT32_C(0x00000007)
|
||||
#define RS_CLOCK_STATUS_ACTIVE_VALID UINT32_C(0x00000008)
|
||||
#define RS_CLOCK_STATUS_BUSY UINT32_C(0x00000010)
|
||||
#define RS_CLOCK_STATUS_ERROR_SHIFT 6U
|
||||
#define RS_CLOCK_STATUS_SAFE_CLOCK UINT32_C(0x00000100)
|
||||
#define RS_CLOCK_STATUS_PLL_LOCKED UINT32_C(0x00000200)
|
||||
#define RS_CLOCK_STATUS_CAPABLE UINT32_C(0x00000400)
|
||||
#define RS_CLOCK_ERROR_UNSUPPORTED 1U
|
||||
#define RS_CLOCK_ERROR_LOCK_TIMEOUT 2U
|
||||
|
||||
static bool rs_clock_frequency_valid(rs_clock_frequency_t frequency) {
|
||||
return (uint32_t)frequency <= (uint32_t)RS_CLOCK_FREQ_192MHZ;
|
||||
}
|
||||
|
||||
rs_status_t rs_clock_get_status(rs_clock_status_t *status) {
|
||||
uint32_t value;
|
||||
|
||||
if (status == NULL) {
|
||||
return RS_EINVAL;
|
||||
}
|
||||
value = reg_sysctrl_pll_status;
|
||||
status->requested_frequency =
|
||||
(rs_clock_frequency_t)(reg_sysctrl_pll_cfg & RS_CLOCK_STATUS_ACTIVE_MASK);
|
||||
status->active_frequency = (rs_clock_frequency_t)(value & RS_CLOCK_STATUS_ACTIVE_MASK);
|
||||
status->error_reason = (uint8_t)((value >> RS_CLOCK_STATUS_ERROR_SHIFT) & UINT32_C(0x3));
|
||||
status->active_valid = (value & RS_CLOCK_STATUS_ACTIVE_VALID) != 0U;
|
||||
status->busy = (value & RS_CLOCK_STATUS_BUSY) != 0U;
|
||||
status->safe_clock = (value & RS_CLOCK_STATUS_SAFE_CLOCK) != 0U;
|
||||
status->pll_locked = (value & RS_CLOCK_STATUS_PLL_LOCKED) != 0U;
|
||||
status->capable = (value & RS_CLOCK_STATUS_CAPABLE) != 0U;
|
||||
return RS_OK;
|
||||
}
|
||||
|
||||
rs_status_t rs_clock_set_frequency(rs_clock_frequency_t frequency, rs_timeout_t timeout) {
|
||||
rs_clock_status_t status;
|
||||
bool busy_observed = false;
|
||||
|
||||
if (!rs_clock_frequency_valid(frequency)) {
|
||||
return RS_EINVAL;
|
||||
}
|
||||
if (rs_clock_get_status(&status) != RS_OK) {
|
||||
return RS_EIO;
|
||||
}
|
||||
if (!status.capable) {
|
||||
return RS_ENOTSUP;
|
||||
}
|
||||
if (status.busy) {
|
||||
return RS_EIO;
|
||||
}
|
||||
|
||||
reg_sysctrl_pll_cmd = RS_CLOCK_CMD_CLEAR_ERROR;
|
||||
reg_sysctrl_pll_cfg = (uint32_t)frequency;
|
||||
reg_sysctrl_pll_cmd = RS_CLOCK_CMD_APPLY;
|
||||
|
||||
while (timeout-- != 0U) {
|
||||
if (rs_clock_get_status(&status) != RS_OK) {
|
||||
return RS_EIO;
|
||||
}
|
||||
busy_observed = busy_observed || status.busy;
|
||||
if (busy_observed && !status.busy) {
|
||||
if (status.error_reason == RS_CLOCK_ERROR_UNSUPPORTED) {
|
||||
return RS_ENOTSUP;
|
||||
}
|
||||
if (status.error_reason == RS_CLOCK_ERROR_LOCK_TIMEOUT) {
|
||||
return RS_ETIMEOUT;
|
||||
}
|
||||
return status.error_reason == 0U ? RS_OK : RS_EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return RS_ETIMEOUT;
|
||||
}
|
||||
@@ -7,6 +7,8 @@ the root README and subsystem guides.
|
||||
artifacts, result policy, warning baselines, metrics, CI, and releases.
|
||||
- [misra-c-2012.md](misra-c-2012.md) defines the MISRA C:2012 Amendment 2
|
||||
baseline, scope, partial automation, and deviation process.
|
||||
- [pll-clock-control.md](pll-clock-control.md) describes the SYSCTRL PLL
|
||||
register protocol and software quiesce contract.
|
||||
|
||||
Keep policy descriptions here concise and link to executable configuration as
|
||||
the source of truth. Changes that alter process requirements must also update
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# PLL Dynamic Clock Control
|
||||
|
||||
The system powers up on the `extclk_i_pad` external safe clock. After software
|
||||
submits a PLL frequency request through SYSCTRL, the RCU switches to the safe
|
||||
source, configures the PLL, waits for lock, and switches back in the external
|
||||
reference-clock domain. PLL lock transitions do not reset the system. A failed
|
||||
configuration leaves the system on the safe clock.
|
||||
|
||||
## Registers
|
||||
|
||||
| Offset | Name | Access | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `0x08` | `PLL_CFG` | RW | `FREQ_SEL[2:0]`: 24, 48, 72, 96, 120, 144, 168, or 192 MHz. |
|
||||
| `0x0c` | `PLL_CMD` | WO | bit 0 is `APPLY`; bit 1 is `CLEAR_ERROR`. |
|
||||
| `0x1c` | `PLL_STATUS` | RO | Active profile, validity, busy state, error and cause, safe-clock source, lock state, and capability. |
|
||||
|
||||
Applications use `rs_clock_set_frequency()` and `rs_clock_get_status()` from
|
||||
`<retrosoc/hal/clock.h>`; PDK-specific PLL divider settings are not exposed.
|
||||
|
||||
## Software Flow
|
||||
|
||||
1. Run the transition routine from SRAM, disable interrupts, and quiesce DMA,
|
||||
serial transfers, and other frequency-sensitive transactions.
|
||||
2. Call `rs_clock_set_frequency()` and wait with a bounded timeout.
|
||||
3. On success, reprogram UART, SPI, I2C, timer, and other divider-dependent
|
||||
peripherals for the new frequency before restoring normal operation.
|
||||
4. `RS_ENOTSUP` means the current PDK has no integrated dynamic PLL or
|
||||
glitch-free clock-switch backend. The system remains on the external safe
|
||||
clock.
|
||||
|
||||
`PDK_BEHAV` provides a dynamic-frequency and lock behavior model. A real PDK
|
||||
must integrate a characterized PLL macro, lock timing, and glitch-free clock
|
||||
switch before setting capability to 1. The current IHP130 and ICS55 backends
|
||||
do not advertise this capability.
|
||||
@@ -91,10 +91,6 @@ module retrosoc_top (
|
||||
`ifdef HAVE_PLL
|
||||
.xi_i_pad (s_sys_clk),
|
||||
.xo_o_pad (),
|
||||
.clk_bypass_i_pad (1'b1),
|
||||
.pll_cfg_0_i_pad (1'b0),
|
||||
.pll_cfg_1_i_pad (1'b0),
|
||||
.pll_cfg_2_i_pad (1'b0),
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
.core_sel_0_i_pad (1'b0),
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||
// retroSoC is licensed under Mulan PSL v2.
|
||||
// You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
// You may obtain a copy of Mulan PSL v2 at:
|
||||
// http://license.coscl.org.cn/MulanPSL2
|
||||
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the Mulan PSL v2 for more details.
|
||||
|
||||
interface pll_ctrl_if ();
|
||||
logic [2:0] req_sel_o;
|
||||
logic req_valid_o;
|
||||
logic req_ready_i;
|
||||
|
||||
logic [2:0] rsp_active_sel_i;
|
||||
logic rsp_active_valid_i;
|
||||
logic rsp_safe_clk_i;
|
||||
logic rsp_pll_lock_i;
|
||||
logic [1:0] rsp_error_i;
|
||||
logic rsp_valid_i;
|
||||
logic rsp_ready_o;
|
||||
logic capable_i;
|
||||
|
||||
modport sysctrl(
|
||||
output req_sel_o,
|
||||
output req_valid_o,
|
||||
output rsp_ready_o,
|
||||
input req_ready_i,
|
||||
input rsp_active_sel_i,
|
||||
input rsp_active_valid_i,
|
||||
input rsp_safe_clk_i,
|
||||
input rsp_pll_lock_i,
|
||||
input rsp_error_i,
|
||||
input rsp_valid_i,
|
||||
input capable_i
|
||||
);
|
||||
|
||||
modport rcu(
|
||||
input req_sel_o,
|
||||
input req_valid_o,
|
||||
input rsp_ready_o,
|
||||
output req_ready_i,
|
||||
output rsp_active_sel_i,
|
||||
output rsp_active_valid_i,
|
||||
output rsp_safe_clk_i,
|
||||
output rsp_pll_lock_i,
|
||||
output rsp_error_i,
|
||||
output rsp_valid_i,
|
||||
output capable_i
|
||||
);
|
||||
endinterface
|
||||
@@ -14,9 +14,12 @@
|
||||
// verilog_format: off
|
||||
`define NATV_SYSCTRL_CORESEL 8'h00 // RO
|
||||
`define NATV_SYSCTRL_IPSEL 8'h04 // WR/RD
|
||||
`define NATV_SYSCTRL_PLL_CFG `SOC_SYSCTRL_PLL_CFG_OFFSET // WR/RD
|
||||
`define NATV_SYSCTRL_PLL_CMD `SOC_SYSCTRL_PLL_CMD_OFFSET // WO
|
||||
`define NATV_SYSCTRL_FAULT_STATUS `SOC_SYSCTRL_FAULT_STATUS_OFFSET // W1C/RD
|
||||
`define NATV_SYSCTRL_FAULT_ADDR `SOC_SYSCTRL_FAULT_ADDR_OFFSET // RD
|
||||
`define NATV_SYSCTRL_FAULT_COUNT `SOC_SYSCTRL_FAULT_COUNT_OFFSET // RD
|
||||
`define NATV_SYSCTRL_PLL_STATUS `SOC_SYSCTRL_PLL_STATUS_OFFSET // RD
|
||||
// verilog_format: on
|
||||
|
||||
`endif
|
||||
@@ -40,7 +43,8 @@ module nmi_sysctrl (
|
||||
input logic [3:0] fault_wstrb_i,
|
||||
input logic fault_reserved_i,
|
||||
nmi_if.slave nmi,
|
||||
sysctrl_if.dut sysctrl
|
||||
sysctrl_if.dut sysctrl,
|
||||
pll_ctrl_if.sysctrl pll_ctrl
|
||||
// verilog_format: on
|
||||
);
|
||||
|
||||
@@ -52,6 +56,18 @@ module nmi_sysctrl (
|
||||
logic [`USER_CORESEL_WIDTH-1:0] s_sysctrl_coresel_d, s_sysctrl_coresel_q;
|
||||
logic s_sysctrl_ipsel_en;
|
||||
logic [`USER_IPSEL_WIDTH-1:0] s_sysctrl_ipsel_d, s_sysctrl_ipsel_q;
|
||||
logic [2:0] s_pll_cfg_d, s_pll_cfg_q;
|
||||
logic s_pll_cfg_en;
|
||||
logic s_pll_apply, s_pll_clear_error;
|
||||
logic s_pll_req_valid_d, s_pll_req_valid_q;
|
||||
logic s_pll_busy_d, s_pll_busy_q;
|
||||
logic s_pll_rsp_accept;
|
||||
logic s_pll_error_d, s_pll_error_q;
|
||||
logic [1:0] s_pll_error_reason_d, s_pll_error_reason_q;
|
||||
logic [2:0] s_pll_active_sel_d, s_pll_active_sel_q;
|
||||
logic s_pll_active_valid_d, s_pll_active_valid_q;
|
||||
logic s_pll_safe_clk_d, s_pll_safe_clk_q;
|
||||
logic s_pll_lock_d, s_pll_lock_q;
|
||||
logic s_fault_status_clear;
|
||||
logic s_fault_pending_d, s_fault_pending_q;
|
||||
logic s_fault_write_d, s_fault_write_q;
|
||||
@@ -59,14 +75,17 @@ module nmi_sysctrl (
|
||||
logic [31:0] s_fault_addr_d, s_fault_addr_q;
|
||||
logic [31:0] s_fault_count_d, s_fault_count_q;
|
||||
|
||||
assign s_nmi_wr_hdshk = nmi.valid && (~s_nmi_ready_q) && (|nmi.wstrb);
|
||||
assign s_nmi_rd_hdshk = nmi.valid && (~s_nmi_ready_q) && (~(|nmi.wstrb));
|
||||
assign nmi.ready = s_nmi_ready_q;
|
||||
assign nmi.rdata = s_nmi_rdata_q;
|
||||
assign s_nmi_wr_hdshk = nmi.valid && (~s_nmi_ready_q) && (|nmi.wstrb);
|
||||
assign s_nmi_rd_hdshk = nmi.valid && (~s_nmi_ready_q) && (~(|nmi.wstrb));
|
||||
assign nmi.ready = s_nmi_ready_q;
|
||||
assign nmi.rdata = s_nmi_rdata_q;
|
||||
|
||||
assign sysctrl.ip_sel_o = s_sysctrl_ipsel_q;
|
||||
assign sysctrl.ip_sel_o = s_sysctrl_ipsel_q;
|
||||
assign pll_ctrl.req_sel_o = s_pll_cfg_q;
|
||||
assign pll_ctrl.req_valid_o = s_pll_req_valid_q;
|
||||
assign pll_ctrl.rsp_ready_o = 1'b1;
|
||||
|
||||
assign s_sysctrl_coresel_d = sysctrl.core_sel_i;
|
||||
assign s_sysctrl_coresel_d = sysctrl.core_sel_i;
|
||||
dffr #(`USER_CORESEL_WIDTH) u_sysctrl_coresel_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
@@ -84,6 +103,111 @@ module nmi_sysctrl (
|
||||
s_sysctrl_ipsel_q
|
||||
);
|
||||
|
||||
assign s_pll_cfg_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_SYSCTRL_PLL_CFG && nmi.wstrb[0];
|
||||
assign s_pll_cfg_d = nmi.wdata[2:0];
|
||||
dffer #(3) u_pll_cfg_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_cfg_en,
|
||||
s_pll_cfg_d,
|
||||
s_pll_cfg_q
|
||||
);
|
||||
|
||||
assign s_pll_apply = s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_SYSCTRL_PLL_CMD &&
|
||||
nmi.wstrb[0] && nmi.wdata[0];
|
||||
assign s_pll_clear_error = s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_SYSCTRL_PLL_CMD &&
|
||||
nmi.wstrb[0] && nmi.wdata[1];
|
||||
assign s_pll_rsp_accept = pll_ctrl.rsp_valid_i && pll_ctrl.rsp_ready_o;
|
||||
|
||||
always_comb begin
|
||||
s_pll_req_valid_d = s_pll_req_valid_q;
|
||||
s_pll_busy_d = s_pll_busy_q;
|
||||
if (s_pll_req_valid_q && pll_ctrl.req_ready_i) begin
|
||||
s_pll_req_valid_d = 1'b0;
|
||||
end
|
||||
if (s_pll_apply && ~s_pll_busy_q && ~s_pll_req_valid_q) begin
|
||||
s_pll_req_valid_d = 1'b1;
|
||||
s_pll_busy_d = 1'b1;
|
||||
end
|
||||
if (s_pll_rsp_accept) begin
|
||||
s_pll_busy_d = 1'b0;
|
||||
end
|
||||
end
|
||||
dffr #(1) u_pll_req_valid_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_req_valid_d,
|
||||
s_pll_req_valid_q
|
||||
);
|
||||
dffr #(1) u_pll_busy_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_busy_d,
|
||||
s_pll_busy_q
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
s_pll_error_d = s_pll_error_q;
|
||||
s_pll_error_reason_d = s_pll_error_reason_q;
|
||||
if (s_pll_clear_error) begin
|
||||
s_pll_error_d = 1'b0;
|
||||
s_pll_error_reason_d = 2'd0;
|
||||
end
|
||||
if (s_pll_apply && (s_pll_busy_q || s_pll_req_valid_q)) begin
|
||||
s_pll_error_d = 1'b1;
|
||||
s_pll_error_reason_d = 2'd3;
|
||||
end
|
||||
if (s_pll_rsp_accept && |pll_ctrl.rsp_error_i) begin
|
||||
s_pll_error_d = 1'b1;
|
||||
s_pll_error_reason_d = pll_ctrl.rsp_error_i;
|
||||
end
|
||||
end
|
||||
dffr #(1) u_pll_error_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_error_d,
|
||||
s_pll_error_q
|
||||
);
|
||||
dffr #(2) u_pll_error_reason_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_error_reason_d,
|
||||
s_pll_error_reason_q
|
||||
);
|
||||
|
||||
assign s_pll_active_sel_d = pll_ctrl.rsp_active_sel_i;
|
||||
dffer #(3) u_pll_active_sel_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_rsp_accept,
|
||||
s_pll_active_sel_d,
|
||||
s_pll_active_sel_q
|
||||
);
|
||||
assign s_pll_active_valid_d = pll_ctrl.rsp_active_valid_i;
|
||||
dffer #(1) u_pll_active_valid_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_rsp_accept,
|
||||
s_pll_active_valid_d,
|
||||
s_pll_active_valid_q
|
||||
);
|
||||
assign s_pll_safe_clk_d = pll_ctrl.rsp_safe_clk_i;
|
||||
dfferc #(1, 1'b1) u_pll_safe_clk_dfferc (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_rsp_accept,
|
||||
s_pll_safe_clk_d,
|
||||
s_pll_safe_clk_q
|
||||
);
|
||||
assign s_pll_lock_d = pll_ctrl.rsp_pll_lock_i;
|
||||
dffer #(1) u_pll_lock_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_pll_rsp_accept,
|
||||
s_pll_lock_d,
|
||||
s_pll_lock_q
|
||||
);
|
||||
|
||||
assign s_fault_status_clear = s_nmi_wr_hdshk &&
|
||||
nmi.addr[7:0] == `NATV_SYSCTRL_FAULT_STATUS &&
|
||||
nmi.wstrb[0] && nmi.wdata[0];
|
||||
@@ -152,9 +276,21 @@ module nmi_sysctrl (
|
||||
// verilog_format: off
|
||||
`NATV_SYSCTRL_CORESEL: s_nmi_rdata_d = {{(32 - `USER_CORESEL_WIDTH) {1'b0}}, s_sysctrl_coresel_q};
|
||||
`NATV_SYSCTRL_IPSEL: s_nmi_rdata_d = {{(32 - `USER_IPSEL_WIDTH) {1'b0}}, s_sysctrl_ipsel_q};
|
||||
`NATV_SYSCTRL_PLL_CFG: s_nmi_rdata_d = {29'd0, s_pll_cfg_q};
|
||||
`NATV_SYSCTRL_FAULT_STATUS: s_nmi_rdata_d = {28'd0, s_fault_reason_q, s_fault_write_q, s_fault_pending_q};
|
||||
`NATV_SYSCTRL_FAULT_ADDR: s_nmi_rdata_d = s_fault_addr_q;
|
||||
`NATV_SYSCTRL_FAULT_COUNT: s_nmi_rdata_d = s_fault_count_q;
|
||||
`NATV_SYSCTRL_PLL_STATUS: s_nmi_rdata_d = {
|
||||
21'd0,
|
||||
pll_ctrl.capable_i,
|
||||
s_pll_lock_q,
|
||||
s_pll_safe_clk_q,
|
||||
s_pll_error_reason_q,
|
||||
s_pll_error_q,
|
||||
s_pll_busy_q,
|
||||
s_pll_active_valid_q,
|
||||
s_pll_active_sel_q
|
||||
};
|
||||
default: s_nmi_rdata_d = s_nmi_rdata_q;
|
||||
endcase
|
||||
// verilog_format: on
|
||||
|
||||
@@ -129,9 +129,12 @@ def render_rtl(cpu_reset: int, regions: list[dict[str, Any]]) -> str:
|
||||
lines.append(f"`define SOC_ADDR_IS_{route.upper()}(addr) ({join_or(selected)})")
|
||||
lines += [
|
||||
"",
|
||||
"`define SOC_SYSCTRL_PLL_CFG_OFFSET 32'h00000008",
|
||||
"`define SOC_SYSCTRL_PLL_CMD_OFFSET 32'h0000000C",
|
||||
"`define SOC_SYSCTRL_FAULT_STATUS_OFFSET 32'h00000010",
|
||||
"`define SOC_SYSCTRL_FAULT_ADDR_OFFSET 32'h00000014",
|
||||
"`define SOC_SYSCTRL_FAULT_COUNT_OFFSET 32'h00000018",
|
||||
"`define SOC_SYSCTRL_PLL_STATUS_OFFSET 32'h0000001C",
|
||||
"",
|
||||
"`endif",
|
||||
"",
|
||||
@@ -162,9 +165,12 @@ def render_c(cpu_reset: int, regions: list[dict[str, Any]], have_sram_if: str) -
|
||||
]
|
||||
lines += [
|
||||
"",
|
||||
"#define RS_SOC_SYSCTRL_PLL_CFG_OFFSET UINT32_C(0x00000008)",
|
||||
"#define RS_SOC_SYSCTRL_PLL_CMD_OFFSET UINT32_C(0x0000000C)",
|
||||
"#define RS_SOC_SYSCTRL_FAULT_STATUS_OFFSET UINT32_C(0x00000010)",
|
||||
"#define RS_SOC_SYSCTRL_FAULT_ADDR_OFFSET UINT32_C(0x00000014)",
|
||||
"#define RS_SOC_SYSCTRL_FAULT_COUNT_OFFSET UINT32_C(0x00000018)",
|
||||
"#define RS_SOC_SYSCTRL_PLL_STATUS_OFFSET UINT32_C(0x0000001C)",
|
||||
"",
|
||||
"#endif",
|
||||
"",
|
||||
|
||||
@@ -19,18 +19,14 @@ module retrosoc_tb;
|
||||
|
||||
integer sim_runtime;
|
||||
|
||||
reg r_ext_clk;
|
||||
wire s_ext_clk;
|
||||
reg r_aud_clk;
|
||||
wire s_aud_clk;
|
||||
reg r_rst_n;
|
||||
wire s_rst_n;
|
||||
reg r_ext_clk;
|
||||
wire s_ext_clk;
|
||||
reg r_aud_clk;
|
||||
wire s_aud_clk;
|
||||
reg r_rst_n;
|
||||
wire s_rst_n;
|
||||
`ifdef HAVE_PLL
|
||||
reg r_xtal_clk;
|
||||
reg r_pll_en;
|
||||
wire s_clk_bypass;
|
||||
reg [2:0] r_pll_cfg;
|
||||
wire [2:0] s_pll_cfg;
|
||||
reg r_xtal_clk;
|
||||
`endif
|
||||
reg [ 4:0] r_core_sel;
|
||||
wire [ 4:0] s_core_sel;
|
||||
@@ -88,13 +84,9 @@ module retrosoc_tb;
|
||||
always #(1000 / AUD_CPU_FREQ / 2) r_aud_clk = (r_aud_clk === 1'b0);
|
||||
|
||||
// connect inout pad
|
||||
assign s_ext_clk = r_ext_clk;
|
||||
assign s_aud_clk = r_aud_clk;
|
||||
assign s_rst_n = r_rst_n;
|
||||
`ifdef HAVE_PLL
|
||||
assign s_clk_bypass = ~r_pll_en;
|
||||
assign s_pll_cfg = r_pll_cfg;
|
||||
`endif
|
||||
assign s_ext_clk = r_ext_clk;
|
||||
assign s_aud_clk = r_aud_clk;
|
||||
assign s_rst_n = r_rst_n;
|
||||
assign s_core_sel = r_core_sel;
|
||||
assign s_user_gpio_0_io = r_user_gpio_0_io;
|
||||
|
||||
@@ -105,10 +97,6 @@ module retrosoc_tb;
|
||||
`ifdef HAVE_PLL
|
||||
.xi_i_pad (r_xtal_clk),
|
||||
.xo_o_pad (),
|
||||
.clk_bypass_i_pad (s_clk_bypass),
|
||||
.pll_cfg_0_i_pad (s_pll_cfg[0]),
|
||||
.pll_cfg_1_i_pad (s_pll_cfg[1]),
|
||||
.pll_cfg_2_i_pad (s_pll_cfg[2]),
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
.core_sel_0_i_pad (s_core_sel[0]),
|
||||
@@ -412,27 +400,7 @@ module retrosoc_tb;
|
||||
`endif
|
||||
|
||||
`ifdef HAVE_PLL
|
||||
if ($test$plusargs("pll_en")) r_pll_en = 1'b1;
|
||||
else r_pll_en = 1'b0;
|
||||
|
||||
if ($test$plusargs("pll_cfg0")) r_pll_cfg = 3'd0; // 24M
|
||||
else if ($test$plusargs("pll_cfg1")) r_pll_cfg = 3'd1; // 48M
|
||||
else if ($test$plusargs("pll_cfg2")) r_pll_cfg = 3'd2; // 72M
|
||||
else if ($test$plusargs("pll_cfg3")) r_pll_cfg = 3'd3; // 96M
|
||||
else if ($test$plusargs("pll_cfg4")) r_pll_cfg = 3'd4; // 120M
|
||||
else if ($test$plusargs("pll_cfg5")) r_pll_cfg = 3'd5; // 144M
|
||||
else if ($test$plusargs("pll_cfg6")) r_pll_cfg = 3'd6; // 168M
|
||||
else if ($test$plusargs("pll_cfg7")) r_pll_cfg = 3'd7; // 192M
|
||||
else r_pll_cfg = 3'd0; // 24M
|
||||
|
||||
if (r_pll_en == 1'b0) begin
|
||||
$display("pll_en: %0d pll_cfg: %0d clk_freq: %0dMHz", r_pll_en, r_pll_cfg, EXT_CPU_FREQ);
|
||||
end else if (r_pll_cfg == 3'd0 || r_pll_cfg == 3'd1) begin
|
||||
$display("pll_en: %0d pll_cfg: %0d clk_freq: %0dMHz", r_pll_en, r_pll_cfg, XTAL_CPU_FREQ);
|
||||
end else begin
|
||||
$display("pll_en: %0d pll_cfg: %0d clk_freq: %0dMHz", r_pll_en, r_pll_cfg,
|
||||
(r_pll_cfg + 1) * 24);
|
||||
end
|
||||
$display("pll clock control: sysctrl");
|
||||
`else
|
||||
$display("ext clk_freq: %0dMHz", EXT_CPU_FREQ);
|
||||
`endif
|
||||
|
||||
@@ -29,7 +29,6 @@ module retrosoc_top (
|
||||
wire s_clk;
|
||||
wire s_rst_n;
|
||||
wire [4:0] s_core_sel;
|
||||
wire s_clk_bypass;
|
||||
wire s_psram_sck;
|
||||
wire s_psram_nss0;
|
||||
wire s_psram_dat0;
|
||||
@@ -43,10 +42,9 @@ module retrosoc_top (
|
||||
wire s_xpi_dat2_io;
|
||||
wire s_xpi_dat3_io;
|
||||
|
||||
assign s_clk = ext_clk_i;
|
||||
assign s_rst_n = rst_n_i;
|
||||
assign s_core_sel = core_sel_i;
|
||||
assign s_clk_bypass = 1'b1;
|
||||
assign s_clk = ext_clk_i;
|
||||
assign s_rst_n = rst_n_i;
|
||||
assign s_core_sel = core_sel_i;
|
||||
retrosoc_asic u_retrosoc_asic (
|
||||
.extclk_i_pad (s_clk),
|
||||
.audclk_i_pad (),
|
||||
@@ -54,10 +52,6 @@ module retrosoc_top (
|
||||
`ifdef HAVE_PLL
|
||||
.xi_i_pad (),
|
||||
.xo_o_pad (),
|
||||
.clk_bypass_i_pad (s_clk_bypass),
|
||||
.pll_cfg_0_i_pad (),
|
||||
.pll_cfg_1_i_pad (),
|
||||
.pll_cfg_2_i_pad (),
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
.core_sel_0_i_pad (s_core_sel[0]),
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
/ip/native/storage/xpi.sv
|
||||
/ip/native/peripheral/dma_core.sv
|
||||
/ip/native/peripheral/dma.sv
|
||||
/ip/native/peripheral/pll_ctrl_if.sv
|
||||
/ip/native/peripheral/sysctrl.sv
|
||||
/ip/native/peripheral/clint.sv
|
||||
/ip/native/memory/sdram_clkgen.sv
|
||||
|
||||
@@ -28,8 +28,7 @@ IVERILOG_POST_DEPFILE := $(IVERILOG_POST_DIR)/simv.d
|
||||
IVERILOG_COMMON_OPTS := -g2012
|
||||
IVERILOG_TIME_OPTS := -gno-specify
|
||||
IVERILOG_POST_OPTS := -gspecify -Tmin
|
||||
IVERILOG_SIM_OPTS := +$(RTL_SIM_PLLEN) +$(RTL_SIM_PLLCFG) \
|
||||
+core_sel=$(RTL_SIM_CORESEL) +sim_timeout=$(RTL_SIM_TIMEOUT) +wave_$(WAVE)
|
||||
IVERILOG_SIM_OPTS := +core_sel=$(RTL_SIM_CORESEL) +sim_timeout=$(RTL_SIM_TIMEOUT) +wave_$(WAVE)
|
||||
|
||||
$(CONVERTED_SOC): $(MPW_VARIANT_STAMP) $(FILELIST_STAMP)
|
||||
@mkdir -p $(@D)
|
||||
|
||||
@@ -65,6 +65,7 @@ CRT_SRCS := $(ROOT_PATH)/crt/arch/riscv/startup.S \
|
||||
$(ROOT_PATH)/crt/src/core/archinfo.c \
|
||||
$(ROOT_PATH)/crt/src/service/bench.c \
|
||||
$(ROOT_PATH)/crt/src/service/booter.c \
|
||||
$(ROOT_PATH)/crt/src/hal/clock.c \
|
||||
$(ROOT_PATH)/crt/src/hal/uart.c \
|
||||
$(ROOT_PATH)/crt/src/hal/gpio.c \
|
||||
$(ROOT_PATH)/crt/src/hal/timer.c \
|
||||
|
||||
+1
-2
@@ -46,8 +46,7 @@ POST_OPTS := -sdf min:retrosoc_tb.u_retrosoc_asic:$(SDF_PATH) \
|
||||
|
||||
TIME_OPTION := +notimingcheck +nospecify
|
||||
SIM_OPTS := +vcs+loopreport+1000 -suppress=ASLR_DETECTED_INFO \
|
||||
+$(RTL_SIM_PLLEN) +$(RTL_SIM_PLLCFG) +core_sel=$(RTL_SIM_CORESEL) +sim_timeout=$(RTL_SIM_TIMEOUT) \
|
||||
+wave_$(WAVE)
|
||||
+core_sel=$(RTL_SIM_CORESEL) +sim_timeout=$(RTL_SIM_TIMEOUT) +wave_$(WAVE)
|
||||
|
||||
VCS_BEHV_DIR := $(SIM_BUILD_ROOT)/behv
|
||||
VCS_NETL_DIR := $(SIM_BUILD_ROOT)/netl
|
||||
|
||||
@@ -29,6 +29,7 @@ module ip_nmi_wrapper (
|
||||
xpi_if.dut xpi,
|
||||
nmi_if.master dma_nmi,
|
||||
sysctrl_if.dut sysctrl,
|
||||
pll_ctrl_if.sysctrl pll_ctrl,
|
||||
sdram_if.dut sdram,
|
||||
dvp_if.dut dvp,
|
||||
sdio_if.dut sdio,
|
||||
@@ -382,7 +383,8 @@ module ip_nmi_wrapper (
|
||||
.fault_wstrb_i (fault_wstrb_i),
|
||||
.fault_reserved_i(fault_reserved_i),
|
||||
.nmi (u_sysctrl_nmi_if),
|
||||
.sysctrl (sysctrl)
|
||||
.sysctrl (sysctrl),
|
||||
.pll_ctrl (pll_ctrl)
|
||||
);
|
||||
|
||||
nmi_clint u_nmi_clint (
|
||||
|
||||
+292
-124
@@ -5,74 +5,122 @@
|
||||
// http://license.coscl.org.cn/MulanPSL2
|
||||
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the Mulan PSL v2 for more details.
|
||||
|
||||
module rcu (
|
||||
input logic ext_clk_i,
|
||||
input logic aud_clk_i,
|
||||
input logic ext_rst_n_i,
|
||||
input logic ext_clk_i,
|
||||
input logic aud_clk_i,
|
||||
input logic ext_rst_n_i,
|
||||
`ifdef HAVE_PLL
|
||||
input logic xtal_clk_i,
|
||||
input logic clk_bypass_i,
|
||||
input logic [2:0] pll_cfg_i,
|
||||
input logic xtal_clk_i,
|
||||
`endif
|
||||
output logic sys_clk_o,
|
||||
output logic sys_rst_n_o,
|
||||
output logic aud_rst_n_o,
|
||||
output logic sys_clkdiv4_o
|
||||
pll_ctrl_if.rcu pll_ctrl,
|
||||
output logic sys_clk_o,
|
||||
output logic sys_rst_n_o,
|
||||
output logic aud_rst_n_o,
|
||||
output logic sys_clkdiv4_o
|
||||
);
|
||||
`ifdef HAVE_PLL
|
||||
logic s_xtal_clk_buf;
|
||||
logic s_pll_clk_buf;
|
||||
logic s_pll_clk;
|
||||
logic s_pll_lock;
|
||||
logic s_pll_bp, s_pll_bp_q;
|
||||
logic [3:0] s_pll_N, s_pll_N_q;
|
||||
logic [7:0] s_pll_M, s_pll_M_q;
|
||||
logic [1:0] s_pll_OD, s_pll_OD_q;
|
||||
`endif
|
||||
logic s_ext_clk_buf;
|
||||
logic s_sys_clk;
|
||||
logic s_aud_clk_buf;
|
||||
logic s_sys_clk;
|
||||
logic s_ext_rst_n_sync;
|
||||
logic s_sys_rst_n_sync;
|
||||
logic s_aud_rst_n_sync;
|
||||
|
||||
logic [3:0] s_div_cnt_d, s_div_cnt_q;
|
||||
logic s_sys_clkdiv4_d, s_sys_clkdiv4_q;
|
||||
|
||||
|
||||
// ext buffer
|
||||
tc_clk_buf u_ext_clk_buf (
|
||||
.clk_i(ext_clk_i),
|
||||
.clk_o(s_ext_clk_buf)
|
||||
);
|
||||
// aud buffer
|
||||
tc_clk_buf u_aud_clk_buf (
|
||||
.clk_i(aud_clk_i),
|
||||
.clk_o(s_aud_clk_buf)
|
||||
);
|
||||
|
||||
rst_sync #(
|
||||
.STAGE(5)
|
||||
) u_ext_rst_sync (
|
||||
.clk_i (s_ext_clk_buf),
|
||||
.rst_n_i(ext_rst_n_i),
|
||||
.rst_n_o(s_ext_rst_n_sync)
|
||||
);
|
||||
|
||||
`ifdef HAVE_PLL
|
||||
logic s_xtal_clk_buf;
|
||||
logic s_pll_clk;
|
||||
logic s_pll_clk_buf;
|
||||
logic s_pll_lock;
|
||||
logic s_pll_capable;
|
||||
logic [2:0] s_pll_sel;
|
||||
logic s_pll_apply;
|
||||
logic s_select_ext_clk;
|
||||
|
||||
tc_clk_buf u_xtal_buf (
|
||||
.clk_i(xtal_clk_i),
|
||||
.clk_o(s_xtal_clk_buf)
|
||||
);
|
||||
|
||||
tc_pll u_tc_pll (
|
||||
.fref_i (s_xtal_clk_buf),
|
||||
.rst_n_i (s_ext_rst_n_sync),
|
||||
.cfg_sel_i (s_pll_sel),
|
||||
.cfg_apply_i (s_pll_apply),
|
||||
.pll_capable_o(s_pll_capable),
|
||||
.pll_lock_o (s_pll_lock),
|
||||
.pll_clk_o (s_pll_clk)
|
||||
);
|
||||
tc_clk_buf u_pll_clk_buf (
|
||||
.clk_i(s_pll_clk),
|
||||
.clk_o(s_pll_clk_buf)
|
||||
);
|
||||
|
||||
// select system clock from pll or ext
|
||||
tc_clk_mux2 u_sys_mux (
|
||||
tc_clk_switch2 u_sys_clk_switch (
|
||||
.clk0_i (s_pll_clk_buf),
|
||||
.clk1_i (s_ext_clk_buf),
|
||||
.clk_sel_i(clk_bypass_i),
|
||||
.clk_sel_i(s_select_ext_clk),
|
||||
.clk_o (s_sys_clk)
|
||||
);
|
||||
|
||||
pll_rcu_controller u_pll_rcu_controller (
|
||||
.sys_clk_i (s_sys_clk),
|
||||
.sys_rst_n_i (s_sys_rst_n_sync),
|
||||
.ext_clk_i (s_ext_clk_buf),
|
||||
.ext_rst_n_i (s_ext_rst_n_sync),
|
||||
.pll_lock_i (s_pll_lock),
|
||||
.pll_capable_i (s_pll_capable),
|
||||
.pll_sel_o (s_pll_sel),
|
||||
.pll_apply_o (s_pll_apply),
|
||||
.select_ext_clk_o(s_select_ext_clk),
|
||||
.pll_ctrl (pll_ctrl)
|
||||
);
|
||||
`else
|
||||
assign s_sys_clk = s_ext_clk_buf;
|
||||
logic s_no_pll_rsp_valid_d, s_no_pll_rsp_valid_q;
|
||||
|
||||
assign s_sys_clk = s_ext_clk_buf;
|
||||
assign pll_ctrl.req_ready_i = ~s_no_pll_rsp_valid_q;
|
||||
assign pll_ctrl.rsp_active_sel_i = '0;
|
||||
assign pll_ctrl.rsp_active_valid_i = 1'b0;
|
||||
assign pll_ctrl.rsp_safe_clk_i = 1'b1;
|
||||
assign pll_ctrl.rsp_pll_lock_i = 1'b0;
|
||||
assign pll_ctrl.rsp_error_i = 2'd1;
|
||||
assign pll_ctrl.rsp_valid_i = s_no_pll_rsp_valid_q;
|
||||
assign pll_ctrl.capable_i = 1'b0;
|
||||
|
||||
always_comb begin
|
||||
s_no_pll_rsp_valid_d = s_no_pll_rsp_valid_q;
|
||||
if (pll_ctrl.req_valid_o && pll_ctrl.req_ready_i) begin
|
||||
s_no_pll_rsp_valid_d = 1'b1;
|
||||
end
|
||||
if (s_no_pll_rsp_valid_q && pll_ctrl.rsp_ready_o) begin
|
||||
s_no_pll_rsp_valid_d = 1'b0;
|
||||
end
|
||||
end
|
||||
dffr #(1) u_no_pll_rsp_valid_dffr (
|
||||
s_ext_clk_buf,
|
||||
s_ext_rst_n_sync,
|
||||
s_no_pll_rsp_valid_d,
|
||||
s_no_pll_rsp_valid_q
|
||||
);
|
||||
`endif
|
||||
|
||||
tc_clk_buf u_sys_clk_buf (
|
||||
@@ -80,16 +128,13 @@ module rcu (
|
||||
.clk_o(sys_clk_o)
|
||||
);
|
||||
|
||||
|
||||
// reset sync logic
|
||||
rst_sync #(
|
||||
.STAGE(5)
|
||||
) u_ext_rst_sync (
|
||||
) u_sys_rst_sync (
|
||||
.clk_i (sys_clk_o),
|
||||
.rst_n_i(ext_rst_n_i),
|
||||
.rst_n_o(s_ext_rst_n_sync)
|
||||
.rst_n_o(s_sys_rst_n_sync)
|
||||
);
|
||||
|
||||
rst_sync #(
|
||||
.STAGE(5)
|
||||
) u_aud_rst_sync (
|
||||
@@ -98,12 +143,7 @@ module rcu (
|
||||
.rst_n_o(s_aud_rst_n_sync)
|
||||
);
|
||||
|
||||
`ifdef HAVE_PLL
|
||||
assign sys_rst_n_o = clk_bypass_i ? s_ext_rst_n_sync : s_pll_lock;
|
||||
`else
|
||||
assign sys_rst_n_o = s_ext_rst_n_sync;
|
||||
`endif
|
||||
|
||||
assign sys_rst_n_o = s_sys_rst_n_sync;
|
||||
assign aud_rst_n_o = s_aud_rst_n_sync;
|
||||
assign sys_clkdiv4_o = s_sys_clkdiv4_q;
|
||||
|
||||
@@ -114,7 +154,6 @@ module rcu (
|
||||
s_div_cnt_d,
|
||||
s_div_cnt_q
|
||||
);
|
||||
|
||||
assign s_sys_clkdiv4_d = (s_div_cnt_q == 4'd1) ? ~s_sys_clkdiv4_q : s_sys_clkdiv4_q;
|
||||
dffr #(1) u_sys_clkdiv4_dffr (
|
||||
sys_clk_o,
|
||||
@@ -122,97 +161,226 @@ module rcu (
|
||||
s_sys_clkdiv4_d,
|
||||
s_sys_clkdiv4_q
|
||||
);
|
||||
endmodule
|
||||
|
||||
module pll_rcu_controller #(
|
||||
parameter int LOCK_TIMEOUT = 1024
|
||||
) (
|
||||
input logic sys_clk_i,
|
||||
input logic sys_rst_n_i,
|
||||
input logic ext_clk_i,
|
||||
input logic ext_rst_n_i,
|
||||
input logic pll_lock_i,
|
||||
input logic pll_capable_i,
|
||||
output logic [2:0] pll_sel_o,
|
||||
output logic pll_apply_o,
|
||||
output logic select_ext_clk_o,
|
||||
pll_ctrl_if.rcu pll_ctrl
|
||||
);
|
||||
localparam logic [2:0] PLL_IDLE = 3'd0;
|
||||
localparam logic [2:0] PLL_SAFE = 3'd1;
|
||||
localparam logic [2:0] PLL_APPLY = 3'd2;
|
||||
localparam logic [2:0] PLL_WAIT_LOCK = 3'd3;
|
||||
localparam logic [2:0] PLL_SWITCH = 3'd4;
|
||||
localparam logic [2:0] PLL_RESPOND = 3'd5;
|
||||
|
||||
logic [2:0] s_req_sel;
|
||||
logic s_req_valid, s_req_ready;
|
||||
logic [7:0] s_rsp_data;
|
||||
logic s_rsp_valid, s_rsp_ready;
|
||||
logic [7:0] s_rsp_sys_data;
|
||||
logic s_rsp_sys_valid;
|
||||
logic [2:0] s_state_d, s_state_q;
|
||||
logic [2:0] s_pll_sel_d, s_pll_sel_q;
|
||||
logic s_pll_apply_d, s_pll_apply_q;
|
||||
logic s_select_ext_clk_d, s_select_ext_clk_q;
|
||||
logic [15:0] s_lock_count_d, s_lock_count_q;
|
||||
logic [2:0] s_active_sel_d, s_active_sel_q;
|
||||
logic s_active_valid_d, s_active_valid_q;
|
||||
logic s_safe_clk_d, s_safe_clk_q;
|
||||
logic s_lock_d, s_lock_q;
|
||||
logic [1:0] s_error_d, s_error_q;
|
||||
logic s_rsp_valid_d, s_rsp_valid_q;
|
||||
|
||||
cdc_2phase #(
|
||||
.DATA_WIDTH(3)
|
||||
) u_pll_request_cdc (
|
||||
.src_clk_i (sys_clk_i),
|
||||
.src_rst_n_i(sys_rst_n_i),
|
||||
.src_data_i (pll_ctrl.req_sel_o),
|
||||
.src_valid_i(pll_ctrl.req_valid_o),
|
||||
.src_ready_o(pll_ctrl.req_ready_i),
|
||||
.dst_clk_i (ext_clk_i),
|
||||
.dst_rst_n_i(ext_rst_n_i),
|
||||
.dst_data_o (s_req_sel),
|
||||
.dst_valid_o(s_req_valid),
|
||||
.dst_ready_i(s_req_ready)
|
||||
);
|
||||
cdc_2phase #(
|
||||
.DATA_WIDTH(8)
|
||||
) u_pll_response_cdc (
|
||||
.src_clk_i (ext_clk_i),
|
||||
.src_rst_n_i(ext_rst_n_i),
|
||||
.src_data_i (s_rsp_data),
|
||||
.src_valid_i(s_rsp_valid_q),
|
||||
.src_ready_o(s_rsp_ready),
|
||||
.dst_clk_i (sys_clk_i),
|
||||
.dst_rst_n_i(sys_rst_n_i),
|
||||
.dst_data_o (s_rsp_sys_data),
|
||||
.dst_valid_o(s_rsp_sys_valid),
|
||||
.dst_ready_i(pll_ctrl.rsp_ready_o)
|
||||
);
|
||||
|
||||
assign pll_ctrl.rsp_active_sel_i = s_rsp_sys_data[2:0];
|
||||
assign pll_ctrl.rsp_active_valid_i = s_rsp_sys_data[3];
|
||||
assign pll_ctrl.rsp_safe_clk_i = s_rsp_sys_data[4];
|
||||
assign pll_ctrl.rsp_pll_lock_i = s_rsp_sys_data[5];
|
||||
assign pll_ctrl.rsp_error_i = s_rsp_sys_data[7:6];
|
||||
assign pll_ctrl.rsp_valid_i = s_rsp_sys_valid;
|
||||
assign pll_ctrl.capable_i = pll_capable_i;
|
||||
assign s_req_ready = s_state_q == PLL_IDLE;
|
||||
assign s_rsp_data = {s_error_q, s_lock_q, s_safe_clk_q, s_active_valid_q, s_active_sel_q};
|
||||
assign pll_sel_o = s_pll_sel_q;
|
||||
assign pll_apply_o = s_pll_apply_q;
|
||||
assign select_ext_clk_o = s_select_ext_clk_q;
|
||||
|
||||
// 24(bypass) 48(ext clk) 72 96
|
||||
// 120 144 168 192
|
||||
// 2 <= N <= 4
|
||||
// 7 <= M
|
||||
`ifdef HAVE_PLL
|
||||
always_comb begin
|
||||
unique case (pll_cfg_i)
|
||||
3'b000: begin //bypass 24MHz
|
||||
s_pll_bp = 1'b1;
|
||||
s_pll_M = 8'd20;
|
||||
s_pll_N = 4'd2;
|
||||
s_pll_OD = 2'd1;
|
||||
s_state_d = s_state_q;
|
||||
s_pll_sel_d = s_pll_sel_q;
|
||||
s_pll_apply_d = (s_state_q == PLL_APPLY) || (s_state_q == PLL_WAIT_LOCK);
|
||||
s_select_ext_clk_d = s_select_ext_clk_q;
|
||||
s_lock_count_d = s_lock_count_q;
|
||||
s_active_sel_d = s_active_sel_q;
|
||||
s_active_valid_d = s_active_valid_q;
|
||||
s_safe_clk_d = s_safe_clk_q;
|
||||
s_lock_d = s_lock_q;
|
||||
s_error_d = s_error_q;
|
||||
s_rsp_valid_d = s_rsp_valid_q;
|
||||
|
||||
unique case (s_state_q)
|
||||
PLL_IDLE: begin
|
||||
if (s_req_valid) begin
|
||||
s_pll_sel_d = s_req_sel;
|
||||
s_select_ext_clk_d = 1'b1;
|
||||
s_error_d = 2'd0;
|
||||
s_state_d = PLL_SAFE;
|
||||
end
|
||||
end
|
||||
3'b001: begin //bypass 24MHz
|
||||
s_pll_bp = 1'b1;
|
||||
s_pll_M = 8'd20;
|
||||
s_pll_N = 4'd2;
|
||||
s_pll_OD = 2'd1;
|
||||
PLL_SAFE: begin
|
||||
s_select_ext_clk_d = 1'b1;
|
||||
s_safe_clk_d = 1'b1;
|
||||
s_lock_d = 1'b0;
|
||||
if (pll_capable_i) begin
|
||||
s_state_d = PLL_APPLY;
|
||||
end else begin
|
||||
s_active_valid_d = 1'b0;
|
||||
s_error_d = 2'd1;
|
||||
s_state_d = PLL_RESPOND;
|
||||
end
|
||||
end
|
||||
3'b010: begin //3*clk 72MHz
|
||||
s_pll_bp = 1'b0;
|
||||
s_pll_M = 8'd24;
|
||||
s_pll_N = 4'd2;
|
||||
s_pll_OD = 2'd2;
|
||||
PLL_APPLY: begin
|
||||
s_lock_count_d = '0;
|
||||
s_state_d = PLL_WAIT_LOCK;
|
||||
end
|
||||
3'b011: begin //4*clk 96MHz
|
||||
s_pll_bp = 1'b0;
|
||||
s_pll_M = 8'd32;
|
||||
s_pll_N = 4'd2;
|
||||
s_pll_OD = 2'd2;
|
||||
PLL_WAIT_LOCK: begin
|
||||
if (pll_lock_i) begin
|
||||
s_active_sel_d = s_pll_sel_q;
|
||||
s_active_valid_d = 1'b1;
|
||||
s_safe_clk_d = 1'b0;
|
||||
s_lock_d = 1'b1;
|
||||
s_error_d = 2'd0;
|
||||
s_state_d = PLL_SWITCH;
|
||||
end else if (s_lock_count_q == LOCK_TIMEOUT - 1) begin
|
||||
s_active_valid_d = 1'b0;
|
||||
s_safe_clk_d = 1'b1;
|
||||
s_lock_d = 1'b0;
|
||||
s_error_d = 2'd2;
|
||||
s_state_d = PLL_RESPOND;
|
||||
end else begin
|
||||
s_lock_count_d = s_lock_count_q + 1'b1;
|
||||
end
|
||||
end
|
||||
3'b100: begin //5*clk 120MHz
|
||||
s_pll_bp = 1'b0;
|
||||
s_pll_M = 8'd40;
|
||||
s_pll_N = 4'd2;
|
||||
s_pll_OD = 2'd2;
|
||||
PLL_SWITCH: begin
|
||||
s_select_ext_clk_d = 1'b0;
|
||||
s_state_d = PLL_RESPOND;
|
||||
end
|
||||
3'b101: begin //6*clk 144MHz
|
||||
s_pll_bp = 1'b0;
|
||||
s_pll_M = 8'd48;
|
||||
s_pll_N = 4'd2;
|
||||
s_pll_OD = 2'd2;
|
||||
PLL_RESPOND: begin
|
||||
s_rsp_valid_d = 1'b1;
|
||||
if (s_rsp_valid_q && s_rsp_ready) begin
|
||||
s_rsp_valid_d = 1'b0;
|
||||
s_state_d = PLL_IDLE;
|
||||
end
|
||||
end
|
||||
3'b110: begin //7*clk 168MHz
|
||||
s_pll_bp = 1'b0;
|
||||
s_pll_M = 8'd56;
|
||||
s_pll_N = 4'd2;
|
||||
s_pll_OD = 2'd2;
|
||||
end
|
||||
3'b111: begin //8*clk 192MHz
|
||||
s_pll_bp = 1'b0;
|
||||
s_pll_M = 8'd64;
|
||||
s_pll_N = 4'd4;
|
||||
s_pll_OD = 2'd1;
|
||||
end
|
||||
default: begin //bypass
|
||||
s_pll_bp = 1'b1;
|
||||
s_pll_M = 8'd20;
|
||||
s_pll_N = 4'd2;
|
||||
s_pll_OD = 2'd1;
|
||||
default: begin
|
||||
s_state_d = PLL_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// Register PLL config outputs to break the comb path to PLL macro
|
||||
always_ff @(posedge s_ext_clk_buf or negedge ext_rst_n_i) begin
|
||||
if (~ext_rst_n_i) begin
|
||||
s_pll_bp_q <= 1'b1;
|
||||
s_pll_M_q <= 8'd20;
|
||||
s_pll_N_q <= 4'd2;
|
||||
s_pll_OD_q <= 2'd1;
|
||||
end else begin
|
||||
s_pll_bp_q <= s_pll_bp;
|
||||
s_pll_M_q <= s_pll_M;
|
||||
s_pll_N_q <= s_pll_N;
|
||||
s_pll_OD_q <= s_pll_OD;
|
||||
end
|
||||
end
|
||||
|
||||
tc_pll u_tc_pll (
|
||||
.fref_i (s_xtal_clk_buf),
|
||||
.rst_n_i (s_ext_rst_n_sync),
|
||||
.refdiv_i (s_pll_M_q),
|
||||
.fbdiv_i (),
|
||||
.postdiv1_i(s_pll_N_q),
|
||||
.postdiv2_i(s_pll_OD_q),
|
||||
.bp_i (clk_bypass_i || s_pll_bp_q),
|
||||
.pll_lock_o(s_pll_lock),
|
||||
.pll_clk_o (s_pll_clk)
|
||||
dffrc #(3, PLL_IDLE) u_state_dffrc (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_state_d,
|
||||
s_state_q
|
||||
);
|
||||
dffr #(3) u_pll_sel_dffr (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_pll_sel_d,
|
||||
s_pll_sel_q
|
||||
);
|
||||
dffr #(1) u_pll_apply_dffr (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_pll_apply_d,
|
||||
s_pll_apply_q
|
||||
);
|
||||
dffrc #(1, 1'b1) u_select_ext_clk_dffrc (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_select_ext_clk_d,
|
||||
s_select_ext_clk_q
|
||||
);
|
||||
dffr #(16) u_lock_count_dffr (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_lock_count_d,
|
||||
s_lock_count_q
|
||||
);
|
||||
dffr #(3) u_active_sel_dffr (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_active_sel_d,
|
||||
s_active_sel_q
|
||||
);
|
||||
dffr #(1) u_active_valid_dffr (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_active_valid_d,
|
||||
s_active_valid_q
|
||||
);
|
||||
dffrc #(1, 1'b1) u_safe_clk_dffrc (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_safe_clk_d,
|
||||
s_safe_clk_q
|
||||
);
|
||||
dffr #(1) u_lock_dffr (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_lock_d,
|
||||
s_lock_q
|
||||
);
|
||||
dffr #(2) u_error_dffr (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_error_d,
|
||||
s_error_q
|
||||
);
|
||||
dffr #(1) u_rsp_valid_dffr (
|
||||
ext_clk_i,
|
||||
ext_rst_n_i,
|
||||
s_rsp_valid_d,
|
||||
s_rsp_valid_q
|
||||
);
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
@@ -18,6 +18,7 @@ module retrosoc (
|
||||
input logic clk_aud_i,
|
||||
input logic rst_aud_n_i,
|
||||
input logic clkdiv4_i,
|
||||
pll_ctrl_if.sysctrl pll_ctrl,
|
||||
`ifdef CORE_MDD
|
||||
input logic [`USER_CORESEL_WIDTH-1:0] core_sel_i,
|
||||
`endif
|
||||
@@ -409,6 +410,7 @@ module retrosoc (
|
||||
.xpi (xpi),
|
||||
.dma_nmi (u_dma_nmi_if),
|
||||
.sysctrl (u_sysctrl_if),
|
||||
.pll_ctrl (pll_ctrl),
|
||||
.sdram (sdram),
|
||||
.dvp (u_dvp_if),
|
||||
.sdio (u_sdio_if),
|
||||
|
||||
@@ -20,10 +20,6 @@ module retrosoc_asic (
|
||||
`ifdef HAVE_PLL
|
||||
input xi_i_pad,
|
||||
output xo_o_pad,
|
||||
inout clk_bypass_i_pad,
|
||||
inout pll_cfg_0_i_pad,
|
||||
inout pll_cfg_1_i_pad,
|
||||
inout pll_cfg_2_i_pad,
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
inout core_sel_0_i_pad,
|
||||
@@ -142,9 +138,7 @@ module retrosoc_asic (
|
||||
logic s_aud_clk;
|
||||
logic s_sys_clkdiv4;
|
||||
`ifdef HAVE_PLL
|
||||
logic s_xtal_io;
|
||||
logic s_clk_bypass;
|
||||
logic [2:0] s_pll_cfg;
|
||||
logic s_xtal_io;
|
||||
`endif
|
||||
logic s_sys_clk;
|
||||
logic s_ext_rst_n;
|
||||
@@ -174,6 +168,7 @@ module retrosoc_asic (
|
||||
uart_if u_uart0_if ();
|
||||
xpi_if u_xpi_if ();
|
||||
sdram_if u_sdram_if ();
|
||||
pll_ctrl_if u_pll_ctrl_if ();
|
||||
|
||||
|
||||
tc_io_tri_pad u_extclk_i_pad (.pad(extclk_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_ext_clk));
|
||||
@@ -181,10 +176,6 @@ module retrosoc_asic (
|
||||
tc_io_tri_schmitt_pad u_ext_rst_n_i_pad (.pad(ext_rst_n_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_ext_rst_n));
|
||||
`ifdef HAVE_PLL
|
||||
tc_io_xtl_pad u_xtal_io_pad (.xi_pad(xi_i_pad), .xo_pad(xo_o_pad), .en(1'b1), .clk(s_xtal_io));
|
||||
tc_io_tri_pad u_clk_bypass_i_pad (.pad(clk_bypass_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_clk_bypass));
|
||||
tc_io_tri_pad u_pll_cfg_0_i_pad (.pad(pll_cfg_0_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_pll_cfg[0]));
|
||||
tc_io_tri_pad u_pll_cfg_1_i_pad (.pad(pll_cfg_1_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_pll_cfg[1]));
|
||||
tc_io_tri_pad u_pll_cfg_2_i_pad (.pad(pll_cfg_2_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_pll_cfg[2]));
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
tc_io_tri_pad u_core_sel_0_i_pad (.pad(core_sel_0_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_core_sel[0]));
|
||||
@@ -307,9 +298,8 @@ module retrosoc_asic (
|
||||
.ext_rst_n_i (s_ext_rst_n),
|
||||
`ifdef HAVE_PLL
|
||||
.xtal_clk_i (s_xtal_io),
|
||||
.clk_bypass_i (s_clk_bypass),
|
||||
.pll_cfg_i (s_pll_cfg),
|
||||
`endif
|
||||
.pll_ctrl (u_pll_ctrl_if),
|
||||
.sys_clk_o (s_sys_clk),
|
||||
.sys_rst_n_o (s_sys_rst_n),
|
||||
.aud_rst_n_o (s_aud_rst_n),
|
||||
@@ -329,6 +319,7 @@ module retrosoc_asic (
|
||||
.clk_aud_i (s_aud_clk),
|
||||
.rst_aud_n_i(s_aud_rst_n),
|
||||
.clkdiv4_i (s_sys_clkdiv4),
|
||||
.pll_ctrl (u_pll_ctrl_if),
|
||||
`ifdef CORE_MDD
|
||||
.core_sel_i (s_core_sel),
|
||||
`endif
|
||||
|
||||
@@ -118,6 +118,28 @@ module tc_clk_mux2 (
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
// Dynamic clock switching is enabled only with the behavioral PLL backend.
|
||||
// Silicon backends keep capability low until this wrapper is replaced by a
|
||||
// characterized, glitch-free clock-switch cell.
|
||||
module tc_clk_switch2 (
|
||||
input logic clk0_i,
|
||||
input logic clk1_i,
|
||||
input logic clk_sel_i,
|
||||
output logic clk_o
|
||||
);
|
||||
|
||||
`ifdef PDK_BEHAV
|
||||
assign clk_o = clk_sel_i ? clk1_i : clk0_i;
|
||||
`else
|
||||
tc_clk_mux2 u_tc_clk_mux2 (
|
||||
.clk0_i (clk0_i),
|
||||
.clk1_i (clk1_i),
|
||||
.clk_sel_i(clk_sel_i),
|
||||
.clk_o (clk_o)
|
||||
);
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
module tc_clk_xor2 (
|
||||
input logic clk0_i,
|
||||
input logic clk1_i,
|
||||
|
||||
+98
-56
@@ -5,77 +5,119 @@
|
||||
// http://license.coscl.org.cn/MulanPSL2
|
||||
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
module tc_pll (
|
||||
input logic fref_i,
|
||||
input logic rst_n_i,
|
||||
input logic [ 7:0] refdiv_i,
|
||||
input logic [11:0] fbdiv_i,
|
||||
input logic [ 3:0] postdiv1_i,
|
||||
input logic [ 1:0] postdiv2_i,
|
||||
input logic bp_i,
|
||||
output logic pll_lock_o,
|
||||
output logic pll_clk_o
|
||||
input logic fref_i,
|
||||
input logic rst_n_i,
|
||||
input logic [2:0] cfg_sel_i,
|
||||
input logic cfg_apply_i,
|
||||
output logic pll_capable_o,
|
||||
output logic pll_lock_o,
|
||||
output logic pll_clk_o
|
||||
);
|
||||
|
||||
`ifdef PDK_BEHAV
|
||||
assign pll_lock_o = 1'b1;
|
||||
assign pll_clk_o = fref_i;
|
||||
`elsif PDK_IHP130
|
||||
assign pll_lock_o = 1'b1;
|
||||
assign pll_clk_o = fref_i;
|
||||
`elsif PDK_ICS55
|
||||
`ifndef HAVE_PLL
|
||||
assign pll_lock_o = 1'b1;
|
||||
assign pll_clk_o = fref_i;
|
||||
`else
|
||||
localparam logic [2:0] PLL_LOCK_CYCLES = 3'd4;
|
||||
|
||||
`endif
|
||||
`elsif PDK_S110
|
||||
logic [2:0] s_cfg_sel_d, s_cfg_sel_q;
|
||||
logic [2:0] s_lock_count_d, s_lock_count_q;
|
||||
logic s_lock_d, s_lock_q;
|
||||
logic s_apply_seen_d, s_apply_seen_q;
|
||||
logic s_cfg_apply;
|
||||
logic s_force_lock_fail;
|
||||
time s_last_ref_edge;
|
||||
time s_ref_period;
|
||||
|
||||
`ifndef HAVE_PLL
|
||||
assign pll_lock_o = 1'b1;
|
||||
assign pll_clk_o = fref_i;
|
||||
`else
|
||||
`define LOCK_CNT_END 20'h1FFFF
|
||||
function automatic int pll_multiplier(input logic [2:0] cfg_sel);
|
||||
case (cfg_sel)
|
||||
3'd0: pll_multiplier = 1;
|
||||
3'd1: pll_multiplier = 2;
|
||||
3'd2: pll_multiplier = 3;
|
||||
3'd3: pll_multiplier = 4;
|
||||
3'd4: pll_multiplier = 5;
|
||||
3'd5: pll_multiplier = 6;
|
||||
3'd6: pll_multiplier = 7;
|
||||
default: pll_multiplier = 8;
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
logic [19:0] s_lock_cnt_d, s_lock_cnt_q;
|
||||
initial begin
|
||||
s_force_lock_fail = $test$plusargs("pll_lock_fail");
|
||||
s_last_ref_edge = 0;
|
||||
s_ref_period = 0;
|
||||
pll_clk_o = 1'b0;
|
||||
end
|
||||
|
||||
assign pll_lock_o = s_lock_cnt_q == `LOCK_CNT_END;
|
||||
//lock Time Max 0.5ms(500us, 500*1000ns)
|
||||
assign s_lock_cnt_d = s_lock_cnt_q + 20'h1;
|
||||
dffer #(20) u_lock_cnt_dffer (
|
||||
always @(posedge fref_i) begin
|
||||
if (s_last_ref_edge != 0) begin
|
||||
s_ref_period = $time - s_last_ref_edge;
|
||||
end
|
||||
s_last_ref_edge = $time;
|
||||
end
|
||||
|
||||
always begin
|
||||
@(posedge fref_i);
|
||||
wait (pll_lock_o);
|
||||
while (pll_lock_o) begin
|
||||
#(s_ref_period / (2 * pll_multiplier(s_cfg_sel_q)));
|
||||
if (pll_lock_o) begin
|
||||
pll_clk_o = ~pll_clk_o;
|
||||
end
|
||||
end
|
||||
pll_clk_o = 1'b0;
|
||||
end
|
||||
|
||||
assign pll_capable_o = 1'b1;
|
||||
assign pll_lock_o = s_lock_q;
|
||||
assign s_cfg_apply = cfg_apply_i && !s_apply_seen_q;
|
||||
assign s_cfg_sel_d = cfg_sel_i;
|
||||
dffer #(3) u_cfg_sel_dffer (
|
||||
fref_i,
|
||||
rst_n_i,
|
||||
s_lock_cnt_q < `LOCK_CNT_END,
|
||||
s_lock_cnt_d,
|
||||
s_lock_cnt_q
|
||||
s_cfg_apply,
|
||||
s_cfg_sel_d,
|
||||
s_cfg_sel_q
|
||||
);
|
||||
|
||||
S013PLLFN u0_pll (
|
||||
// .A2VDD33 (),
|
||||
// .A2VSS33 (),
|
||||
// .AVDD33 (),
|
||||
// .AVSS33 (),
|
||||
// .DVDD12 (),
|
||||
// .DVSS12 (),
|
||||
.XIN (fref_i),
|
||||
.CLK_OUT (pll_clk_o),
|
||||
.N (postdiv1_i),
|
||||
.M (refdiv_i),
|
||||
.RESET ('0),
|
||||
.SLEEP12 ('0),
|
||||
.OD (postdiv2_i),
|
||||
.BP (bp_i),
|
||||
.SELECT (1'b1),
|
||||
.FS ('0),
|
||||
.FRAC_N_in('0),
|
||||
.LKDT ()
|
||||
assign s_apply_seen_d = cfg_apply_i;
|
||||
dffr #(1) u_apply_seen_dffr (
|
||||
fref_i,
|
||||
rst_n_i,
|
||||
s_apply_seen_d,
|
||||
s_apply_seen_q
|
||||
);
|
||||
|
||||
`endif
|
||||
always_comb begin
|
||||
s_lock_count_d = s_lock_count_q;
|
||||
s_lock_d = s_lock_q;
|
||||
if (s_cfg_apply) begin
|
||||
s_lock_count_d = '0;
|
||||
s_lock_d = 1'b0;
|
||||
end else if (!s_lock_q && !s_force_lock_fail) begin
|
||||
if (s_lock_count_q == PLL_LOCK_CYCLES - 1'b1) begin
|
||||
s_lock_d = 1'b1;
|
||||
end else begin
|
||||
s_lock_count_d = s_lock_count_q + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
dffr #(3) u_lock_count_dffr (
|
||||
fref_i,
|
||||
rst_n_i,
|
||||
s_lock_count_d,
|
||||
s_lock_count_q
|
||||
);
|
||||
dffr #(1) u_lock_dffr (
|
||||
fref_i,
|
||||
rst_n_i,
|
||||
s_lock_d,
|
||||
s_lock_q
|
||||
);
|
||||
`else
|
||||
assign pll_capable_o = 1'b0;
|
||||
assign pll_lock_o = 1'b0;
|
||||
assign pll_clk_o = fref_i;
|
||||
`endif
|
||||
endmodule
|
||||
+15
-167
@@ -1,184 +1,32 @@
|
||||
# mini gen2 plus
|
||||
# set_units -time ns -capacitance pF -current mA -voltage V -resistance kOhm
|
||||
# Mini SoC default external-safe-clock timing mode.
|
||||
# Dynamic PLL timing modes are enabled only after a PDK backend supplies a
|
||||
# characterized PLL macro and a glitch-free switch cell.
|
||||
|
||||
# unit: MHz
|
||||
set clk_xtal_freq 24.0
|
||||
set clk_ext_freq 72.0
|
||||
set clk_aud_freq 18.432
|
||||
set clk_ext_freq 72.0
|
||||
set clk_aud_freq 18.432
|
||||
set clk_ext_period [expr 1000.0 / $clk_ext_freq]
|
||||
set clk_aud_period [expr 1000.0 / $clk_aud_freq]
|
||||
|
||||
set clk_xtal_period [expr 1000.0 / $clk_xtal_freq]
|
||||
set clk_ext_period [expr 1000.0 / $clk_ext_freq]
|
||||
set clk_aud_period [expr 1000.0 / $clk_aud_freq]
|
||||
|
||||
set clk_period_factor .2
|
||||
|
||||
# set_operating_conditions -analysis_type on_chip_variation -library [get_libs {ETSCA_N55_H7BH_DSS_PRCMAX_V1P0_T125.db:ETSCA_N55_H7BH_DSS_PRCMAX_V1P0_T125}]
|
||||
###############################################################################
|
||||
# Clock Related Information
|
||||
###############################################################################
|
||||
create_clock -name clk_ext -period $clk_ext_period [get_ports extclk_i_pad]
|
||||
create_clock -name clk_aud -period $clk_aud_period [get_ports audclk_i_pad]
|
||||
###############################################################################
|
||||
# Derived Clock related information
|
||||
###############################################################################
|
||||
create_generated_clock -name clk_i2s_mclk_o -source [get_pins \u_rcu.u_aud_clk_buf/clk_o] -divide_by 1 [get_ports gpio_10_io_pad]
|
||||
set_clock_uncertainty -setup 0.2 [get_clocks clk_i2s_mclk_o]
|
||||
set_clock_uncertainty -hold 0.1 [get_clocks clk_i2s_mclk_o]
|
||||
###############################################################################
|
||||
# Point to Point exceptions
|
||||
###############################################################################
|
||||
# group_path -name CLK_u_xtal_io_pad_u_P65_1233_PWE_XC_in2reg -from [get_ports {xi_i_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_rx_i_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_miso_i_pad}] -to [get_clocks {CLK_u_xtal_io_pad_u_P65_1233_PWE_XC}]
|
||||
# group_path -name CLK_u_xtal_io_pad_u_P65_1233_PWE_XC_reg2out -from [get_clocks {CLK_u_xtal_io_pad_u_P65_1233_PWE_XC}] -to [get_ports {xo_o_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad sys_clkdiv4_o_pad uart_tx_o_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_tx_o_pad cust_uart_rx_i_pad cust_pwm_pwm_0_o_pad cust_pwm_pwm_1_o_pad cust_pwm_pwm_2_o_pad cust_pwm_pwm_3_o_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_spi_clk_o_pad cust_qspi_spi_csn_0_o_pad cust_qspi_spi_csn_1_o_pad cust_qspi_spi_csn_2_o_pad cust_qspi_spi_csn_3_o_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sclk_o_pad cust_psram_ce_o_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_clk_o_pad cust_spfs_cs_o_pad cust_spfs_mosi_o_pad cust_spfs_miso_i_pad}]
|
||||
# group_path -name CLK_u_extclk_i_pad_u_P65_1233_PBMUX_C_in2reg -from [get_ports {xi_i_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_rx_i_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_miso_i_pad}] -to [get_clocks {clk_ext}]
|
||||
# group_path -name CLK_u_extclk_i_pad_u_P65_1233_PBMUX_C_reg2out -from [get_clocks {clk_ext}] -to [get_ports {xo_o_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad sys_clkdiv4_o_pad uart_tx_o_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_tx_o_pad cust_uart_rx_i_pad cust_pwm_pwm_0_o_pad cust_pwm_pwm_1_o_pad cust_pwm_pwm_2_o_pad cust_pwm_pwm_3_o_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_spi_clk_o_pad cust_qspi_spi_csn_0_o_pad cust_qspi_spi_csn_1_o_pad cust_qspi_spi_csn_2_o_pad cust_qspi_spi_csn_3_o_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sclk_o_pad cust_psram_ce_o_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_clk_o_pad cust_spfs_cs_o_pad cust_spfs_mosi_o_pad cust_spfs_miso_i_pad}]
|
||||
# group_path -name CLK_u_rcu_u_pll_clk_buf_u_BUFX0P7H7L_Y_in2reg -from [get_ports {xi_i_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_rx_i_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_miso_i_pad}] -to [get_clocks {CLK_u_rcu_u_pll_clk_buf_u_BUFX0P7H7L_Y}]
|
||||
# group_path -name CLK_u_rcu_u_pll_clk_buf_u_BUFX0P7H7L_Y_reg2out -from [get_clocks {CLK_u_rcu_u_pll_clk_buf_u_BUFX0P7H7L_Y}] -to [get_ports {xo_o_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad sys_clkdiv4_o_pad uart_tx_o_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_tx_o_pad cust_uart_rx_i_pad cust_pwm_pwm_0_o_pad cust_pwm_pwm_1_o_pad cust_pwm_pwm_2_o_pad cust_pwm_pwm_3_o_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_spi_clk_o_pad cust_qspi_spi_csn_0_o_pad cust_qspi_spi_csn_1_o_pad cust_qspi_spi_csn_2_o_pad cust_qspi_spi_csn_3_o_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sclk_o_pad cust_psram_ce_o_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_clk_o_pad cust_spfs_cs_o_pad cust_spfs_mosi_o_pad cust_spfs_miso_i_pad}]
|
||||
# group_path -name CLK_sys_clk_buf_in2reg -from [get_ports {xi_i_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_rx_i_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_miso_i_pad}] -to [get_clocks {CLK_sys_clk_buf}]
|
||||
# group_path -name CLK_sys_clk_buf_reg2out -from [get_clocks {CLK_sys_clk_buf}] -to [get_ports {xo_o_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad sys_clkdiv4_o_pad uart_tx_o_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_tx_o_pad cust_uart_rx_i_pad cust_pwm_pwm_0_o_pad cust_pwm_pwm_1_o_pad cust_pwm_pwm_2_o_pad cust_pwm_pwm_3_o_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_spi_clk_o_pad cust_qspi_spi_csn_0_o_pad cust_qspi_spi_csn_1_o_pad cust_qspi_spi_csn_2_o_pad cust_qspi_spi_csn_3_o_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sclk_o_pad cust_psram_ce_o_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_clk_o_pad cust_spfs_cs_o_pad cust_spfs_mosi_o_pad cust_spfs_miso_i_pad}]
|
||||
# group_path -name CLK_cust_qspi_spi_clk_o_in2reg -from [get_ports {xi_i_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_rx_i_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_miso_i_pad}] -to [get_clocks {CLK_cust_qspi_spi_clk_o}]
|
||||
# group_path -name CLK_cust_qspi_spi_clk_o_reg2out -from [get_clocks {CLK_cust_qspi_spi_clk_o}] -to [get_ports {xo_o_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad sys_clkdiv4_o_pad uart_tx_o_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_tx_o_pad cust_uart_rx_i_pad cust_pwm_pwm_0_o_pad cust_pwm_pwm_1_o_pad cust_pwm_pwm_2_o_pad cust_pwm_pwm_3_o_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_spi_clk_o_pad cust_qspi_spi_csn_0_o_pad cust_qspi_spi_csn_1_o_pad cust_qspi_spi_csn_2_o_pad cust_qspi_spi_csn_3_o_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sclk_o_pad cust_psram_ce_o_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_clk_o_pad cust_spfs_cs_o_pad cust_spfs_mosi_o_pad cust_spfs_miso_i_pad}]
|
||||
# group_path -name CLK_cust_psram_sclk_o_in2reg -from [get_ports {xi_i_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_rx_i_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_miso_i_pad}] -to [get_clocks {CLK_cust_psram_sclk_o}]
|
||||
# group_path -name CLK_cust_psram_sclk_o_reg2out -from [get_clocks {CLK_cust_psram_sclk_o}] -to [get_ports {xo_o_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad sys_clkdiv4_o_pad uart_tx_o_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_tx_o_pad cust_uart_rx_i_pad cust_pwm_pwm_0_o_pad cust_pwm_pwm_1_o_pad cust_pwm_pwm_2_o_pad cust_pwm_pwm_3_o_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_spi_clk_o_pad cust_qspi_spi_csn_0_o_pad cust_qspi_spi_csn_1_o_pad cust_qspi_spi_csn_2_o_pad cust_qspi_spi_csn_3_o_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sclk_o_pad cust_psram_ce_o_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_clk_o_pad cust_spfs_cs_o_pad cust_spfs_mosi_o_pad cust_spfs_miso_i_pad}]
|
||||
# group_path -name CLK_cust_spfs_clk_o_in2reg -from [get_ports {xi_i_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_rx_i_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_miso_i_pad}] -to [get_clocks {CLK_cust_spfs_clk_o}]
|
||||
# group_path -name CLK_cust_spfs_clk_o_reg2out -from [get_clocks {CLK_cust_spfs_clk_o}] -to [get_ports {xo_o_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad sys_clkdiv4_o_pad uart_tx_o_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_tx_o_pad cust_uart_rx_i_pad cust_pwm_pwm_0_o_pad cust_pwm_pwm_1_o_pad cust_pwm_pwm_2_o_pad cust_pwm_pwm_3_o_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_spi_clk_o_pad cust_qspi_spi_csn_0_o_pad cust_qspi_spi_csn_1_o_pad cust_qspi_spi_csn_2_o_pad cust_qspi_spi_csn_3_o_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sclk_o_pad cust_psram_ce_o_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_clk_o_pad cust_spfs_cs_o_pad cust_spfs_mosi_o_pad cust_spfs_miso_i_pad}]
|
||||
# group_path -name all_in2out -from [get_ports {xi_i_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_rx_i_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_miso_i_pad}] -to [get_ports {xo_o_pad extclk_i_pad pll_cfg_0_i_pad pll_cfg_1_i_pad pll_cfg_2_i_pad clk_bypass_i_pad ext_rst_n_i_pad sys_clkdiv4_o_pad uart_tx_o_pad uart_rx_i_pad gpio_0_io_pad gpio_1_io_pad gpio_2_io_pad gpio_3_io_pad gpio_4_io_pad gpio_5_io_pad gpio_6_io_pad gpio_7_io_pad gpio_8_io_pad gpio_9_io_pad gpio_10_io_pad gpio_11_io_pad gpio_12_io_pad gpio_13_io_pad gpio_14_io_pad gpio_15_io_pad irq_pin_i_pad cust_uart_tx_o_pad cust_uart_rx_i_pad cust_pwm_pwm_0_o_pad cust_pwm_pwm_1_o_pad cust_pwm_pwm_2_o_pad cust_pwm_pwm_3_o_pad cust_ps2_ps2_clk_i_pad cust_ps2_ps2_dat_i_pad cust_i2c_scl_io_pad cust_i2c_sda_io_pad cust_qspi_spi_clk_o_pad cust_qspi_spi_csn_0_o_pad cust_qspi_spi_csn_1_o_pad cust_qspi_spi_csn_2_o_pad cust_qspi_spi_csn_3_o_pad cust_qspi_dat_0_io_pad cust_qspi_dat_1_io_pad cust_qspi_dat_2_io_pad cust_qspi_dat_3_io_pad cust_psram_sclk_o_pad cust_psram_ce_o_pad cust_psram_sio0_io_pad cust_psram_sio1_io_pad cust_psram_sio2_io_pad cust_psram_sio3_io_pad cust_spfs_clk_o_pad cust_spfs_cs_o_pad cust_spfs_mosi_o_pad cust_spfs_miso_i_pad}]
|
||||
# set_case_analysis 1 [get_pins {u_rcu.u_sys_mux.u_MUX2X0P5H7L/S0}]
|
||||
create_generated_clock -name clk_i2s_mclk_o -source [get_pins \u_rcu.u_aud_clk_buf/clk_o] \
|
||||
-divide_by 1 [get_ports gpio_10_io_pad]
|
||||
|
||||
set_input_transition .1 [all_inputs]
|
||||
set_clock_uncertainty -setup 0.2 [get_clocks clk_ext]
|
||||
set_clock_uncertainty -hold 0.1 [get_clocks clk_ext]
|
||||
set_clock_uncertainty -hold 0.1 [get_clocks clk_ext]
|
||||
set_clock_uncertainty -setup 0.2 [get_clocks clk_aud]
|
||||
set_clock_uncertainty -hold 0.1 [get_clocks clk_aud]
|
||||
set_clock_uncertainty -hold 0.1 [get_clocks clk_aud]
|
||||
set_clock_uncertainty -setup 0.2 [get_clocks clk_i2s_mclk_o]
|
||||
set_clock_uncertainty -hold 0.1 [get_clocks clk_i2s_mclk_o]
|
||||
|
||||
set_timing_derate -cell_delay -net_delay -late 1
|
||||
set_timing_derate -net_delay -clock -early 0.95
|
||||
set_timing_derate -net_delay -data -early 1
|
||||
set_timing_derate -net_delay -clock -early 0.95
|
||||
set_timing_derate -net_delay -data -early 1
|
||||
set_timing_derate -cell_delay -clock -early 0.95
|
||||
set_timing_derate -cell_delay -data -early 1
|
||||
# Clock Group
|
||||
###############################################################################
|
||||
set_clock_groups -name cgp_async -asynchronous -group [get_clocks clk_ext] -group [get_clocks clk_aud]
|
||||
###############################################################################
|
||||
# Input/Output Delay
|
||||
###############################################################################
|
||||
set_clock_groups -name cgp_async -asynchronous -group [get_clocks clk_ext] \
|
||||
-group [get_clocks clk_aud]
|
||||
|
||||
###############################################################################
|
||||
# Pin drive/load
|
||||
###############################################################################
|
||||
# set_load -pin_load 8 [get_ports extclk_i_pad]
|
||||
# set_load -pin_load 8 [get_ports audclk_i_pad]
|
||||
# set_load -pin_load 8 [get_ports ext_rst_n_i_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_0_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_1_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_2_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_3_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_4_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_5_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_6_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_7_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_8_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_9_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_10_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_11_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_12_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_13_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_14_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_15_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_16_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_17_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_18_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_19_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_20_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_21_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_22_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_23_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_24_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_25_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_26_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_27_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_28_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_29_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_30_io_pad]
|
||||
# set_load -pin_load 8 [get_ports gpio_31_io_pad]
|
||||
# set_load -pin_load 8 [get_ports uart0_tx_o_pad]
|
||||
# set_load -pin_load 8 [get_ports uart0_rx_i_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_sck_o_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_nss0_o_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_nss1_o_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_nss2_o_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_nss3_o_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_dat0_io_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_dat1_io_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_dat2_io_pad]
|
||||
# set_load -pin_load 8 [get_ports xpi_dat3_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_clk_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_cke_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_cs_n_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_ras_n_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_cas_n_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_we_n_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_ba0_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_ba1_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr0_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr1_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr2_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr3_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr4_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr5_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr6_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr7_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr8_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr9_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr10_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr11_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_addr12_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dqm0_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dqm1_o_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq0_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq1_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq2_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq3_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq4_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq5_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq6_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq7_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq8_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq9_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq10_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq11_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq12_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq13_io_pad]
|
||||
# set_load -pin_load 8 [get_ports sdram_dq14_io_pad]
|
||||
###############################################################################
|
||||
# False Path
|
||||
###############################################################################
|
||||
set_false_path -from [get_cells \u_rcu.u_ext_rst_sync*]
|
||||
set_false_path -from [get_cells s_sys_rst_n_reg]
|
||||
set_false_path -from [get_cells \u_rcu.u_aud_rst_sync*]
|
||||
set_false_path -from [get_cells s_aud_rst_n_reg]
|
||||
|
||||
###############################################################################
|
||||
|
||||
# set_wire_load_mode top
|
||||
# set_max_fanout 32 [current_design]
|
||||
# set_max_transition 1.7 [get_clocks {CLK_sys_clk_buf}] -clock_path -rise
|
||||
# set_max_transition 1.7 [get_clocks {CLK_sys_clk_buf}] -clock_path -fall
|
||||
# set_max_transition 3.4 [get_clocks {CLK_sys_clk_buf}] -data_path -rise
|
||||
# set_max_transition 3.4 [get_clocks {CLK_sys_clk_buf}] -data_path -fall
|
||||
# set_max_transition 7.083333 [get_clocks {CLK_u_xtal_io_pad_u_P65_1233_PWE_XC}] -clock_path -rise
|
||||
# set_max_transition 7.083333 [get_clocks {CLK_u_xtal_io_pad_u_P65_1233_PWE_XC}] -clock_path -fall
|
||||
# set_max_transition 14.166667 [get_clocks {CLK_u_xtal_io_pad_u_P65_1233_PWE_XC}] -data_path -rise
|
||||
# set_max_transition 14.166667 [get_clocks {CLK_u_xtal_io_pad_u_P65_1233_PWE_XC}] -data_path -fall
|
||||
# set_max_transition 1.7 [get_clocks {clk_ext}] -clock_path -rise
|
||||
# set_max_transition 1.7 [get_clocks {clk_ext}] -clock_path -fall
|
||||
# set_max_transition 3.4 [get_clocks {clk_ext}] -data_path -rise
|
||||
# set_max_transition 3.4 [get_clocks {clk_ext}] -data_path -fall
|
||||
# set_max_transition 7.083333 [get_clocks {CLK_u_rcu_u_pll_clk_buf_u_BUFX0P7H7L_Y}] -clock_path -rise
|
||||
# set_max_transition 7.083333 [get_clocks {CLK_u_rcu_u_pll_clk_buf_u_BUFX0P7H7L_Y}] -clock_path -fall
|
||||
# set_max_transition 14.166667 [get_clocks {CLK_u_rcu_u_pll_clk_buf_u_BUFX0P7H7L_Y}] -data_path -rise
|
||||
# set_max_transition 14.166667 [get_clocks {CLK_u_rcu_u_pll_clk_buf_u_BUFX0P7H7L_Y}] -data_path -fall
|
||||
# ###############################################################################
|
||||
# # POCV Information
|
||||
# ###############################################################################
|
||||
@@ -1,40 +1,10 @@
|
||||
#24MHz
|
||||
set clk_xtal_period 41.67
|
||||
#120MHz
|
||||
set clk_ext_period 8.33
|
||||
set clk_period_factor .2
|
||||
# clk src
|
||||
create_clock -name CLK_src_xtal -period $clk_xtal_period xi_i_pad
|
||||
create_clock -name CLK_src_ext -period $clk_ext_period extclk_i_pad
|
||||
# clk buf
|
||||
create_generated_clock -name CLK_xtal_buf -source \u_rcu.u_xtal_buf.i_buf/I -master_clock CLK_src_xtal -divide_by 1 \u_rcu.u_xtal_buf.i_buf/Z
|
||||
create_generated_clock -name CLK_ext_buf -source \u_rcu.u_ext_clk_buf.i_buf/I -master_clock CLK_src_ext -divide_by 1 \u_rcu.u_ext_clk_buf.i_buf/Z
|
||||
create_generated_clock -name CLK_pll -source \u_rcu.u_tc_pll.u0_pll/XIN -master_clock CLK_xtal_buf -multiply_by 4 \u_rcu.u_tc_pll.u0_pll/CLK_OUT
|
||||
create_generated_clock -name CLK_pll_buf -source \u_rcu.u_pll_clk_buf.i_buf/I -master_clock CLK_pll -divide_by 1 \u_rcu.u_pll_clk_buf.i_buf/Z
|
||||
set_clock_groups -logically_exclusive -group {CLK_pll_buf} -group {CLK_ext_buf}
|
||||
set_clock_groups -asynchronous -group {CLK_pll_buf} -group {CLK_ext_buf}
|
||||
# clk mux
|
||||
create_generated_clock -name CLK_sys_mux_pll -source \u_rcu.u_sys_mux.u_LVT_CKMUX2HDV4/I0 -master_clock CLK_pll_buf -divide_by 1 \u_rcu.u_sys_mux.u_LVT_CKMUX2HDV4/Z -add
|
||||
create_generated_clock -name CLK_sys_mux_ext -source \u_rcu.u_sys_mux.u_LVT_CKMUX2HDV4/I1 -master_clock CLK_ext_buf -divide_by 1 \u_rcu.u_sys_mux.u_LVT_CKMUX2HDV4/Z -add
|
||||
create_generated_clock -name CLK_sys_clk_buf -source \u_rcu.u_sys_clk_buf.i_buf/I -master_clock CLK_src_ext -divide_by 1 \u_rcu.u_sys_clk_buf.i_buf/Z
|
||||
set_clock_groups -physically_exclusive -group {CLK_sys_mux_pll} -group {CLK_sys_mux_ext}
|
||||
# set bypass mode
|
||||
set_case_analysis 0 \u_rcu.u_sys_mux.u_LVT_CKMUX2HDV4/S
|
||||
# when bypass xtal_buf
|
||||
# set_clock_groups -asynchronous -group {CLK_xtal_buf} -group {CLK_sys_clk_buf}
|
||||
# ip
|
||||
create_generated_clock -name CLK_flash_clk_o -source \u_retrosoc.u_spimemio.xfer.flash_clk_reg/Q -master_clock CLK_sys_clk_buf -divide_by 2 flash_clk_o_pad
|
||||
create_generated_clock -name CLK_cust_qspi_spi_clk_o -source s_cust_qspi_spi_clk_o_reg/Q -master_clock CLK_sys_clk_buf -divide_by 2 cust_qspi_spi_clk_o_pad
|
||||
create_generated_clock -name CLK_cust_psram_sclk_o -source s_cust_psram_sclk_o_reg/Q -master_clock CLK_sys_clk_buf -divide_by 2 cust_psram_sclk_o_pad
|
||||
create_generated_clock -name CLK_cust_spfs_clk_o -source s_cust_spfs_clk_o_reg/Q -master_clock CLK_sys_clk_buf -divide_by 2 cust_spfs_clk_o_pad
|
||||
# async rst
|
||||
set_false_path -from \u_rcu.s_ext_rst_n_sync_reg
|
||||
set_false_path -from [get_cells \u_rcu.u_tc_pll.s_lock_cnt_*__reg]
|
||||
# in/out
|
||||
# set clk_delay [expr $clk_ext_period * $clk_period_factor]
|
||||
# set_input_delay $clk_delay -clock clk {req_val reset resp_rdy req_msg[*]}
|
||||
# set_input_delay $clk_delay -clock xi_i_pad {}
|
||||
# set_output_delay $clk_delay -clock xi_i_pad [all_outputs]
|
||||
set_input_transition .1 [all_inputs]
|
||||
set_clock_uncertainty -setup .1 [all_clocks]
|
||||
set_clock_uncertainty -hold .1 [all_clocks]
|
||||
# Dynamic PLL timing template.
|
||||
#
|
||||
# This file is intentionally not selected by the default OpenSTA flow. It may
|
||||
# be enabled only after a PDK backend supplies the concrete PLL and
|
||||
# glitch-free clock-switch cell pin names. Sign off every selector mode with
|
||||
# its own generated-clock period (24, 48, 72, 96, 120, 144, 168, 192 MHz),
|
||||
# and declare the external safe clock and PLL clock physically exclusive.
|
||||
#
|
||||
# The current IHP130 and ICS55 wrappers report PLL capability disabled, so
|
||||
# their valid signoff mode is sta/opensta/gen2.sdc.
|
||||
@@ -0,0 +1,170 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module pll_ctrl_tb;
|
||||
logic ext_clk_i = 1'b0;
|
||||
logic xtal_clk_i = 1'b0;
|
||||
logic aud_clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic fault_valid_i = 1'b0;
|
||||
logic [31:0] fault_addr_i = '0;
|
||||
logic [ 3:0] fault_wstrb_i = '0;
|
||||
logic fault_reserved_i = 1'b0;
|
||||
nmi_if nmi ();
|
||||
sysctrl_if sysctrl ();
|
||||
pll_ctrl_if pll_ctrl ();
|
||||
logic sys_clk_o;
|
||||
logic sys_rst_n_o;
|
||||
logic aud_rst_n_o;
|
||||
logic sys_clkdiv4_o;
|
||||
logic [31:0] read_data;
|
||||
time edge_start;
|
||||
time edge_end;
|
||||
|
||||
always #7 ext_clk_i = ~ext_clk_i;
|
||||
always #21 xtal_clk_i = ~xtal_clk_i;
|
||||
always #27 aud_clk_i = ~aud_clk_i;
|
||||
|
||||
rcu u_rcu (
|
||||
.ext_clk_i (ext_clk_i),
|
||||
.aud_clk_i (aud_clk_i),
|
||||
.ext_rst_n_i (rst_n_i),
|
||||
`ifdef HAVE_PLL
|
||||
.xtal_clk_i (xtal_clk_i),
|
||||
`endif
|
||||
.pll_ctrl (pll_ctrl),
|
||||
.sys_clk_o (sys_clk_o),
|
||||
.sys_rst_n_o (sys_rst_n_o),
|
||||
.aud_rst_n_o (aud_rst_n_o),
|
||||
.sys_clkdiv4_o(sys_clkdiv4_o)
|
||||
);
|
||||
|
||||
nmi_sysctrl u_sysctrl (
|
||||
.clk_i (sys_clk_o),
|
||||
.rst_n_i (sys_rst_n_o),
|
||||
.fault_valid_i (fault_valid_i),
|
||||
.fault_addr_i (fault_addr_i),
|
||||
.fault_wstrb_i (fault_wstrb_i),
|
||||
.fault_reserved_i(fault_reserved_i),
|
||||
.nmi (nmi),
|
||||
.sysctrl (sysctrl),
|
||||
.pll_ctrl (pll_ctrl)
|
||||
);
|
||||
|
||||
task automatic read_register(input logic [31:0] address, output logic [31:0] data);
|
||||
begin
|
||||
@(negedge sys_clk_o);
|
||||
nmi.addr = address;
|
||||
nmi.wdata = '0;
|
||||
nmi.wstrb = '0;
|
||||
nmi.valid = 1'b1;
|
||||
while (!nmi.ready) @(posedge sys_clk_o);
|
||||
data = nmi.rdata;
|
||||
@(negedge sys_clk_o);
|
||||
nmi.valid = 1'b0;
|
||||
while (nmi.ready) @(posedge sys_clk_o);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic write_register(input logic [31:0] address, input logic [31:0] data);
|
||||
begin
|
||||
@(negedge sys_clk_o);
|
||||
nmi.addr = address;
|
||||
nmi.wdata = data;
|
||||
nmi.wstrb = 4'hF;
|
||||
nmi.valid = 1'b1;
|
||||
while (!nmi.ready) @(posedge sys_clk_o);
|
||||
@(negedge sys_clk_o);
|
||||
nmi.valid = 1'b0;
|
||||
while (nmi.ready) @(posedge sys_clk_o);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic wait_for_completion(output logic [31:0] status);
|
||||
integer index;
|
||||
logic complete;
|
||||
begin
|
||||
status = '0;
|
||||
complete = 1'b0;
|
||||
for (index = 0; index < 3000; index = index + 1) begin
|
||||
if (!complete) begin
|
||||
read_register(32'h1000_B01C, status);
|
||||
complete = !status[4];
|
||||
end
|
||||
end
|
||||
if (!complete) begin
|
||||
$fatal(1, "pll configuration did not complete");
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
nmi.valid = 1'b0;
|
||||
nmi.addr = '0;
|
||||
nmi.wdata = '0;
|
||||
nmi.wstrb = '0;
|
||||
sysctrl.core_sel_i = '0;
|
||||
#100;
|
||||
rst_n_i = 1'b1;
|
||||
repeat (12) @(posedge sys_clk_o);
|
||||
|
||||
read_register(32'h1000_B01C, read_data);
|
||||
`ifdef HAVE_PLL
|
||||
if (read_data !== 32'h0000_0500) begin
|
||||
$fatal(1, "pll reset status is not the external safe clock");
|
||||
end
|
||||
`else
|
||||
if (read_data !== 32'h0000_0100) begin
|
||||
$fatal(1, "unsupported pll reset status is not the external safe clock");
|
||||
end
|
||||
`endif
|
||||
|
||||
write_register(32'h1000_B008, 32'd4);
|
||||
write_register(32'h1000_B00C, 32'd1);
|
||||
wait_for_completion(read_data);
|
||||
|
||||
`ifdef HAVE_PLL
|
||||
if ($test$plusargs("pll_lock_fail")) begin
|
||||
if (read_data !== 32'h0000_05A0) begin
|
||||
$fatal(1, "pll lock timeout did not keep the external safe clock");
|
||||
end
|
||||
$display("pll controller timeout test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (read_data !== 32'h0000_060C) begin
|
||||
$fatal(1, "pll configuration did not select the requested frequency");
|
||||
end
|
||||
repeat (4) @(posedge sys_clk_o);
|
||||
@(posedge sys_clk_o);
|
||||
edge_start = $time;
|
||||
@(posedge sys_clk_o);
|
||||
edge_end = $time;
|
||||
if ((edge_end - edge_start) > 9) begin
|
||||
$fatal(1, "pll behavioral output is slower than 120MHz");
|
||||
end
|
||||
|
||||
write_register(32'h1000_B008, 32'd0);
|
||||
write_register(32'h1000_B00C, 32'd1);
|
||||
wait_for_completion(read_data);
|
||||
if (read_data !== 32'h0000_0608) begin
|
||||
$fatal(1, "pll did not select the 24MHz profile");
|
||||
end
|
||||
repeat (4) @(posedge sys_clk_o);
|
||||
@(posedge sys_clk_o);
|
||||
edge_start = $time;
|
||||
@(posedge sys_clk_o);
|
||||
edge_end = $time;
|
||||
if ((edge_end - edge_start) < 35) begin
|
||||
$fatal(1, "pll behavioral output is faster than the 24MHz profile");
|
||||
end
|
||||
|
||||
$display("pll controller dynamic configuration test passed");
|
||||
`else
|
||||
if (read_data !== 32'h0000_0160) begin
|
||||
$fatal(1, "unsupported pll backend did not report the safe-clock error");
|
||||
end
|
||||
$display("pll controller capability gate test passed");
|
||||
`endif
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -9,6 +9,7 @@ module sysctrl_fault_tb;
|
||||
logic fault_reserved_i = 1'b0;
|
||||
nmi_if nmi ();
|
||||
sysctrl_if sysctrl ();
|
||||
pll_ctrl_if pll_ctrl ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
@@ -20,7 +21,8 @@ module sysctrl_fault_tb;
|
||||
.fault_wstrb_i (fault_wstrb_i),
|
||||
.fault_reserved_i(fault_reserved_i),
|
||||
.nmi (nmi),
|
||||
.sysctrl (sysctrl)
|
||||
.sysctrl (sysctrl),
|
||||
.pll_ctrl (pll_ctrl)
|
||||
);
|
||||
|
||||
task automatic read_register(input logic [31:0] address, output logic [31:0] data);
|
||||
@@ -54,11 +56,19 @@ module sysctrl_fault_tb;
|
||||
|
||||
logic [31:0] read_data;
|
||||
initial begin
|
||||
nmi.valid = 1'b0;
|
||||
nmi.addr = '0;
|
||||
nmi.wdata = '0;
|
||||
nmi.wstrb = '0;
|
||||
sysctrl.core_sel_i = '0;
|
||||
nmi.valid = 1'b0;
|
||||
nmi.addr = '0;
|
||||
nmi.wdata = '0;
|
||||
nmi.wstrb = '0;
|
||||
sysctrl.core_sel_i = '0;
|
||||
pll_ctrl.req_ready_i = 1'b1;
|
||||
pll_ctrl.rsp_active_sel_i = '0;
|
||||
pll_ctrl.rsp_active_valid_i = 1'b0;
|
||||
pll_ctrl.rsp_safe_clk_i = 1'b1;
|
||||
pll_ctrl.rsp_pll_lock_i = 1'b0;
|
||||
pll_ctrl.rsp_error_i = '0;
|
||||
pll_ctrl.rsp_valid_i = 1'b0;
|
||||
pll_ctrl.capable_i = 1'b0;
|
||||
repeat (2) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@ def test_generated_artifacts_share_the_capacity_baseline(tmp_path: Path) -> None
|
||||
assert "RS_SOC_NMI_SDIO_BASE" not in header
|
||||
assert "RS_SOC_OPIPSRAM_BASE" not in header
|
||||
assert "RS_SOC_HAS_SRAM 1U" in header
|
||||
assert "SOC_SYSCTRL_PLL_CFG_OFFSET 32'h00000008" in rtl
|
||||
assert "SOC_SYSCTRL_PLL_STATUS_OFFSET 32'h0000001C" in rtl
|
||||
assert "RS_SOC_SYSCTRL_PLL_CFG_OFFSET UINT32_C(0x00000008)" in header
|
||||
assert "RS_SOC_SYSCTRL_PLL_STATUS_OFFSET UINT32_C(0x0000001C)" in header
|
||||
assert "PSRAM (wxa!ri) : ORIGIN = 0x40000000, LENGTH = 0x00800000" in linker
|
||||
|
||||
|
||||
@@ -151,6 +155,7 @@ def test_sysctrl_fault_registers_record_and_clear_pending(tmp_path: Path) -> Non
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/nmi_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
|
||||
str(ROOT / "rtl/ip/native/peripheral/pll_ctrl_if.sv"),
|
||||
str(ROOT / "rtl/ip/native/peripheral/sysctrl.sv"),
|
||||
str(ROOT / "tests/rtl/sysctrl_fault_tb.sv"),
|
||||
"",
|
||||
@@ -179,6 +184,98 @@ def test_sysctrl_fault_registers_record_and_clear_pending(tmp_path: Path) -> Non
|
||||
assert "sysctrl fault registers test passed" in result.stdout
|
||||
|
||||
|
||||
def test_pll_controller_reconfigures_and_falls_back_to_the_safe_clock(tmp_path: Path) -> None:
|
||||
iverilog = shutil.which("iverilog")
|
||||
vvp = shutil.which("vvp")
|
||||
if iverilog is None or vvp is None:
|
||||
return
|
||||
generate(tmp_path)
|
||||
source_list = tmp_path / "pll_ctrl.fl"
|
||||
source_list.write_text(
|
||||
"\n".join(
|
||||
[
|
||||
"+define+SV_ASSRT_DISABLE",
|
||||
"+define+PDK_BEHAV",
|
||||
"+define+HAVE_PLL",
|
||||
f"+incdir+{tmp_path / 'rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/mini/top'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/nmi_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/cdc/cdc_sync.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/cdc/cdc_2phase.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/clkrst/rst_sync.sv"),
|
||||
str(ROOT / "rtl/ip/native/peripheral/pll_ctrl_if.sv"),
|
||||
str(ROOT / "rtl/ip/native/peripheral/sysctrl.sv"),
|
||||
str(ROOT / "rtl/tech/tc_clk.sv"),
|
||||
str(ROOT / "rtl/tech/tc_pll.sv"),
|
||||
str(ROOT / "rtl/mini/top/rcu.sv"),
|
||||
str(ROOT / "tests/rtl/pll_ctrl_tb.sv"),
|
||||
"",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
converted = tmp_path / "pll_ctrl_tb.v"
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
|
||||
"-f",
|
||||
str(source_list),
|
||||
"--output",
|
||||
str(converted),
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
simulation = tmp_path / "pll_ctrl_tb"
|
||||
subprocess.run(
|
||||
[iverilog, "-g2012", "-s", "pll_ctrl_tb", "-o", str(simulation), str(converted)],
|
||||
check=True,
|
||||
)
|
||||
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
|
||||
assert "pll controller dynamic configuration test passed" in result.stdout
|
||||
result = subprocess.run(
|
||||
[vvp, str(simulation), "+pll_lock_fail"], text=True, capture_output=True, check=True
|
||||
)
|
||||
assert "pll controller timeout test passed" in result.stdout
|
||||
|
||||
unsupported_list = tmp_path / "pll_unsupported.fl"
|
||||
unsupported_list.write_text(
|
||||
source_list.read_text(encoding="utf-8").replace("+define+HAVE_PLL\n", ""),
|
||||
encoding="utf-8",
|
||||
)
|
||||
unsupported_converted = tmp_path / "pll_unsupported_tb.v"
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
|
||||
"-f",
|
||||
str(unsupported_list),
|
||||
"--output",
|
||||
str(unsupported_converted),
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
unsupported_simulation = tmp_path / "pll_unsupported_tb"
|
||||
subprocess.run(
|
||||
[
|
||||
iverilog,
|
||||
"-g2012",
|
||||
"-s",
|
||||
"pll_ctrl_tb",
|
||||
"-o",
|
||||
str(unsupported_simulation),
|
||||
str(unsupported_converted),
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
result = subprocess.run(
|
||||
[vvp, str(unsupported_simulation)], text=True, capture_output=True, check=True
|
||||
)
|
||||
assert "pll controller capability gate test passed" in result.stdout
|
||||
|
||||
|
||||
def test_sysctrl_does_not_expose_unused_i2c_or_qspi_select_registers() -> None:
|
||||
rtl = (ROOT / "rtl/ip/native/peripheral/sysctrl.sv").read_text(encoding="utf-8")
|
||||
header = (ROOT / "crt/include/retrosoc/core/soc.h").read_text(encoding="utf-8")
|
||||
|
||||
Reference in new issue
Block a user