参考手册:TMS320C6678用户手册。 https://blog.csdn.net/u014404875/article/details/79771589


1. DSP上电复位配置什么?


    DSP的大、小端,自启动(boot)模式,PCIe模式,网络协处理器时钟选择需要在上电复位的时候选择,怎么选择?
依靠上电时候锁定DSP Device Configuration pins(设备配置管脚)的逻辑电平。
    配置管脚的逻辑电平怎么设置?
一般采用两种方式:
  • 第一种是把DSP的配置管脚全部和FPGA的IO连接,由FPGA上电控制(文末附FPGA复位DSP程序)
  • 第二种是通过外部上拉/下拉电阻。
   提示:
    合理的板载设计应该确保所有的设备输入引脚都在一个有效电平而不能悬空,可以通过上拉/下拉电阻实现,当然可以内部上拉或外部上拉。
设备通过评估需求,一般内部实现上拉/下拉。但是一些管脚需要外部上拉/下拉。
    (1) 设备配置管脚:这些管脚同时需要输出(C6678的配置管脚和GPIO是公用管脚)且没有驱动(高阻态),即使内部上拉/下拉电阻也许满足需求电平,
但是外部上拉/下拉也是必须,目的是为了确保配置有效,也方便切换模式。
    (2) 其他输入管脚:如果内部上拉/下拉没有满足需求电平,则需要外部上拉/下拉。
    

2. TMS320C6678设备配置管脚

(1) LENDIAN :决定DSP的大小端。
(2) BOOTMODE[12:0] :决定DSP的自启动模式(详情见BootLoader for the C66x DSP User Guide)。
(3) PCIESSMODE : 决定PCIe子系统处于EP、legacy EP还是RC。
(4) PCIESSEN : 决定是否使能PICe 子系统,默认是不使能。
(5) PACKSEL: 决定网络协处理器的输入时钟是核时钟还是PASSCLK时钟。

3. DSP上电时序
    DSP的上电时序,就是上电复位的时序。
    设备初始化分为两个阶段:
(1) 所有的供电电源稳定,不同的电源有供电时序,可见下面时序图。
(2) RESET、POR、RESERFULL按时序拉高,当然还包括时钟输入稳定。

                                上电时序图
注意:
(1) 在电源稳定期间,POR要保持低电平,所以复位前拉低。
(2) DDRCLK、REFCLK应该在POR拉高前触发。
(3) 一旦获得DVDD18供电,RESETSTAT拉低。
      在DVDD18供电前,所有的LVCMOS输入和双向管脚不能驱动为低电平或拉高。
(4) 在DVDD18有效后,RESETSTAT可以在任何时刻被拉高。在POR控制boot下,RESET必须在POR拉高前拉高。
(5) 在电源稳定后,POR必须持续保持低电平至少100us。至此,电源稳定阶段结束。
(6) 在电源稳定阶段后设备初始化需要500个REFCLK时钟周期。最大时钟周期是33.33nsec,所以在POR上升沿前延迟16us是必要的。在整个16us期间,时钟必须是激活的。
(7) 在POR稳定在高电平之后,RESETFULL必须要保持低电平24个REFCLK时钟周期。
(8) 在RESETFULL上升沿,设备锁定GPIO 配置管脚的电平,然后进行配置,到复位状态位RESETSTAT信号拉高延迟大约10000到50000个时钟周期。
(9) GPIO配置必须在RESETFULL上升沿前保持至少12个REFCLK时钟周期(transitions)。
(10) GPIO配置必须在RESETFULL上升沿后保持至少12个REFCLK时钟周期(transitions)。
总的来说:
    在各个电源供电正常后,DSP的时钟稳定后,驱动RESET、POR、RESETFULL依次拉高,在RESETFULL的上升沿锁定DSP复位配置的GPIO电平,然后RESETSTAT拉高,则DSP上电复位完成。

4. DSP的复位模式
    总共四种复位模式,前三种复位模式都会触发RESETSTAT,局部复位不会触发RESETSTAT.
(1) 上电复位
(2) 硬件复位
(3) 软件复位
详见手册。
(4) 局部复位    

                                        局部复位时序图
上电复位后,可以进行局部复位,即对每个核单独复位。
局部复位可以被以下方式触发:
  • LRESET pin
  • Watchdog timer、CORESEL[3:0] and RSTCFG register
  • LPSC MMRs(memory-mapped registers)  


一般我们不使用局部复位,如果上电复位后,发现某些核处于复位状态,而其他核可以连接使用,多半是局部复位造成的,应该把LRESETNMIEN 设置为1,则可以避免这个问题。

5. FPGA控制DSP上电复位程序。
module DSP_RST(
        input clk_25m,
        input RESETSTAT,                     //DSP复位状态 0表示复位态 1表示工作态
        input LOCKED,                         //时钟模块是否正常

        output ref LRESETNMIENz = 1'b0,       //局部复位管脚
        output reg PORz=1'b0,                 //Power-on Reset
        output reg RESETFULL=1'b0,            //Full Reset
        output reg RESET=1'b0        
    );
        
        reg [2:0] RES_STATE=2'b00;
        reg [15:0] por_counter=16'b0,resetfull_counter=16'b0,reset_counter=16'b0;
        
        parameter IDLE=2'b00,PULL_RESET=2'b01,PULL_POR=2'b10,PULL_RESETFULL=2'b11;
        
always @(posedge clk_25m)
    if(LOCKED==1)
        begin
        case(RES_STATE)
        IDLE: 
                 RES_STATE<=PULL_RESET ;
        PULL_RESET: if(reset_counter<25000)
                            begin
                            reset_counter<=reset_counter+16'b1;
                            RES_STATE<=RES_STATE;
                            RESET<=1'b0;
                            PORz<=1'b0;
                            RESETFULL<=1'b0;
                            end
                        else
                            begin
                            RESET<=1'b1;
                            LRESETNMIENz<=1`b1;    //禁止局部复位。
                            RES_STATE<=PULL_POR;
                            end
        PULL_POR: if(por_counter<25000)  
                            begin
                            por_counter<=por_counter+16'b1;
                            RES_STATE<=RES_STATE;
                            PORz<=1'b0;
                            end
                     else
                            begin
                            PORz<=1'b1;
                            RES_STATE<=PULL_RESETFULL;
                            end
        PULL_RESETFULL:if(resetfull_counter<25000)
                                begin
                                resetfull_counter<=resetfull_counter+16'b1;
                                RES_STATE<=RES_STATE;
                                RESETFULL<=1'b0;
                                end
                            else
                                begin
                                RESETFULL<=1'b1;
                                RES_STATE<=RES_STATE;
                                end
        endcase                
        end
    else
        begin
        reset_counter<=16'b0;
        resetfull_counter<=16'b0;
        por_counter<=16'b0;
        RES_STATE<=IDLE;
        RESET<=1'b0;
        PORz<=1'b0;
        RESETFULL<=1'b0;
        end

endmodule`