blob: d75707a145d1481fa823bed5708573b97173af63 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//############################################################################
// *Name: ast_dft
// *Module Description: AST DFT
//############################################################################
`include "prim_assert.sv"
module ast_dft (
input clk_i, // TLUL Clock
input rst_ni, // TLUL Reset
input clk_io_osc_i, // IO Oscillator Clock
input clk_io_osc_val_i, // IO Oscillator Clock Valid
input rst_io_clk_ni, // IO Oscillator Clock Reset
input clk_ast_ext_i, // External (Reference) Clock
input lc_ctrl_pkg::lc_tx_t lc_clk_byp_req_i, // External clock mux override for OTP bootstrap
output logic clk_src_io_o, // IO Source Clock
output logic clk_src_io_val_o, // IO Source Clock Valid
output lc_ctrl_pkg::lc_tx_t lc_clk_byp_ack_o, // Switch clocks to External clock
// memories read-write margins
output ast_pkg::dpm_rm_t dpram_rmf_o, // Dual Port RAM Read-write Margin Fast
output ast_pkg::dpm_rm_t dpram_rml_o, // Dual Port RAM Read-write Margin sLow
output ast_pkg::spm_rm_t spram_rm_o, // Single Port RAM Read-write Margin
output ast_pkg::spm_rm_t sprgf_rm_o, // Single Port Reg-File Read-write Margin
output ast_pkg::spm_rm_t sprom_rm_o // Single Port ROM Read-write Margin
);
////////////////////////////////////////
// IO Source Clock Selection
////////////////////////////////////////
logic lc_clk_byp_sel, lc_clk_byp_en;
assign lc_clk_byp_sel = (lc_clk_byp_req_i == lc_ctrl_pkg::On);
logic clks_aoff, clk_osc_en_q, clk_byp_en_q;
assign clks_aoff = !(clk_osc_en_q || clk_byp_en_q);
// Clock IO Oscillator
////////////////////////////////////////
logic rst_clk_osc_n, clk_osc_sel, clk_osc_aoff, clk_osc;
assign rst_clk_osc_n = clk_io_osc_val_i;
always_ff @( posedge clk_io_osc_i, negedge rst_clk_osc_n ) begin
if ( !rst_clk_osc_n ) begin
clk_osc_sel <= 1'b0;
clk_osc_aoff <= 1'b0;
end else begin
clk_osc_sel <= !lc_clk_byp_sel;
clk_osc_aoff <= clks_aoff;
end
end
always_ff @( posedge clk_io_osc_i, negedge rst_clk_osc_n ) begin
if ( !rst_clk_osc_n ) begin
clk_osc_en_q <= 1'b0;
end else if ( !clk_osc_sel ) begin
clk_osc_en_q <= 1'b0;
end else if ( clk_osc_sel && clk_osc_aoff ) begin
clk_osc_en_q <= 1'b1;
end
end
logic clk_osc_en;
assign clk_osc_en = clk_osc_sel && (clk_osc_en_q || clk_osc_aoff);
prim_clock_gating u_clk_osc_ckgt (
.clk_i ( clk_io_osc_i ),
.en_i ( clk_osc_en ),
.test_en_i ( 1'b0 ),
.clk_o ( clk_osc )
);
// Clock IO Bypass
////////////////////////////////////////
logic rst_clk_byp_n, clk_byp_sel, clk_byp_aoff, clk_byp;
assign rst_clk_byp_n = rst_io_clk_ni;
always_ff @( posedge clk_ast_ext_i, negedge rst_clk_byp_n ) begin
if ( !rst_clk_byp_n ) begin
clk_byp_sel <= 1'b0;
clk_byp_aoff <= 1'b0;
end else begin
clk_byp_sel <= lc_clk_byp_sel;
clk_byp_aoff <= clks_aoff;
end
end
always_ff @( posedge clk_ast_ext_i, negedge rst_clk_byp_n ) begin
if ( !rst_clk_byp_n ) begin
clk_byp_en_q <= 1'b0;
end else if ( !clk_byp_sel ) begin
clk_byp_en_q <= 1'b0;
end else if ( clk_byp_sel && clk_byp_aoff ) begin
clk_byp_en_q <= 1'b1;
end
end
logic clk_byp_en;
assign clk_byp_en = clk_byp_sel && (clk_byp_en_q || clk_byp_aoff);
prim_clock_gating u_clk_byp_ckgt (
.clk_i ( clk_ast_ext_i ),
.en_i ( clk_byp_en ),
.test_en_i ( 1'b0 ),
.clk_o ( clk_byp )
);
// IO Clock Source
////////////////////////////////////////
assign lc_clk_byp_en = clk_byp_en;
assign clk_src_io_o = clk_osc || clk_byp;
assign clk_src_io_val_o = clk_io_osc_val_i || lc_clk_byp_en;
assign lc_clk_byp_ack_o = lc_clk_byp_en ? lc_ctrl_pkg::On :
lc_ctrl_pkg::Off;
////////////////////////////////////////
// Memories Read-write Margins
////////////////////////////////////////
assign dpram_rmf_o = 10'h000;
assign dpram_rml_o = 10'h000;
assign spram_rm_o = 5'h00;
assign sprgf_rm_o = 5'h00;
assign sprom_rm_o = 5'h00;
///////////////////////
// Unused Signals
///////////////////////
logic unused_sigs;
assign unused_sigs = ^{ clk_i, // Used in ASIC implementation
rst_ni // Used in ASIC implementation
};
endmodule : ast_dft