mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
Integrate the Tiny RCU, normalized REF24 control, external-input profiles, single PLL backend, SYS/MEM/PCLK clocks, CPU-only WFI gating, peripheral lifecycle control and retained debug behavior. Keep CPU and all 32 main SRAM macros on SYS and the six private Crypto macros on PCLK. Add the handwritten RCU register/HAL contract, RS_EBUSY, bounded SDK operations and focused firmware. Preserve shared-IP defaults and the ICS55/PLL SAFE24 boot and explicit IHP130/no-PLL compatibility profiles. Use APB/AXI domain bridges and source-owned response holders to preserve backpressured responses, complete aborted bursts and prevent stale replay. Verify production DMA source-reset drain and common XPI endpoint reset with extracted integration bindings and an independent scoreboard. Add source-bound macro/clock audits, SAFE24 observational STA constraints and commercial-adapter host checks. No P8 functionality or operating-point qualification is included. See TINY-R2-P7 in docs/ip/tiny-soc.md. Validation: 54 P7 directed tests pass, including both simulators, ten source-reset ratio runs and two expected-negative drain mutations. RTL format/style, clock/reset inventory, Ruff and both Tiny PDK PR dry-runs pass. Retained 06-00 synthesis and strict netlist boots pass for both PDKs; STA remains negative and observational. Source comparison confirms only the follow-up tests changed after that backend campaign. Evidence: build/ics55-tiny-2026-10-14-06-00-ff4b5cef6eb5/meta/ tiny-r2-p7-source-reset/summary.json. Earlier firmware, HAL and compatibility results and the non-clean full-suite attempt retain their original attribution. Full Icarus firmware is deferred to final Tiny qualification; this commit does not constitute human phase acceptance or physical signoff.
218 lines
5.6 KiB
Systemverilog
218 lines
5.6 KiB
Systemverilog
// 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.
|
|
|
|
`timescale 1ns / 1ps
|
|
module tc_pll #(
|
|
parameter bit UseIcs55EcosPll = 1'b0,
|
|
parameter bit Ics55Parked = 1'b0
|
|
) (
|
|
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
|
|
localparam logic [2:0] PLL_LOCK_CYCLES = 3'd4;
|
|
|
|
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;
|
|
realtime s_last_ref_edge;
|
|
realtime s_ref_period;
|
|
|
|
function automatic int pll_multiplier(input logic [2:0] cfg_sel);
|
|
case (cfg_sel)
|
|
3'd0: pll_multiplier = 3;
|
|
3'd1: pll_multiplier = 4;
|
|
3'd2: pll_multiplier = 5;
|
|
3'd3: pll_multiplier = 6;
|
|
3'd4: pll_multiplier = 7;
|
|
3'd5: pll_multiplier = 8;
|
|
3'd6: pll_multiplier = 9;
|
|
default: pll_multiplier = 10;
|
|
endcase
|
|
endfunction
|
|
|
|
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
|
|
|
|
always @(posedge fref_i) begin
|
|
if (s_last_ref_edge != 0) begin
|
|
s_ref_period = $realtime - s_last_ref_edge;
|
|
end
|
|
s_last_ref_edge = $realtime;
|
|
end
|
|
|
|
always begin
|
|
@(posedge fref_i);
|
|
wait (pll_lock_o && s_ref_period > 0.0);
|
|
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_cfg_apply,
|
|
s_cfg_sel_d,
|
|
s_cfg_sel_q
|
|
);
|
|
|
|
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
|
|
);
|
|
|
|
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
|
|
);
|
|
`elsif PDK_ICS55
|
|
`ifdef HAVE_PLL
|
|
`ifdef RETROSOC_SOC__TINY
|
|
if (UseIcs55EcosPll) begin : gen_ecos
|
|
tc_pll_ics55_ecos #(
|
|
.Parked(Ics55Parked)
|
|
) u_backend (
|
|
.fref_i (fref_i),
|
|
.rst_n_i (rst_n_i),
|
|
.cfg_sel_i (cfg_sel_i),
|
|
.cfg_apply_i (cfg_apply_i),
|
|
.pll_capable_o(pll_capable_o),
|
|
.pll_lock_o (pll_lock_o),
|
|
.pll_clk_o (pll_clk_o)
|
|
);
|
|
end else begin : gen_unsupported
|
|
assign pll_capable_o = 1'b0;
|
|
assign pll_lock_o = 1'b0;
|
|
assign pll_clk_o = 1'b0;
|
|
end
|
|
`else
|
|
// Retain the legacy Mini experimental binding and instance path. It is not
|
|
// the locked OpenECOS backend and does not qualify that macro.
|
|
localparam logic [2:0] ICS55_SUPPORTED_SEL = 3'd0;
|
|
localparam logic [7:0] ICS55_N = 8'd2;
|
|
localparam logic [1:0] ICS55_OD = 2'd2;
|
|
localparam logic [2:0] ICS55_LOCK_CYCLES = 3'd4;
|
|
|
|
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_mode_supported;
|
|
|
|
assign s_cfg_sel_d = cfg_sel_i;
|
|
dffer #(3) u_cfg_sel_dffer (
|
|
fref_i,
|
|
rst_n_i,
|
|
cfg_apply_i,
|
|
s_cfg_sel_d,
|
|
s_cfg_sel_q
|
|
);
|
|
|
|
assign s_mode_supported = s_cfg_sel_q == ICS55_SUPPORTED_SEL;
|
|
always_comb begin
|
|
s_lock_count_d = s_lock_count_q;
|
|
s_lock_d = s_lock_q;
|
|
if (cfg_apply_i || !s_mode_supported) begin
|
|
s_lock_count_d = '0;
|
|
s_lock_d = 1'b0;
|
|
end else if (!s_lock_q) begin
|
|
if (s_lock_count_q == ICS55_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
|
|
);
|
|
|
|
assign pll_capable_o = 1'b1;
|
|
assign pll_lock_o = s_lock_q;
|
|
(* keep *) (* dont_touch = "true" *)
|
|
PLL_TOP u_PLL_TOP (
|
|
.CKOUT1(pll_clk_o),
|
|
.CKOUT2(),
|
|
.CKTST (),
|
|
.EN (rst_n_i && s_mode_supported),
|
|
.REFCLK(fref_i),
|
|
.BP (1'b0),
|
|
.SELECT(1'b0),
|
|
.OD (ICS55_OD),
|
|
.N (ICS55_N)
|
|
);
|
|
`endif
|
|
`else
|
|
assign pll_capable_o = 1'b0;
|
|
assign pll_lock_o = 1'b0;
|
|
assign pll_clk_o = fref_i;
|
|
`endif
|
|
`else
|
|
assign pll_capable_o = 1'b0;
|
|
assign pll_lock_o = 1'b0;
|
|
assign pll_clk_o = fref_i;
|
|
`endif
|
|
endmodule
|