OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [rtl/] [src_peripheral/] [clk_source/] [xilinx_pll/] [xilinx_pll_sim/] [phase_shift.v] - Rev 48

Compare with Previous | Blame | View Log

/*
 * phase_shift.v: Shifts the input clock by the given degree and can change
 	it's duty cycle.
 * author: Till Mahlburg
 * year: 2019-2020
 * organization: Universität Leipzig
 * license: ISC
 *
 */
 
// synthesis translate_off
 
`timescale 1 ns / 1 ps
 
module phase_shift (
	input RST,
	input PWRDWN,
	input clk,
	/* shift in degrees */
	input signed [31:0] shift_1000,
	/* period length of the clock */
	input [31:0] clk_period_1000,
	/* duty cycle in percent */
	input [6:0] duty_cycle,
 
	output reg lock,
	output reg clk_shifted);
 
	/* The formulas used here are composed of the following:
	 * - clk_period_1000 / 1000.0 calculates the actual period length, which
	 *   has been multiplied by 1000 to enable a higher precision.
	 * - shift * ((clk_period_1000 / 1000.0) / 360.0) calculate the basic shift
	 *   as a multiple of a 360th of the period of the clk to shift
	 * - if the desired shift is negative, we just add a shift by
	 *   360 degrees and add the (negative) shift:
	 *   clk_period + (shift * (clk_period / 360.0))
	 * - to calculate the duty cycle, we delay or rush the output of
	 *   0 by adding (or subtracting) the desired duty cycle in 100th
	 *   of the input clk period from the default (50):
	 *   (duty_cycle + 50.0) * (clk_period / 100.0)
	 */
 
	/* calculate when to put out high */
	always @(posedge clk or posedge RST or posedge PWRDWN) begin
		if (!RST && !PWRDWN) begin
			if (shift_1000 < 0) begin
				clk_shifted <= #((clk_period_1000 / 1000.0) + ((shift_1000 / 1000.0) * ((clk_period_1000 / 1000.0) / 360.0))) 1;
			end else begin
				clk_shifted <= #((shift_1000 / 1000.0) * ((clk_period_1000 / 1000.0) / 360.0)) 1;
			end
		end
	end
 
	/* calculate when to put out low and return when the phase and duty cycle is correctly set */
	always @(negedge clk or posedge RST) begin
		if (RST) begin
			clk_shifted <= 1'b0;
			lock <= 1'b0;
		end else if (lock !== 1'bx) begin
			if (shift_1000 < 0) begin
				clk_shifted <= #((clk_period_1000 / 1000.0) + ((shift_1000/ 1000.0)  * ((clk_period_1000 / 1000.0) / 360.0)) + ((duty_cycle + 50.0) * ((clk_period_1000 / 1000.0) / 100.0))) 0;
				lock <= #((clk_period_1000 / 1000.0) + ((shift_1000/ 1000.0)  * ((clk_period_1000 / 1000.0) / 360.0)) + ((duty_cycle + 50.0) * ((clk_period_1000 / 1000.0) / 100.0))) 1'b1;
			end else begin
				clk_shifted <= #((shift_1000/ 1000.0)  * ((clk_period_1000 / 1000.0) / 360.0) + ((duty_cycle + 50.0) * ((clk_period_1000 / 1000.0) / 100.0))) 0;
				lock <= #((shift_1000/ 1000.0)  * ((clk_period_1000 / 1000.0) / 360.0) + ((duty_cycle + 50.0) * ((clk_period_1000 / 1000.0) / 100.0))) 1'b1;
			end
		end
	end
 
	/* PWRDWN for good */
	always begin
		if (PWRDWN) begin
			clk_shifted <= 1'bx;
			lock <= 1'bx;
			#0.001;
		end else begin
		#1;
		end
	end
 
endmodule
 
// synthesis translate_on
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.