-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add wrapper for dynamic clk_int_div module for static clk division * Improve documentation of clk_int_div and add notes about constraints * Add clk_int_div_static TB to CI * Update README * Fix initalization instead of assignment bug * Update lint waivers for blocking assignments in clk_int_div
- Loading branch information
Showing
7 changed files
with
214 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
//----------------------------------------------------------------------------- | ||
// Title : Static Integer Clock Divider | ||
//----------------------------------------------------------------------------- | ||
// File : clk_int_div_static.sv | ||
// Author : Manuel Eggimann <[email protected]> | ||
// Created : 08.05.2023 | ||
//----------------------------------------------------------------------------- | ||
// Description : | ||
// | ||
// This module implements a static arbitrary integer divider. Static in this | ||
// case means, the divider value is constant at elaboration time (SV parameter). | ||
// It supports arbitrary integer division with a guaranteed 50% duty cycle for | ||
// odd and even division. | ||
|
||
// Internally, this module is wrapper around the "at-runtime" configurable | ||
// `clk_int_div`module. If you need to change the division factor at-runtime you | ||
// should directly use `clk_int_div`instead. However if all you need is a single | ||
// division factor this module provides a convenience wrapper for you with a | ||
// simplified interface. | ||
// | ||
// The `en_i` signal can be used to enable or disable the output clock in a safe | ||
// manner (there is an internal, glitch-free clock gate). | ||
// | ||
// Parameters: | ||
// | ||
// DIV_VALUE: The integer value by which the clock shall be divided. Must be | ||
// non-zero integer smaller than 2^32-1. | ||
// | ||
// ENABLE_CLOCK_IN_RESET: If 1'b1, the clock gate will be enabled during reset | ||
// which allows the clk_int_div instance to bypass the clock during reset, IFF | ||
// the DEFAULT_DIV_VALUE is 1. For all other DEFAULT_DIV_VALUES, the output | ||
// clock will not be available until rst_ni is deasserted! | ||
// | ||
// IMPORTANT!!! | ||
// | ||
// All clock gating/logic within this design is performed by dedicated clock | ||
// logic tech cells. By default the common_cell library uses the behavioral | ||
// models in the `tech_cells_generic` repository. However, for synthesis these | ||
// cells need to be mapped to dedicated cells from your standard cell library, | ||
// preferably ones that are designed for clock logic (they have balanced rise | ||
// and fall time). During synthesis you furthermore have to properly set | ||
// `dont_touch` or `size_only` attributes to prevent the logic synthesizer from | ||
// replacing those cells with regular logic gates which could end up being | ||
// glitchty! | ||
// | ||
//----------------------------------------------------------------------------- | ||
// Copyright (C) 2023 ETH Zurich, University of Bologna Copyright and related | ||
// rights are licensed under the Solderpad Hardware License, Version 0.51 (the | ||
// "License"); you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or | ||
// agreed to in writing, software, hardware and materials distributed under this | ||
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS | ||
// OF ANY KIND, either express or implied. See the License for the specific | ||
// language governing permissions and limitations under the License. | ||
// SPDX-License-Identifier: SHL-0.51 | ||
// ----------------------------------------------------------------------------- | ||
|
||
|
||
module clk_int_div_static #( | ||
parameter int unsigned DIV_VALUE = 1, | ||
parameter bit ENABLE_CLOCK_IN_RESET = 1'b1 | ||
) ( | ||
input logic clk_i, | ||
input logic rst_ni, | ||
input logic en_i, | ||
input logic test_mode_en_i, | ||
output logic clk_o | ||
); | ||
if (DIV_VALUE == 0) begin : gen_elab_error | ||
$error("DIV_VALUE must be strictly larger than 0."); | ||
end | ||
|
||
localparam int unsigned DivValueWidth = $clog2(DIV_VALUE+1); | ||
|
||
logic [DivValueWidth-1:0] div_value; | ||
assign div_value = DIV_VALUE; | ||
|
||
clk_int_div #( | ||
.DIV_VALUE_WIDTH ( DivValueWidth ), | ||
.DEFAULT_DIV_VALUE ( DIV_VALUE ), | ||
.ENABLE_CLOCK_IN_RESET ( ENABLE_CLOCK_IN_RESET ) | ||
) i_clk_int_div ( | ||
.clk_i, | ||
.rst_ni, | ||
.en_i, | ||
.test_mode_en_i, | ||
.div_i ( div_value ), | ||
.div_valid_i ( 1'b0 ), | ||
.div_ready_o ( ), | ||
.clk_o, | ||
.cycl_count_o ( ) | ||
); | ||
|
||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
//----------------------------------------------------------------------------- | ||
// Copyright (C) 2023 ETH Zurich, University of Bologna | ||
// Copyright and related rights are licensed under the Solderpad Hardware | ||
// License, Version 0.51 (the "License"); you may not use this file except in | ||
// compliance with the License. You may obtain a copy of the License at | ||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law | ||
// or agreed to in writing, software, hardware and materials distributed under | ||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
// specific language governing permissions and limitations under the License. | ||
// SPDX-License-Identifier: SHL-0.51 | ||
//----------------------------------------------------------------------------- | ||
|
||
module clk_int_div_static_tb; | ||
parameter int unsigned NumTestCycles = 10000; | ||
parameter realtime TClkIn = 10ns; | ||
localparam int unsigned RstClkCycles = 10; | ||
|
||
localparam int unsigned MaxClkDiv = 100; | ||
|
||
realtime t_delta = 100ps; | ||
|
||
logic clk, rstn; | ||
logic test_mode_en; | ||
logic enable; | ||
logic clk_out [MaxClkDiv]; | ||
|
||
|
||
// system clock and reset | ||
clk_rst_gen #( | ||
.ClkPeriod ( TClkIn ), | ||
.RstClkCycles ( RstClkCycles ) | ||
) i_clk_rst_gen_reg ( | ||
.clk_o ( clk ), | ||
.rst_no ( rstn ) | ||
); | ||
|
||
property T_clk(real clk_period); | ||
realtime current_time; | ||
realtime actual_period; | ||
disable iff (!rstn || !enable) | ||
(('1, current_time = $realtime)) |=> | ||
('1, actual_period = $realtime - current_time) |-> | ||
(($realtime - current_time >= clk_period - t_delta) && ($realtime - current_time < clk_period + t_delta)); | ||
endproperty | ||
|
||
|
||
for (genvar i = 1; i < MaxClkDiv; i++) begin :gen_clk_divs | ||
clk_int_div_static #( | ||
.DIV_VALUE(i), | ||
.ENABLE_CLOCK_IN_RESET(1'b1) | ||
) i_dut( | ||
.clk_i ( clk ), | ||
.rst_ni ( rstn ), | ||
.en_i ( enable ), | ||
.test_mode_en_i ( test_mode_en ), | ||
.clk_o ( clk_out[i] ) | ||
); | ||
|
||
assert_period_period: assert property (@(posedge clk_out[i]) T_clk(TClkIn*i)) else | ||
$error("Output period of div %d clock is incorrect. Should be in range %d to %d.", i, TClkIn*i-t_delta, TClkIn*i+t_delta); | ||
|
||
end | ||
|
||
initial begin : apply_stimuli | ||
test_mode_en = 1'b0; | ||
enable = 1'b1; | ||
$info("Resetting clock dividers..."); | ||
@(posedge rstn); | ||
|
||
// Randomly enable and disable the output clock | ||
repeat(NumTestCycles) begin | ||
@(posedge clk); | ||
if ($urandom_range(0, 1000)<5) begin | ||
enable = 1'b0; | ||
repeat($urandom_range(1, 100)) @(posedge clk); | ||
enable = 1'b1; | ||
end | ||
end | ||
$info("Test finished"); | ||
$stop(); | ||
end | ||
|
||
endmodule |