连接
Avalon -MM接口
mgmt_waitrequest:当 PLL 重配置进程开始后,此端口变高并在 PLL 重配置期间保持高电平。
PLL 重配置进程完成后,此端口变低。
I/O PLL重配写操作步骤:
1、 为mgmt_address和mgmt_writedata设置有效值,并且使能mgmt_write一个mgmt_clk周期
2、 重复步骤1共8次
3、 为mgmt_address设置启动地址9’b000000000,mgmt._writedata任意,并且使能mgmt_write一个mgmt_clk周期
4、 当配置完成后mgmt_waitrequest拉低
注:(1)如果发送的命令超过8个,内部的FIFO会溢出。
(2)每个命令(地址数据对)属于以下三种之一:
1、计数器重配设置
2、带宽重配设置
3、动态相位移动
1、计数器重配设置寄存器
1、 动态相位移动
3、带宽重配设置
环路滤波器和充电泵设置
CP :Charge pump setting
BP :Loop filter setting
对于PLL的带宽选择有三种—在PLL的参数设置中可以选择,它们是Low,Medium和High。可以来看下手册上对它们的说明:
• Low—PLL with a low bandwidth has better jitter rejection but a slower lock time.
• High—PLL with a high bandwidth has a faster lock time but tracks more jitter.
• Medium—A medium bandwidth offers a balance between lock time and jitter rejection.
带宽应该指的是环路滤波带宽,带宽越小就越不容易锁定,太宽了时钟抖动会比较大。
VCO的设置范围为600~1434M
其中M,N,C的参数分别对应上面,C0表示输出通道0,C1表示输出通道1,以此类推。
module mr_reconfig_master_pll #(parameter MIF_OFFSET = 7, // total cram address that differ resulted from PLL mif files comparisonparameter ADDR_WIDTH_FOR_VALUEMASK = 6, // number of bits representation for total ROM depth for PLL valuemask parameter ADDR_WIDTH_FOR_DPRIOADDR = 3, // number of bits representation for total CRAM address that differparameter DPRIO_ADDRESS_WIDTH = 9, //parameter DPRIO_DATA_WIDTH = 32 //
) (input wire clock,input wire reset,input wire reconfig_request, // from main state machine - request for reconfigoutput reg reconfig_done, // to main state machine - indicate reconfig is completedinput wire clr_reconfig_done, // from main state machine - full handshake signal to acknowledge reconfig_done (both rx & pll) is servicedinput wire [ADDR_WIDTH_FOR_VALUEMASK-1:0] offset_pointer, // from main state machine - indicate which rom address (mif range) to be readoutput wire [ADDR_WIDTH_FOR_VALUEMASK-1:0] valuemask_addr_ptr, // to value mask rom - start from offset_pointer & increment by 1 for each cycle & increment for MIF_OFFSET timesoutput wire [ADDR_WIDTH_FOR_DPRIOADDR-1:0] dprioaddr_addr_ptr, // to dprio addr rom - start from 0 & increment by 1 for each cycle & increment for MIF_OFFSET times input wire [7:0] dprio_offset, // from dprio addr rom - indicate which cram address to write toinput wire [31:0] field_valuemask, // from value mask rom - indicate the value of cram bit to write to (in 8-bitmask format)input wire reconfig_waitrequest, // output reg reconfig_write, // Reconfig signals to/from PLL reconfig controlleroutput reg [DPRIO_ADDRESS_WIDTH-1:0] reconfig_address, //output reg [DPRIO_DATA_WIDTH-1:0] reconfig_writedata //
);localparam [2:0]IDLE = 0,MOD = 1, WR = 2,TRANS = 3,START = 4,WAITREQUEST = 5,DONE = 6;reg [2:0] next_state;
reg [2:0] current_state;
wire [DPRIO_DATA_WIDTH-1:0] data_to_write; // data to be written to PLL
reg [ADDR_WIDTH_FOR_DPRIOADDR-1:0] num_exec; // offset start from 0 & increment by 1 & for MIF_OFFSET times
reg [ADDR_WIDTH_FOR_VALUEMASK-1:0] pointer; // get the pointer start offset from main state machine
reg last_offset; // indicate if the current offset is the last or not
wire reconfig_waitrequest_sync; // synchronize waitrequest signal from the PLL reconfig controlleraltera_std_synchronizer #(.depth(3)) u_reconfig_waitrequest_sync (.clk(clock),.reset_n(1'b1),.din(reconfig_waitrequest),.dout(reconfig_waitrequest_sync));always @ (posedge clock or posedge reset)
beginif (reset) begincurrent_state <= IDLE;end else begincurrent_state <= next_state;end
endalways @ (*)
beginnext_state = current_state;case (current_state)IDLE: beginif (reconfig_request) begin //由主状态机发出重配请求next_state = MOD;end endMOD: beginnext_state = WR;end // reconfig write WR: begin if (~reconfig_request) begin//如果重配请求清除则返回IDLE状态next_state = IDLE;end else beginnext_state = TRANS;end end// cycle to next offset before it hits MIF_OFFSET times
//TRANS state:TRANS: beginif (last_offset) beginnext_state = START;end else beginnext_state = MOD;end end// write to start register to initiate the PLL reconfig// then wait for waitrequest signal to be asserted //发送启动地址0x000 START: beginif (reconfig_waitrequest_sync) beginnext_state = WAITREQUEST;end else if (~reconfig_request) begin next_state = IDLE;end end// once waitrequest is deasserted, PLL reconfig is complete //等待PLL重配完成 WAITREQUEST: beginif (~reconfig_waitrequest_sync) beginnext_state = DONE;end else if (~reconfig_request) begin next_state = IDLE;endend// full handshaking between this master and main state machine DONE: beginif (~reconfig_request) beginnext_state = IDLE;end end endcase
end//mun_exec是参数ROM模块的读地址
always @ (posedge clock or posedge reset)
beginif (reset) beginnum_exec <= {ADDR_WIDTH_FOR_DPRIOADDR{1'b0}};pointer <= {ADDR_WIDTH_FOR_VALUEMASK{1'b0}};last_offset <= 1'b0;end else beginif (next_state == IDLE) beginnum_exec <= {ADDR_WIDTH_FOR_DPRIOADDR{1'b0}};pointer <= offset_pointer; end else if (next_state == TRANS && ~last_offset) beginnum_exec <= num_exec + {{{ADDR_WIDTH_FOR_DPRIOADDR-1}{1'b0}}, 1'b1};pointer <= pointer + {{{ADDR_WIDTH_FOR_VALUEMASK-1}{1'b0}}, 1'b1}; endlast_offset <= num_exec == (MIF_OFFSET - 1);end
end// mgmt_write signal
always @ (posedge clock or posedge reset)
beginif (reset) beginreconfig_write <= 1'b0; end else beginif (next_state == WR || next_state == START) begin reconfig_write <= 1'b1; end else begin reconfig_write <= 1'b0; endend
end
//write address to pll mgmt_address
always @ (posedge clock or posedge reset)
beginif (reset) beginreconfig_address <= {DPRIO_ADDRESS_WIDTH{1'b0}}; end else beginif (next_state == WR) beginreconfig_address <= {1'b0, dprio_offset};end else if (next_state == START) beginreconfig_address <= {1'b0, 8'h00};end end
end
//write data to pll mgmt_writedata
assign data_to_write = field_valuemask;always @ (posedge clock or posedge reset)
beginif (reset) beginreconfig_writedata <= {DPRIO_DATA_WIDTH{1'b0}}; end else beginif (next_state == WR) beginreconfig_writedata <= data_to_write;end else if (next_state == START) beginreconfig_writedata <= 32'd0;end end
end
// reconfigure done signal
always @ (posedge clock or posedge reset)
beginif (reset) beginreconfig_done <= 1'b0;end else beginif (clr_reconfig_done) beginreconfig_done <= 1'b0;end else if (next_state == DONE) beginreconfig_done <= 1'b1;end end
endassign dprioaddr_addr_ptr = num_exec;
assign valuemask_addr_ptr = pointer;endmodule 关于TX IOPLL(用于配置HDMI)的参数设置
void GPLL_RECONFIG(int GPLL_RANGE, int COLOR_DEPTH)
{IOWR(WD_TIMER_BASE, 0x0, 0x0); // clear timeout flagIOWR(WD_TIMER_BASE, 0x2, 0x1); // reset internal counterIOWR(WD_TIMER_BASE, 0x1, 0x4); // start timerswitch (GPLL_RANGE){case 0: // <50MHzGPLL_RCFG_WRITE(0x90, 0x00000F0F); // m 30GPLL_RCFG_WRITE(0xA0, 0x00010000); // n 1GPLL_RCFG_WRITE(0xC0, 0x00000303); // c0 6GPLL_RCFG_WRITE(0xC1, 0x00001E1E); // c1 60if (COLOR_DEPTH == 0) GPLL_RCFG_WRITE(0xC2, 0x00001E1E); // c2 60else if (COLOR_DEPTH == 1) GPLL_RCFG_WRITE(0xC2, 0x00002625); // c2 75else if (COLOR_DEPTH == 2) GPLL_RCFG_WRITE(0xC2, 0x00002D2D); // c2 90else GPLL_RCFG_WRITE(0xC2, 0x00003C3C); // c2 120GPLL_RCFG_WRITE(0x20, 0x00000010); // cpGPLL_RCFG_WRITE(0x40, 0x00000100); // bwGPLL_RCFG_WRITE(0x00, 0x00000001); // Write triggerbreak;case 1: // <70MHzGPLL_RCFG_WRITE(0x90, 0x00000A0A); // m 20GPLL_RCFG_WRITE(0xA0, 0x00010000); // n 1GPLL_RCFG_WRITE(0xC0, 0x00000202); // c0 4GPLL_RCFG_WRITE(0xC1, 0x00001414); // c1 40if (COLOR_DEPTH == 0) GPLL_RCFG_WRITE(0xC2, 0x00001414); // c2 40else if (COLOR_DEPTH == 1) GPLL_RCFG_WRITE(0xC2, 0x00001919); // c2 50else if (COLOR_DEPTH == 2) GPLL_RCFG_WRITE(0xC2, 0x00001E1E); // c2 60else GPLL_RCFG_WRITE(0xC2, 0x00002828); // c2 80GPLL_RCFG_WRITE(0x20, 0x0000000B); // cpGPLL_RCFG_WRITE(0x40, 0x000000C0); // bwGPLL_RCFG_WRITE(0x00, 0x00000001); // Write triggerbreak;case 2: // <100MHzGPLL_RCFG_WRITE(0x90, 0x00000505); // m 10GPLL_RCFG_WRITE(0xA0, 0x00010000); // n 1GPLL_RCFG_WRITE(0xC0, 0x00000101); // c0 2GPLL_RCFG_WRITE(0xC1, 0x00000A0A); // c1 20if (COLOR_DEPTH == 0) GPLL_RCFG_WRITE(0xC2, 0x00000A0A); // c2 20else if (COLOR_DEPTH == 1) GPLL_RCFG_WRITE(0xC2, 0x00000D0C); // c2 25else if (COLOR_DEPTH == 2) GPLL_RCFG_WRITE(0xC2, 0x00000F0F); // c2 30else GPLL_RCFG_WRITE(0xC2, 0x00001414); // c2 40GPLL_RCFG_WRITE(0x20, 0x00000010); // cpGPLL_RCFG_WRITE(0x40, 0x000000C0); // bwGPLL_RCFG_WRITE(0x00, 0x00000001); // Write triggerbreak;case 3: // <170MHzGPLL_RCFG_WRITE(0x90, 0x00000404); // m 8GPLL_RCFG_WRITE(0xA0, 0x00010000); // n 1GPLL_RCFG_WRITE(0xC0, 0x00000404); // c0 8GPLL_RCFG_WRITE(0xC1, 0x00000808); // c1 16if (COLOR_DEPTH == 0) GPLL_RCFG_WRITE(0xC2, 0x00000808); // c2 16else if (COLOR_DEPTH == 1) GPLL_RCFG_WRITE(0xC2, 0x00000A0A); // c2 20else if (COLOR_DEPTH == 2) GPLL_RCFG_WRITE(0xC2, 0x00000C0C); // c2 24else GPLL_RCFG_WRITE(0xC2, 0x00001010); // c2 32GPLL_RCFG_WRITE(0x20, 0x00000010); // cpGPLL_RCFG_WRITE(0x40, 0x000000C0); // bwGPLL_RCFG_WRITE(0x00, 0x00000001); // Write triggerbreak;case 4: // <340MHzGPLL_RCFG_WRITE(0x90, 0x00000404); // m 8GPLL_RCFG_WRITE(0xA0, 0x00010000); // n 1GPLL_RCFG_WRITE(0xC0, 0x00000202); // c0 4GPLL_RCFG_WRITE(0xC1, 0x00000404); // c1 8if (COLOR_DEPTH == 0) GPLL_RCFG_WRITE(0xC2, 0x00000404); // c2 8else if (COLOR_DEPTH == 1) GPLL_RCFG_WRITE(0xC2, 0x00000505); // c2 10else if (COLOR_DEPTH == 2) GPLL_RCFG_WRITE(0xC2, 0x00000606); // c2 12else GPLL_RCFG_WRITE(0xC2, 0x00000808); // c2 16GPLL_RCFG_WRITE(0x20, 0x00000010); // cpGPLL_RCFG_WRITE(0x40, 0x000000C0); // bwGPLL_RCFG_WRITE(0x00, 0x00000001); // Write triggerbreak;case 5: // <600MHzGPLL_RCFG_WRITE(0x90, 0x00000404); // m 8GPLL_RCFG_WRITE(0xA0, 0x00010000); // n 1GPLL_RCFG_WRITE(0xC0, 0x00000101); // c0 2GPLL_RCFG_WRITE(0xC1, 0x00000202); // c1 4if (COLOR_DEPTH == 0) GPLL_RCFG_WRITE(0xC2, 0x00000202); // c2 4else if (COLOR_DEPTH == 1) GPLL_RCFG_WRITE(0xC2, 0x00000302); // c2 5else if (COLOR_DEPTH == 2) GPLL_RCFG_WRITE(0xC2, 0x00000303); // c2 6else GPLL_RCFG_WRITE(0xC2, 0x00000404); // c2 8GPLL_RCFG_WRITE(0x20, 0x00000010); // cpGPLL_RCFG_WRITE(0x40, 0x000000C0); // bwGPLL_RCFG_WRITE(0x00, 0x00000001); // Write triggerbreak;default: // <600MHzGPLL_RCFG_WRITE(0x90, 0x00000404); // m 8GPLL_RCFG_WRITE(0xA0, 0x00010000); // n 1GPLL_RCFG_WRITE(0xC0, 0x00000101); // c0 2GPLL_RCFG_WRITE(0xC1, 0x00000202); // c1 4if (COLOR_DEPTH == 0) GPLL_RCFG_WRITE(0xC2, 0x00000202); // c2 4else if (COLOR_DEPTH == 1) GPLL_RCFG_WRITE(0xC2, 0x00000302); // c2 5else if (COLOR_DEPTH == 2) GPLL_RCFG_WRITE(0xC2, 0x00000303); // c2 6else GPLL_RCFG_WRITE(0xC2, 0x00000404); // c2 8GPLL_RCFG_WRITE(0x20, 0x00000010); // cpGPLL_RCFG_WRITE(0x40, 0x000000C0); // bwGPLL_RCFG_WRITE(0x00, 0x00000001); // Write triggerbreak;}READ_GPLL_RCFG_READY ();IOWR(WD_TIMER_BASE, 0x1, 0x8); // stop the timerIOWR(WD_TIMER_BASE, 0x0, 0x0); // clear timeout flagIOWR(WD_TIMER_BASE, 0x2, 0x1); // reset internal counter
}
在上面的程序中,关于COLOR_DEPTH,根据HDMI IP里面gcp的定义00:8位,01:10位,10:12位,11:16位,Nios程序中给出COLOR_DEPTH参数0,说明输出时是按8位定义的。