16、时基模块Verilog源码

\qquad 下面是HD-GR基带时基模块的Verilog代码(下载完整的HD-GR基带模块代码):

//                              -*- Mode: Verilog -*-
// Filename        : time_base.v
// Description     : Generates the 
//						TIC (tic_enable), 
//						preTIC (pre_tic_enable),
//						ACCUM_INT (accum_enable),
//						accum_sample_enable1,
//						accum_sample_enable2,
//						pps_tic_0,
//						pps_tic_count.
//
//                  The accumulator sample rate is set at 16.368 MHz in this design.
//                  The accum_sample_enable pulse is derived from the sample clock
//                  driver for the HD-2769-2RF-2 RF front end, but is on a different 
//                  enable phase.
// 
//					changed by CHD: 2014-04-21

// Author          : Peter Mumford  UNSW 2005
// Author          : Cheng Huaide, turing321.com, 2015 (BDS & 1PPS - processing upgrade)

/*
	Copyright (C) 2007  Peter Mumford

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

module time_base (
	clk, rstn, accum_divide, tic_divide, 
	tic_delay_enable, tic_delay_value, 
	pps_tic_enable, pps_tic_load, pps_tic_0, pps_tic_count,
	pre_tic_enable, tic_enable, accum_enable, 
	sample_clk_1, accum_sample_enable_1,
	sample_clk_2, accum_sample_enable_2);
	
	input clk, rstn;
	input [17:0] accum_divide;		// accum_divide = f(clk)/f(tic)-1 = (16.368*6MHz)/2KHz-1 = 49103 = 0xBFCF
	input [24:0] tic_divide;		// tic_divide   = f(clk)/f(tic)-1 = (16.368*6MHz)/10Hz-1 = 9820799 = 0x95DA7F
	input tic_delay_enable;			// tic_delay_enable
	input [31:0] tic_delay_value;	// tic_delay_value
	input pps_tic_enable;			// pps_tic_enable
	input [3:0] pps_tic_load;		// pps_tic_load
	output pps_tic_0;					// pps_tic_0
	output [3:0] pps_tic_count;	// the value of the PPS TIC counter
	output pre_tic_enable;			// to code_nco's (CHD: default 0.1s)
	output tic_enable;				// to code_gen's (CHD: default 0.1s)
	output accum_enable;				// accumulation interrupt (CHD: default 0.5ms)
	input sample_clk_1;				// from RF front end 1 (16.368MHz)
	output accum_sample_enable_1;	// accumulators sampling enable (16.368MHz)
	input sample_clk_2;				// from RF front end 1 (16.368MHz)
	output accum_sample_enable_2;	// accumulators sampling enable (16.368MHz)

	reg [1:0] reg_sample_clk_1;
	reg [1:0] reg_sample_clk_2;
	
	reg [17:0] accum_q;				// output of counter ae
	reg [17:0] accum_delay;			// accum_delay
	wire [17:0] cur_accum_divide;	// current accum_divide
	
	reg tic_shift;						// used to delay TIC 1 clock cycles
	reg [24:0] tic_q;					// output of counter te
	reg [24:0] tic_delay;			// tic_delay
	wire [24:0] cur_tic_divide;	// current tic_divide
	reg div_delay_lift;				// div_delay_lift
	reg div_delay_sign;				// div_delay_sign
	
	reg div_delay_fmt;				// div_delay_fmt
	reg div_slew_sign;				//	div_slew_sign
	reg [6:0] div_slew_value;		// div_slew_value
	reg [3:0] div_slew_mod;			// div_slew_mod
	reg [3:0] div_slew_count;		// div_slew_count
	
	reg [3:0] tic_count;				// tic count in one PPS period
	reg tic_pulse;						// tic pulse: start at new PPS posedge, width=1 clock

	//----------------------------------------------------
	// generate accum_sample_enable_1 pulse at positive edge 
	// of sample_clk_1
	//----------------------------------------------------
	always @ (posedge clk) begin
		if (!rstn) begin
			reg_sample_clk_1 <=2'b00;
		end
		else begin
			reg_sample_clk_1 <= {reg_sample_clk_1[0], sample_clk_1};
		end
	end

	assign accum_sample_enable_1 = (reg_sample_clk_1 == 2'b01)? 1'b1:1'b0;
	
	//----------------------------------------------------
	// generate accum_sample_enable_2 pulse at positive edge 
	// of sample_clk_2
	//----------------------------------------------------
	always @ (posedge clk) begin
		if (!rstn) begin
			reg_sample_clk_2 <=2'b00;
		end
		else begin
			reg_sample_clk_2 <= {reg_sample_clk_2[0], sample_clk_2};
		end
	end

	assign accum_sample_enable_2 = (reg_sample_clk_2 == 2'b01)? 1'b1:1'b0;
	
	//----------------------------------------------------
	// save tic_delay and accum_delay
	//----------------------------------------------------
	always @ (posedge clk) begin
		if (!rstn) begin
			div_delay_fmt <= 0;
			div_delay_lift <= 0;
			div_delay_sign <= 0;
			tic_delay <= 0;
			accum_delay <= 0;
			div_slew_value <= 0;
			div_slew_mod   <= 0;
			div_slew_sign	<= 0;
			div_slew_count <= 0;
		end
		else if (tic_delay_enable) begin
			div_delay_fmt <= tic_delay_value[31];
			div_slew_count <= 0;
			if (tic_delay_value[31]) begin
				div_delay_lift <= 0;
				div_delay_sign <= tic_delay_value[18];
				tic_delay		<= tic_delay_value[17:0];
				accum_delay		<= tic_delay_value[17:0];
				div_slew_value <= tic_delay_value[25:19];
				div_slew_mod	<= tic_delay_value[29:26];
				div_slew_sign	<= tic_delay_value[30];
			end
			else begin
				div_delay_lift <= tic_delay_value[26];
				div_delay_sign <= tic_delay_value[25];
				tic_delay <= tic_delay_value[24:0];
				if (tic_delay_value[27]) 
					accum_delay <= tic_delay_value[17:0];
				else 
					accum_delay <= 0;
				div_slew_value <= 0;
				div_slew_mod	<= 0;
				div_slew_sign	<= 0;
			end
		end
		else if (pre_tic_enable) begin
			// Delay Format 1
			if (div_delay_fmt) begin
				div_delay_sign <= div_slew_sign;
				if (div_slew_count < div_slew_mod) begin
					tic_delay	<= div_slew_value + 1'b1;
					accum_delay	<= div_slew_value + 1'b1;
				end
				else begin
					tic_delay	<= div_slew_value;
					accum_delay	<= div_slew_value;
				end
				
				if (div_slew_count < 9)
					div_slew_count <= div_slew_count + 1'd1; 
				else
					div_slew_count <= 0; 
			end
			// Delay Format 0
			else if (!div_delay_lift) begin
				tic_delay <= 0;
				accum_delay <= 0;
			end
		end
	end
	
	//-------------------------------------------------------
	// generate the tic_enable
	// 
	// tic period = (tic_divide + 1) * clk_en period
	// If clock enabled by clk (= 16.368*6MHz):
	// tic period = (tic_divide + 1) / (16.368*6MHz)
	// For default tic period (0.1s) tic_divide = 9820799 = 0x95DA7F
	//-------------------------------------------------------   
	lpm_counter te(
		.clock(clk),
		.sclr(!rstn),
		.sload(pre_tic_enable),
//		.data(tic_divide),
		.data(cur_tic_divide),
		.q(tic_q)
	);
	defparam te.lpm_direction="DOWN";
	defparam te.lpm_width=25;

	// The preTIC comes first latching the code_nco,
	// followed by the TIC latching everything else.
	// This is due to the delay between the code_nco phase
	// and the prompt code.
	assign pre_tic_enable = (tic_q == 0)? 1'b1:1'b0;
	assign cur_tic_divide = (div_delay_sign == 0) ? (tic_divide+tic_delay):(tic_divide-tic_delay);
   
	always @ (posedge clk)
	begin
		if (!rstn) // set up shift register
		begin
			tic_shift <= 0;
		end
		else // run
		begin
			tic_shift <= pre_tic_enable;
		end
	end // always @ (posedge clk)
	assign tic_enable = tic_shift;
	

	//---------------------------------------------------------
	// generate the accum_enable
	// 
	// The Accumulator interrupt signal and flag needs to have 
	// between 0.5 ms and about 1 ms period.
	// This is to ensure that accumulation data can be read
	// before it is written over by new data.
	// The accumulators are asynchronous to each other and have
	// a dump period of nominally 1ms.
	//
	// ACCUM_INT period = (accum_divide + 1) / (16.368*6MHz)
	// For 0.5 ms accumulator interrupt
	// accum_divide = (16.368*6MHz)*0.0005-1 = 49103 = 0xBFCF     
	//----------------------------------------------------------
	lpm_counter ae(
		.clock(clk),
		.sclr(!rstn),
		.sload(accum_enable),
//		.data(accum_divide),
		.data(cur_accum_divide),
		.q(accum_q)
	);
	defparam ae.lpm_direction="DOWN";
	defparam ae.lpm_width=18;
	
	assign accum_enable = (accum_q == 0)? 1'b1:1'b0;
	assign cur_accum_divide = (tic_q != 0) ? accum_divide:
		((div_delay_sign == 0) ? (accum_divide+accum_delay):(accum_divide-accum_delay));
		
	always @ (posedge clk) begin
		if (!rstn) begin
			tic_count <= 0;
			tic_pulse <= 1'b0; 
		end
		else begin
			tic_pulse <= 1'b0; 
			if (pps_tic_enable) begin
				tic_count <= pps_tic_load;
				if (pps_tic_load == 0)
					tic_pulse <= 1'b1; 
			end
			else if (pre_tic_enable) begin
				if (tic_count < 9) begin
					tic_count <= tic_count + 1'b1; 
				end
				else begin
					tic_count <= 0; 
					tic_pulse <= 1'b1; 
				end
			end
		end
	end

	assign pps_tic_count = tic_count;
	assign pps_tic_0 = tic_pulse;
	
	/*
	always @ (posedge clk)
	begin
		if (!rstn)
			tic_q <= 0;
		else
			if (pre_tic_enable == 1'b1) tic_q <= tic_divide;
			else if (tic_q == 0) tic_q <=  24'd16777215;
			else tic_q <= tic_q - 1'd1;
	end
	*/
	
	/*
	always @ (posedge clk)
	begin
		if (!rstn) accum_q <= 0;
		else
			if (accum_enable == 1'b1) accum_q <= accum_divide;
			else if (accum_q == 0) accum_q <=  24'd16777215;
			else accum_q <= accum_q - 1'd1;
	end
	*/

endmodule // time_base

猜你喜欢

转载自blog.csdn.net/turing321_huaide/article/details/106689766