【GAOPS038】数据链路层PPP和HDLC协议

目录

概述

底层格式转换规则

上层协议包的交互

两者对比


概述

PPP帧格式与HDLC相似,不同的是PPP是面向字符也就是字节(7E),HDLC是面向位(连续的5个1)。

点对点协议(Point to Point Protocol,PPP)是数据链路层协议。替代了原来非标准的第二层协议,即 SLIP。PPP面向字节。

底层格式转换规则

PPP的帧格式

7E

FF

03

协议

信息

FCS

7E

字节

1

1

1

n

2

2

1

PPP采用7EH作为一帧的开始和结束标志(F);

其中地址域(A)和控制域(C)取固定值(A=FFH,C=03H) ;

协议域(两个字节)取0021H表示IP分组,取8021H表示网络控制数据,取C021H表示链路控制数据;

帧校验域(FCS)也为两个字节,它用于对信息域的校验。

若信息域中出现7EH,则转换为(7DH,5EH)两个字符。

如果0x7E出现在帧内部的话,需要出现问题,所以有两种解决方案:

在异步链路上使用字符填充(PPP),即把0x7E用0x7D5E替换

在同步链路上使用位填充(HDLC),即在连续的5个1之后填充一个0

当信息域出现7DH时,则转换为(7DH,5DH)。

若信息字段中出现ASCII码的控制字符(即数值小于0X20的字符),则该字符前面需要加入一个0x7D字节,同时将该字符的编码加以改变(+20),+20H也就是将bit5取反。例如,出现0x03,就要把它转为2字节序列(0x7D,0x23)

上层协议包的交互

简要描述,做底层的,咱也不清楚。

链路控制协议(LCP):一种扩展链路控制协议,用于建立、配置、测试和管理数据链路连接。

网络控制协议(NCP):协商该链路上所传输的数据包格式与类型,建立、配置不同的网络层协议;

为了建立点对点链路通信,PPP 链路的每一端,必须首先发送 LCP 包以便设定和测试数据链路。在链路建立,LCP 所需的可选功能被选定之后,PPP 必须发送 NCP 包以便选择和设定一个或更多的网络层协议。一旦每个被选择的网络层协议都被设定好了,来自每个网络层协议的数据报就能在链路上发送了。

两者对比

PPP协议 && HDLC协议

  相同点:

  (1) PPP、HDLC协议都支持全双工链路。

  (2) 都可以实现透明传输。

  (3) 都可以实现差错检测,但都不纠正差错。

  不同点:

  (1) PPP协议面向字节,HDLC协议面向比特。

  (2) HDLC协议帧格式没有协议字段。

  (3) PPP协议无序号和确认机制,HDLC协议有编号和确认机制。

  (4) PPP协议不可靠,HDLC协议可靠。

HDLC转换例子

11110011111100111111001111110111110111110000000000000
11100001001000000010101101000000000111000010000000001
00000101000000011101110100000011000000000000010000100
10010100101100101010101101000100011111100111111001111
110011111100



//lsb先发送
11110
01111110
01111110
01111110
11111111 FF
11000000 03
00000011 c0
10000100 21
10000000 01
10101101 B5
00000000 00
01110000 0E
10000000 01
00100000 04
10100000 05
00111011 DC
10100000 05
01100000 06
00000000 00
10000100 21
10010100 29
10110010 4D
10101011 D5
01000100 22
01111110 7E
01111110 7E
01111110 

01111110

遇到一个题目:编写HDLC数据链路层的插入0模块,常规思路是用状态机,实现11111序列检测。我在想能不能将串行的实现改为并行实现。插0规则:遇到连续5个1就插入1个0。不是在连续6个1种插入1个0

1次输入8bit待转换数据,数据上次最后5bit(提供上次连续1的个数)。

并行方案1:1拍出数据。8bit数据插入最多就能插入2个0,分3种情况:插入2个0情况,插入1个0情况,插入0个0情况。这样可以实现,但是综合出来的电路路径很长,意味着时序不好。

并行方案2:2拍出结果。实现1个模块,假定输入8bit中最多只插入1个0,实现1拍去掉1个0,两拍连起来就能将2个0去掉。可以考虑电路复用,能节省部分资源。

并行方案3:2拍出结果。将8bit数据拆分为2个4bit数据,先处理低4bit,再处理高4bit ,数据位宽小,组合逻辑路径短,加上电路课复用,资源时序最好,是我目前见到的最优解。但是具体verilog代码还没实现。

 

 

 

`timescale 1ns / 1ns
module insert (
    input               clk                     ,
    input               rst                     ,
    input               idata_vld               ,//本次数据有效
    input   [7:0]       idata                   ,//本次输入数据
    input   [4:0]       bef_data                ,//上个数据最后5bit,用来检查连续1的个数
    
    output  [9:0]       odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                   
    output  [4:0]       last_data               ,//本次的高5位,留给下次用                   
    output  reg         odata_vld               ,//本次输出数据有效
    output  [1:0]       vld_num                  //高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                  
);
    reg     [16:0]      aft_data                ;// {vld_num[1:0],pad[1:0],idata[7:0],bef_data[4:0]} vld[1:0]:2:pad中有两个有效;
    wire    [12:0]      com_data                ;
    
    assign com_data     =  {idata[7:0],bef_data[4:0]} ;
    
always@(posedge clk ) odata_vld <=#1  idata_vld ;
assign   {vld_num[1:0], odata[9:0],last_data[4:0]} = aft_data[16:0];


always@(posedge clk or posedge rst )begin
    if(rst) 
        aft_data<=#1 'b0;
    else if(~idata_vld) 
        aft_data<=#1 aft_data;
    else if(com_data[10:0] == 11'b111_1111_1111) //1
        aft_data <=#1   {2'd2,idata[7:5],1'b0,idata[4:0],1'b0,{idata[7:5],1'b0,idata[4]}   } ;
    else if(com_data[12:0] == 13'b1_1111_1011_1111)//2
        aft_data <=#1   {2'd2,idata[7:6],1'b0,idata[5:0],1'b0,{idata[7:6],1'b0,idata[5:4]} } ;
    else if(com_data[11:0] == 12'b1111_1111_1110)//3
        aft_data <=#1   {2'd2,idata[7:6],1'b0,idata[5:1],1'b0,idata[0]  ,{idata[7:6],1'b0,idata[5:4]} } ;
    else if(com_data[12:1] == 12'b1_1111_1111_110)//4
        aft_data <=#1   {2'd2,idata[7  ],1'b0,idata[6:2],1'b0,idata[1:0], {idata[7],1'b0,idata[6:4]} } ;
        
    else if(com_data[5:0] == 16'b11_1111)//只插入1个0,不放casex,因为会有覆盖
        aft_data <=#1   {2'd2,idata[7  ],1'b0,idata[6:2],1'b0,idata[1:0], {idata[7],1'b0,idata[6:4]} } ;
        
        
    else
        casex(com_data[12:0])
            // 13'bx_x111_1111_1111:  aft_data <=#1   {idata[7:5],1'b0,idata[4:0],1'b0,{idata[7:5],1'b0,idata[4]}   } ;
            // 13'b1_1111_1011_1111:  aft_data <=#1   {idata[7:6],1'b0,idata[5:0],1'b0,{idata[7:6],1'b0,idata[5:4]} } ;
            // 13'bx_1111_1111_1110:  aft_data <=#1   {idata[7:6],1'b0,idata[5:1],1'b0,idata[0]  ,{idata[7:6],1'b0,idata[5:4]} } ;
            // 13'b1_1111_1111_1100:  aft_data <=#1   {idata[7  ],1'b0,idata[6:2],1'b0,idata[1:0],{idata[7],1'b0,idata[6:4]}} ;
            
            13'bx_xxxx_xx11_1111:  aft_data <=#1   {2'd1,1'b0,idata[7:0],1'b0,idata[7:3]          } ;
            13'bx_xxxx_x111_1110:  aft_data <=#1   {2'd1,1'b0,idata[7:1],1'b0,idata[0],idata[7:3]  } ;
            13'bx_xxxx_1111_110x:  aft_data <=#1   {2'd1,1'b0,idata[7:2],1'b0,idata[1:0],idata[7:3]} ;
            13'bx_xxx1_1111_10xx:  aft_data <=#1   {2'd1,1'b0,idata[7:3],1'b0,idata[2:0],idata[7:3]} ;
            13'bx_xx11_1111_0xxx:  aft_data <=#1   {2'd1,1'b0,idata[7:4],1'b0,idata[3:0],{idata[7:4],1'b0}} ;
            13'bx_x111_1110_xxxx:  aft_data <=#1   {2'd1,1'b0,idata[7:5],1'b0,idata[4:0],{idata[7:5],1'b0,idata[4]}} ;
            13'bx_1111_110x_xxxx:  aft_data <=#1   {2'd1,1'b0,idata[7:6],1'b0,idata[5:0],{idata[7:6],1'b0,idata[5:4]}} ;
            13'b1_1111_10xx_xxxx:  aft_data <=#1   {2'd1,1'b0,idata[7]  ,1'b0,idata[6:0],{idata[  7],1'b0,idata[6:4]}} ;
            default:  aft_data <=#1   {2'd0,2'd0,idata[7:0],idata[7:3]} ;
        endcase
end


endmodule

// insert u_insert (
    // .clk      (                 ),//input               clk                     ,
    // .rst      (                 ),//input               rst                     ,
    // .idata_vld(                 ),//input               idata_vld               ,//本次数据有效
    // .idata    (                 ),//input   [7:0]       idata                   ,//本次输入数据
    // .bef_data (                 ),//input   [4:0]       bef_data                ,//上个数据最后5bit,用来检查连续1的个数

    // .odata    (                 ),//output  [9:0]       odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                   
    // .last_data(                 ),//output  [4:0]       last_data               ,//本次的高5位,留给下次用                   
    // .odata_vld(                 ),//output  reg         odata_vld               ,//本次输出数据有效
    // .vld_num  (                 ) //output  [1:0]       vld_num                 ,//高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                  
// );



`timescale 1ns / 1ns
module insert (
    input               clk                     ,
    input               rst                     ,
    input               idata_vld               ,//本次数据有效
    input   [7:0]       idata                   ,//本次输入数据
    input   [4:0]       bef_data                ,//上个数据最后5bit,用来检查连续1的个数
    
    output  [9:0]       odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                   
    output reg [4:0]    last_data               ,//本次的高5位,留给下次用                   
    output              odata_vld               ,//本次输出数据有效
    output  [1:0]       vld_num                  //高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                  
);
    reg                 idata_vld_1d=0          ;
    reg                 idata_vld_2d=0          ;
    wire    [16:0]      com_data                ;
    wire    [16:0]      com_data1               ;
    reg     [16:0]      data_sel                ;
    reg     [16:0]      data_match[5:13]        ;//能去参加匹配的只有0-13bit
    reg     [13:5]      match                   ;
    reg     [3:0]       match_sel               ;
    genvar              i                       ;
    
    
    assign com_data     =  {2'b0,2'b0,idata[7:0],bef_data[4:0]} ;
    assign com_data1    = idata_vld ?  com_data  : data_sel ;    
    // com_data1  D1:D0,C1:C0,B7:B0,A4:A0}  [16:15] [14:13] [12:5][4:0] {vld_num[1:0],pad[1:0],idata[7:0],bef_data[4:0]}
always@(posedge clk ) {idata_vld_2d , idata_vld_1d }<= #1 {idata_vld_1d , idata_vld } ;


    generate for(i=5;i<14;i=i+1) begin
        always@(posedge clk or posedge rst )begin
            if(rst) begin
                data_match[i]   <=#1 'b0;
                match[i]        <=#1 'b0;
            end else if(com_data1[i-:6]==6'b11_1111) begin
                if(idata_vld)begin
                    data_match[i][16:15]<=#1 {2'b01};
                end else if(idata_vld_1d) begin
                    data_match[i][16:15]<=#1 {2'b10};
                end
                data_match[i][14:0]<=#1 {com_data1[13:i],1'b0,com_data1[i-1:0]};
                match[i]<=#1 'b1;
            end  else   begin
                data_match[i]<=#1 com_data1 ;
                match[i]<=#1 'b0;  
        end
    end 
    end endgenerate
    
        always@(* )begin
            casex(match[13:5])//8:0
            9'Bxxxxx_xxx1:match_sel    =  'd0;
            9'Bxxxxx_xx10:match_sel    =  'd1;
            9'Bxxxxx_x100:match_sel    =  'd2;
            9'Bxxxxx_1000:match_sel    =  'd3;
            9'Bxxxx1_0000:match_sel    =  'd4;
            9'Bxxx10_0000:match_sel    =  'd5;
            9'Bxx100_0000:match_sel    =  'd6;
            9'Bx1000_0000:match_sel    =  'd7;
            9'B10000_0000:match_sel    =  'd8;
            default:match_sel    =  'd0;    
            endcase
        end  
        always@(* )begin
            case(match_sel[3:0]) 
            4'd0:data_sel    =  data_match[5+0];
            4'd1:data_sel    =  data_match[5+1];
            4'd2:data_sel    =  data_match[5+2];
            4'd3:data_sel    =  data_match[5+3];
            4'd4:data_sel    =  data_match[5+4];
            4'd5:data_sel    =  data_match[5+5];
            4'd6:data_sel    =  data_match[5+6];
            4'd7:data_sel    =  data_match[5+7];
            4'd8:data_sel    =  data_match[5+8];
            default:data_sel    =  data_match[0];  
            endcase
        end    
    
assign  {vld_num[1:0],odata[9:0] } =     data_sel[16:5];
        always@(* )begin
            case(vld_num[1:0]) 
            2'd0:last_data[4:0]    =  odata[7-:5];
            2'd1:last_data[4:0]    =  odata[8-:5];
            2'd2:last_data[4:0]    =  odata[9-:5];
            default:last_data[4:0] =  odata[7-:5];
            endcase
        end
assign  odata_vld   =     idata_vld_2d;
endmodule

// insert u_insert (
    // .clk      (                 ),//input               clk                     ,
    // .rst      (                 ),//input               rst                     ,
    // .idata_vld(                 ),//input               idata_vld               ,//本次数据有效
    // .idata    (                 ),//input   [7:0]       idata                   ,//本次输入数据
    // .bef_data (                 ),//input   [4:0]       bef_data                ,//上个数据最后5bit,用来检查连续1的个数

    // .odata    (                 ),//output  [9:0]       odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                   
    // .last_data(                 ),//output  [4:0]       last_data               ,//本次的高5位,留给下次用                   
    // .odata_vld(                 ),//output  reg         odata_vld               ,//本次输出数据有效
    // .vld_num  (                 ) //output  [1:0]       vld_num                 ,//高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                  
// );



`timescale 1ns / 1ns
module insert4bit (
    input               clk                     ,
    input               rst                     ,
    
    input   [3:0]       idata                   ,//本次输入数据bit[4]可能是无效数据,通过vld_bit4来区分
    input   [4:0]       iremain                 ,//上个数据最后5bit,用来检查连续1的个数
    input               idata_vld               ,//本次数据有效
    // input               ivld_num                ,//0:无 ,1:1个有效  
    
    output reg  [4:0]   odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                   
    output reg  [4:0]   oremain                 ,//本次的高5位,留给下次用                   
    output              odata_vld               ,//本次输出数据有效
    output reg          ovld_num                 //高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                  
);
    reg                 idata_vld_1d=0          ;
    wire    [8:0]       com_data                ;
    wire    [9:5]       match                   ;
    genvar              i                       ;
    assign com_data     =  {idata[3:0],iremain[4:0]} ;
    always@(posedge clk ) idata_vld_1d <= #1 idata_vld  ;
    generate for(i=4;i<9;i=i+1) begin:aa
        assign match[i+1] = &com_data[i-:5];
    end endgenerate
    always@(posedge clk or posedge rst )begin
        if(rst) begin
            odata[4:0]   <=#1 'b0;                          ovld_num    <=#1 'b0;oremain    <=#1 5'b0;
        end else if(match[5]) begin//在bit5插入0
            odata[4:0]   <=#1 {idata[3:0],1'b0};            ovld_num    <=#1 'b1;oremain    <=#1 {idata[3:0],1'b0};
        end else if(match[6]) begin//在bit6插入0
            odata[4:0]   <=#1 {idata[3:1],1'b0,idata[0]};   ovld_num    <=#1 'b1;oremain    <=#1 {idata[3:1],1'b0,idata[0]}; 
        end else if(match[7]) begin//在bit7插入0
            odata[4:0]   <=#1 {idata[3:2],1'b0,idata[1:0]}; ovld_num    <=#1 'b1;oremain    <=#1 {idata[3:2],1'b0,idata[1:0]};
        end else if(match[8]) begin//在bit8插入0
            odata[4:0]   <=#1 {idata[3],1'b0,idata[2:0]};   ovld_num    <=#1 'b1;oremain    <=#1 {idata[3],1'b0,idata[2:0]};
        end else if(match[9]) begin//在bit9插入0
            odata[4:0]   <=#1 {1'b0,idata[3:0]};            ovld_num    <=#1 'b1;oremain    <=#1 {1'b0,idata[3:0]};     
        end  else   begin
            odata[4:0]   <=#1 {1'b0,idata[3:0]};            ovld_num    <=#1 'b0;oremain    <=#1 {idata[3:0],iremain[4]};       
        end
    end     

assign  odata_vld   =     idata_vld_1d;
endmodule

// insert_step1 u_insert_step1 (
    // .clk      (                 ),//input               clk                     ,
    // .rst      (                 ),//input               rst                     ,
    // .idata_vld(                 ),//input               idata_vld               ,//本次数据有效
    // .idata    (                 ),//input   [3:0]       idata                   ,//本次输入数据
    // .bef_data (                 ),//input   [4:0]       bef_data                ,//上个数据最后5bit,用来检查连续1的个数
                                       
    // .odata    (                 ),//output  [5:0]       odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                    
    // .last_data(                 ),//output  [4:0]       last_data               ,//本次的高5位,留给下次用                   
    // .odata_vld(                 ),//output              odata_vld               ,//本次输出数据有效
    // .vld_num  (                 ) //output  [1:0]       vld_num                  //高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                   
// );


`timescale 1ns / 1ns
module insert (
    input               clk                     ,
    input               rst                     ,
    input               idata_vld               ,//本次数据有效
    input   [7:0]       idata                   ,//本次输入数据
    input   [4:0]       iremain                 ,//上个数据最后5bit,用来检查连续1的个数
    
    output reg  [9:0]   odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                   
    output reg [4:0]    oremain                 ,//本次的高5位,留给下次用                   
    output              odata_vld               ,//本次输出数据有效
    output reg  [1:0]   ovld_num                 //高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                  
);
    reg                 idata_vld_1d=0          ;
    reg                 idata_vld_2d=0          ;
    reg                 idata_vld_3d=0          ;


    reg     [4:0]       u0_odata_1d             ;
    reg     [4:0]       u0_oremain_1d           ;
    reg                 u0_odata_vld_1d         ;
    reg                 u0_ovld_num_1d          ;
    
    wire    [4:0]       u0_odata                ;
    wire    [4:0]       u0_oremain              ;
    wire                u0_odata_vld            ;
    wire                u0_ovld_num             ;
    
    wire    [4:0]       u1_odata                ;
    wire    [4:0]       u1_oremain              ;
    wire                u1_odata_vld            ;
    wire                u1_ovld_num             ;
    
    reg     [7:0]       idata_1d                ;
    
    
always@(posedge clk ) {idata_vld_3d,idata_vld_2d , idata_vld_1d }<= #1 {idata_vld_2d,idata_vld_1d , idata_vld } ;
always@(posedge clk ) idata_1d <= #1 idata ;
always@(posedge clk ) u0_odata_1d     <= #1 u0_odata     ;
always@(posedge clk ) u0_oremain_1d   <= #1 u0_oremain   ;
always@(posedge clk ) u0_odata_vld_1d <= #1 u0_odata_vld ;
always@(posedge clk ) u0_ovld_num_1d  <= #1 u0_ovld_num  ;

insert4bit  u0_insert4bit(
    .clk                (clk                   ),//input               clk                     ,
    .rst                (rst                   ),//input               rst                     ,
        
    .idata              (idata[3:0]            ),//input   [5:0]       idata                   ,//本次输入数据bit[4]可能是无效数据,通过vld_bit4来区分
    .iremain            (iremain               ),//input   [4:0]       iremain                 ,//上个数据最后5bit,用来检查连续1的个数
    .idata_vld          (idata_vld             ),//input               idata_vld               ,//本次数据有效
        
    .odata              (u0_odata              ),//output reg  [5:0]   odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                   
    .oremain            (u0_oremain            ),//output  [4:0]       oremain                 ,//本次的高5位,留给下次用                   
    .odata_vld          (u0_odata_vld          ),//output              odata_vld               ,//本次输出数据有效
    .ovld_num           (u0_ovld_num           ) //output reg [1:0]    ovld_num                 //高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                  
);
insert4bit  u1_insert4bit(
    .clk                (clk                   ),//input               clk                     ,
    .rst                (rst                   ),//input               rst                     ,
        
    .idata              (idata_1d[7:4]         ),//input   [5:0]       idata                   ,//本次输入数据bit[4]可能是无效数据,通过vld_bit4来区分
    .iremain            (u0_oremain            ),//input   [4:0]       iremain                 ,//上个数据最后5bit,用来检查连续1的个数
    .idata_vld          (u0_odata_vld          ),//input               idata_vld               ,//本次数据有效
        
    .odata              (u1_odata              ),//output reg  [5:0]   odata                   ,//输出插入0之后的数据,高2bit中的有效个数不定                   
    .oremain            (u1_oremain            ),//output  [4:0]       oremain                 ,//本次的高5位,留给下次用                   
    .odata_vld          (u1_odata_vld          ),//output              odata_vld               ,//本次输出数据有效
    .ovld_num           (u1_ovld_num           ) //output reg [1:0]    ovld_num                 //高2bit中的有效个数,0:无 ,1:1个有效 ,2:两个有效                  
);

always@(posedge clk )
    case({u0_ovld_num_1d,u1_ovld_num})
        {1'd0,1'd0} : begin     odata <= #1 {2'b0,u1_odata[3:0],u0_odata_1d[3:0]};ovld_num<= #1 2'd0;oremain<= #1 {u1_odata[3:0],u0_odata_1d[3]};end
        {1'd0,1'd1} : begin     odata <= #1 {1'b0,u1_odata[4:0],u0_odata_1d[3:0]};ovld_num<= #1 2'd1;oremain<= #1 {u1_odata[4:0]};end
        {1'd1,1'd1} : begin     odata <= #1 {     u1_odata[4:0],u0_odata_1d[4:0]};ovld_num<= #1 2'd2;oremain<= #1 {u1_odata[4:0]};end
        {1'd1,1'd0} : begin     odata <= #1 {1'b0,u1_odata[3:0],u0_odata_1d[4:0]};ovld_num<= #1 2'd1;oremain<= #1 {u1_odata[3:0],u0_odata_1d[0]};end
        {1'd1,1'd2} : begin     odata <= #1 {u1_odata[4:0],u0_odata_1d[4:0]};     ovld_num<= #1 2'd2;oremain<= #1 {u1_odata[4:0]};     end
        default     : begin     odata <= #1 'b0; ovld_num<= #1 2'd0;oremain<= #1 oremain;  end
    endcase

assign  odata_vld   =     idata_vld_3d;
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值