\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