Menu Close

高速通信中的信道编码–加扰与解扰(乘性加扰实验)

在课程高速通信中的信道编码–加扰与解扰 中,我们学习了乘性加扰的算法,但不是一个完整的通讯工程。之前我们学习过使用400M时钟对100M的通讯数据采样,学习过400M下的得到的数据如何同步到100M时钟域下。利用我们之前学习过的知识,增加乘性加扰,解扰算法,就可以实现整个通讯工程了。

 

仿真文件:

`timescale 1 ns / 1 ps
module tb
       (
       );

parameter SYNC1 = 8'b1010_1010;
parameter SYNC2 = 8'b1010_1011;

parameter PERIOD = 20 ;    //周期20
reg pll_rst;     //实体模块PLL的rst信号
wire tx_rx;      // 收发在testbench的回环信号

wire clk_100M;
wire pll_locked;    //实体PLL锁定信号
wire rst = !pll_locked;     //Testbench内生成复位信号

reg [ 7: 0 ] tx_data;      //待发送数据

wire rx_vld;
wire rx_rdy;
wire [ 7: 0 ] rx_data;
reg inclk ;       // 模拟板级提供的输入时钟

reg [ 2: 0 ] tx_st;

initial
begin
    inclk = 1'b0;
    #( PERIOD / 2 );

    forever
        #( PERIOD / 2 ) inclk = ~inclk;
end

//always #10 inclk=~inclk;

initial
begin
    pll_rst = 1'b1;
    tx_data = 0;
    #50 pll_rst = 1'b0;
end

wire tx_rdy;
reg  tx_vld = 0;
reg  tx_en = 0;

reg [5:0] send_cnt = 0;
always@( posedge clk_100M or posedge rst )

    if ( rst )
    begin
        tx_en <= 0;
        tx_st <= 0;
        tx_data <= 0;
    end
    else
    begin
        case ( tx_st )
            0:
            begin
                tx_en <= 0;
                send_cnt <= 0;
                tx_data <= 0;
                tx_vld <= 0;
                tx_st <= 1;
            end
            1:
            begin
                tx_vld <= 1;
                tx_st <= 2;
            end
            2:
            begin
                if(tx_rdy)
                begin
                    tx_data <= 0;
                    tx_en <= 1;
                    send_cnt <= send_cnt + 1;
                    
//                    if(send_cnt == 7)
                        tx_st <= 3;
                end
            end
            3:
            begin
                tx_en <= 0;
                if(tx_rdy)
                begin
                    tx_en <= 1;
                    tx_data <= tx_data + 1;
                    send_cnt <= send_cnt + 1;

//                    if ( send_cnt == 23 )
                    if ( send_cnt == 31 )
                    begin
                        send_cnt <= 0;
                        tx_st <= 7;
                    end
                end
            end
            6:
            begin
                if(tx_rdy)
                begin
                    tx_data <= 8'hff;
                    send_cnt <= send_cnt + 1;
                    
                    if(send_cnt == 31)
                    begin
                        send_cnt <= 0;
                        tx_st <= 7;
                    end
                end
            end
            7:
            begin
                tx_en <= 0;
                tx_vld <= 0;           
                send_cnt <= send_cnt + 1;
                
                if(&send_cnt)
                begin
                    tx_st <= 0;
                end
            end

            default:
                tx_st <= 0;

        endcase
    end


hs_txrx hs_txrx_inst
(
    .inclk      ( inclk ),
    .pll_rst    ( pll_rst ),

    .tx_data    ( tx_data ),
    .tx_en      ( tx_en ),
    .tx_rdy     ( tx_rdy ),
    .tx_vld     ( tx_vld ),

    .tx         ( tx_rx ),
    .rx         ( tx_rx ),

    .rx_vld     ( rx_vld ),
    .rx_rdy     ( rx_rdy ),
    .rx_data    ( rx_data ),

    .clk_100M   ( clk_100M ),
    .pll_locked ( pll_locked )

);

endmodule

 

testbench 文件和加性加扰中使用的tb 文件相同。

 

顶层文件:

module hs_txrx
#(
    parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
//    parameter SCRAMB_SYNC = 23'b0,
    parameter SYNC1 = 8'b1010_1010,
    parameter SYNC2 = 8'b1010_1011
)
(
    input  inclk,
    input  pll_rst,

    input  [ 7: 0 ] tx_data,
    input  tx_en,
    output tx_rdy,
    input  tx_vld,

    output tx,
    input  rx,

    output rx_rdy,
    output rx_vld,
    output [ 7: 0 ] rx_data,

    output clk_100M,
    output pll_locked
);


wire clk_400M;

wire rst = !pll_locked;



tx_pcs
#(
    .SCRAMB_SYNC( SCRAMB_SYNC ),
    .SYNC1      ( SYNC1 ),
    .SYNC2      ( SYNC2 )
)
tx_pcs_inst
(
    .rst        ( rst ),
    .clk_100M   ( clk_100M ),
    .tx_data    ( tx_data ),    // 100M的时钟对应的数据
    .tx_en      ( tx_en ),
    .tx_vld     ( tx_vld ),
    .tx_rdy     ( tx_rdy ),
    .tx_out     ( tx )
);

           
rev_pcs
#(
    .SCRAMB_SYNC( SCRAMB_SYNC ),
    .SYNC1      ( SYNC1 ),
    .SYNC2      ( SYNC2 )
)
recv_pcs_inst
(
    .rst        ( rst ),
    .clk_100M   ( clk_100M ),
    .clk_400M   ( clk_400M ),
    
    .rx_vld     ( rx_vld ),
    .rx_data    ( rx_data ),
    .rx_rdy     ( rx_rdy ),

    .rx         ( rx )
);


pll1 pll1_inst
(
    .areset ( pll_rst ),    //1'b0;
    .inclk0 ( inclk ),
    .c0     ( clk_10M ),
    .c1     ( clk_100M ),
    .c2     ( clk_400M ),
    .locked ( pll_locked )
);


endmodule

 

tx_pcs.v

module tx_pcs
#(
    parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
    parameter SYNC1 = 8'b1010_1010,
    parameter SYNC2 = 8'b1010_1011
)
(
    input  clk_100M,

    input  tx_vld,
    input  [ 7: 0 ] tx_data,    // 100M的时钟对应的数据
    input  tx_en,
    output reg tx_rdy = 0,
    
    output tx_out,
    input  rst
);



reg tx_en_r;
reg tx_en_ack;
always@( posedge clk_100M or posedge rst )
if ( rst )
begin
    tx_en_r <= 0;
end
else
begin
    if ( tx_en )
    begin
        tx_en_r <= 1'b1;
    end
    else if ( tx_en_ack )
        tx_en_r <= 0;
end


reg [ 7: 0 ] tx_data_r;
reg [ 7: 0 ] tx_sht;
reg [ 2: 0 ] tx_sht_count;

reg [ 1: 0 ] tx_st;

always@( posedge clk_100M or posedge rst )
if ( rst )
begin
    tx_data_r <= SYNC1;
    tx_sht <= SYNC1;
    tx_sht_count <= 0;
    tx_rdy <= 1'b0;
    tx_en_ack <= 1'b0;
    tx_st <= 0;
end
else
begin
    case ( tx_st )
        0:
        begin
            tx_data_r <= SYNC1;
            tx_sht <= tx_data_r;
            tx_sht_count <= 0;
            tx_rdy <= 1'b0;
            tx_en_ack <= 1'b0;
            tx_st <= 1;
        end
        1:
        begin
            tx_rdy <= 1'b0;

            if ( tx_sht_count == 7 )
            begin
                tx_sht <= tx_data_r;
                tx_sht_count <= 0;

                if ( tx_vld )
                begin
                    tx_data_r <= SYNC2;
                    tx_en_ack <= 1'b1;
                    tx_rdy <= 1'b1;
                    tx_st <= 2;
                end
            end
            else
            begin
                tx_sht <= { 1'b0, tx_sht[ 7: 1 ] };
                tx_sht_count <= tx_sht_count + 1'b1;
            end
        end
        2:
        begin
            tx_en_ack <= 1'b0;
            tx_rdy <= 1'b0;

            if ( tx_sht_count == 7 )
            begin
                tx_sht <= tx_data_r;

                tx_sht_count <= 0;

                if ( tx_en_r )
                begin
                    tx_en_ack <= 1'b1;
                    tx_data_r <= tx_data;
                    tx_rdy <= 1'b1;
                end
                else if ( !tx_vld )
                begin
                    tx_en_ack <= 1'b1;
                    tx_data_r <= SYNC1;
                    tx_st <= 3;
                end
            end
            else
            begin
                tx_sht <= { 1'b0, tx_sht[ 7: 1 ] };
                tx_sht_count <= tx_sht_count + 1'b1;
            end

        end
        3:
        begin
            tx_en_ack <= 1'b0;
            tx_rdy <= 1'b0;

            if ( tx_sht_count == 6 )
                tx_st <= 0;

            tx_sht <= { 1'b0, tx_sht[ 7: 1 ] };
            tx_sht_count <= tx_sht_count + 1'b1;
        end
        
        default:  tx_st <= 0;
    endcase
end

wire tx_bit = tx_sht[ 0 ];

trans_pma  # (.SCRAMB_SYNC ( SCRAMB_SYNC ) )
trans_pma_inst
(
    .clk_100M   ( clk_100M ),
    .tx_in      ( tx_bit ),
    .tx_out     ( tx_out ),
    .rst        ( rst )
);
    

endmodule

 

trans_pma.v

module trans_pma
#(
    parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001
)
(
    input  clk_100M,

    input  tx_in,    // 100M的时钟对应的数据
    output tx_out,
    
    input  rst
);
reg [ 22: 0 ] scb_shift;

wire tx_tmp = tx_in ^ ( scb_shift[ 17 ] ^ scb_shift[ 22 ] );

reg tx_out_r = 0;
always@( posedge clk_100M or posedge rst )
if ( rst )
begin
    scb_shift <= SCRAMB_SYNC;
    tx_out_r <= 0;
end
else
begin
    tx_out_r <= tx_tmp;
    scb_shift <= { scb_shift[ 21: 0 ], tx_tmp };
end


// pmd
IO_TX IO_TX_inst
(
    .tx_in  ( tx_out_r ),
    .tx_out ( tx_out )
);


endmodule

 

recv_data.v

module recv_data
#(
    parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
    parameter SYNC1 = 8'b1010_1010,
    parameter SYNC2 = 8'b1010_1011
)
(
    input  rst,
    input  clk_100M,
    input  clk_400M,
    input  rx,
    output reg sync = 0,
    output reg[ 7: 0 ] rx_data_100Mr,
    output reg rx_data_vld_100Mr
);


wire rx_bit;
wire rx_bit_vld;

reg rx_out_r = 0;
reg rx_out_en = 0;

reg [ 22: 0 ] scb_shift;
wire rx_tmp = rx_bit ^ ( scb_shift[ 17 ] ^ scb_shift[ 22 ] );

always@( posedge clk_400M or posedge rst )
if ( rst )
begin
    rx_out_en <= 0;
    scb_shift <= SCRAMB_SYNC;
    rx_out_r <= 0;
end
else
begin
    rx_out_en <= 0;
    
    if( rx_bit_vld )
    begin
        rx_out_r <= rx_tmp;
        rx_out_en <= 1;
        scb_shift <= { scb_shift[ 21: 0 ], rx_bit };
    end
end
    

reg [ 3: 0 ] bit_count;
reg [ 7: 0 ] bit_sft;
reg [ 7: 0 ] sync_shift = 0;

reg fr_sync1, fr_sync2;
reg fr_sync;

reg fr_end;
reg [ 7: 0 ] fr_count;

reg[ 7: 0 ] rx_data;
reg rx_data_vld_tmp;

always@( posedge clk_400M or posedge rst )
if ( rst )
begin
    rx_data <= 0;
    rx_data_vld_tmp <= 0;
    bit_count <= 0;
    bit_sft <= 0;
    fr_sync1 <= 0;
    fr_sync2 <= 0;
    fr_sync <= 0;
    fr_end <= 0;
    fr_count <= 0;
end
else
begin
    if ( rx_out_en )
    begin
        bit_sft <= { rx_out_r, bit_sft[ 7: 1 ]};
        sync_shift <= { bit_sft[ 0 ], sync_shift[ 7: 1] };
    end
    
    if ( fr_sync )
        fr_sync2 <= 1'b0;
    else if ( bit_sft == SYNC2 )
        fr_sync2 <= 1'b1;         //fr----frame
    else
        fr_sync2 <= 1'b0;

    if ( fr_sync )
        fr_sync1 <= 1'b0;
    else if ( sync_shift == SYNC1 )
        fr_sync1 <= 1'b1;
    else
        fr_sync1 <= 1'b0;

    if ( fr_end )
        fr_sync <= 1'b0;
    else if ( fr_sync1 & fr_sync2 & rx_out_en )
//    else if ( fr_sync1 & fr_sync2 )
        fr_sync <= 1'b1;

    if ( fr_sync )
    begin
        if ( rx_out_en )
        begin
            if ( bit_count == 7 )
                bit_count <= 0;
            else
                bit_count <= bit_count + 1;
        end
    end

    rx_data_vld_tmp <= 0;

    if ( bit_count == 7 )
    begin
        rx_data <= bit_sft;
        rx_data_vld_tmp <= 1'b1;
    end

    fr_end <= 1'b0;

    if ( rx_data_vld_tmp & rx_out_en )
        if ( fr_count == 31 )
        begin
            fr_end <= 1'b1;
            fr_count <= 0;
        end
        else
            fr_count <= fr_count + 1;
end

     
wire rx_data_vld = rx_data_vld_tmp & rx_out_en;     

reg rx_data_vld_r;
reg [ 5: 0 ] count_400M;
reg rx_data_vld_x;
reg nrx_data_vld_x;
reg rx_data_vld_xrg;

always@( posedge clk_400M or posedge rst )
if ( rst )
begin
    count_400M <= 0;
    rx_data_vld_r <= 0;
end
else
begin
    if ( rx_data_vld )
        rx_data_vld_r <= 1'b1;
    else if ( count_400M == 15 )
        rx_data_vld_r <= 1'b0;

    if ( count_400M == 15 )
        count_400M <= 0;
    else if ( rx_data_vld_r )
        count_400M <= count_400M + 1;
end

always@( posedge clk_100M or posedge rst )
if ( rst )
begin
    rx_data_vld_x <= 1'b0;
    nrx_data_vld_x <= 1'b1;

    rx_data_vld_xrg <= 1'b0;

    rx_data_100Mr <= 0;
    rx_data_vld_100Mr <= 1'b0;
end
else
begin
    rx_data_vld_x <= rx_data_vld_r;
    nrx_data_vld_x <= !rx_data_vld_x;
    rx_data_vld_xrg <= nrx_data_vld_x & rx_data_vld_x;

    rx_data_vld_100Mr <= 1'b0;

    if ( rx_data_vld_xrg )
    begin
        rx_data_100Mr <= rx_data;
        rx_data_vld_100Mr <= 1'b1;
    end
end


always @ (posedge clk_100M)
    sync <= fr_sync;


recv_bit recv_bit_inst
(
    .rst        ( rst ),
    .clk_400M   ( clk_400M ),
    .rx         ( rx ),
    .rx_bit     ( rx_bit ),
    .rx_bit_vld ( rx_bit_vld )

);


endmodule

 

rec_pcs.v

module rev_pcs
#(
    parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
    parameter SYNC1 = 8'b1010_1010,
    parameter SYNC2 = 8'b1010_1011
)
(
    input  rx,

    output reg rx_vld = 0,
    output rx_rdy,
    output [ 7: 0 ] rx_data,

    input  clk_100M,
    input  clk_400M,
    input  rst
);


wire sync;
    
recv_data
#(
    .SCRAMB_SYNC ( SCRAMB_SYNC ),
    .SYNC1( SYNC1 ),
    .SYNC2( SYNC2 )
)
recv_data_inst
(
    .rst                ( rst ),
    .clk_100M           ( clk_100M ),
    .clk_400M           ( clk_400M ),
    .sync               ( sync ),
    .rx                 ( rx ),
    .rx_data_100Mr      ( rx_data ),
    .rx_data_vld_100Mr  ( rx_rdy )
);


always @ (posedge clk_100M)
if(sync) rx_vld <= 1;
else  if(rx_rdy) rx_vld <= 0;


endmodule

 

recv_data.v

module recv_data
#(
    parameter SCRAMB_SYNC = 23'b1001_0001_1000_0000_1010_1001,
    parameter SYNC1 = 8'b1010_1010,
    parameter SYNC2 = 8'b1010_1011
)
(
    input  rst,
    input  clk_100M,
    input  clk_400M,
    input  rx,
    output reg sync = 0,
    output reg[ 7: 0 ] rx_data_100Mr,
    output reg rx_data_vld_100Mr
);


wire rx_bit;
wire rx_bit_vld;

reg rx_out_r = 0;
reg rx_out_en = 0;

reg [ 22: 0 ] scb_shift;
wire rx_tmp = rx_bit ^ ( scb_shift[ 17 ] ^ scb_shift[ 22 ] );

always@( posedge clk_400M or posedge rst )
if ( rst )
begin
    rx_out_en <= 0;
    scb_shift <= SCRAMB_SYNC;
    rx_out_r <= 0;
end
else
begin
    rx_out_en <= 0;
    
    if( rx_bit_vld )
    begin
        rx_out_r <= rx_tmp;
        rx_out_en <= 1;
        scb_shift <= { scb_shift[ 21: 0 ], rx_bit };
    end
end
    

reg [ 3: 0 ] bit_count;
reg [ 7: 0 ] bit_sft;
reg [ 7: 0 ] sync_shift = 0;

reg fr_sync1, fr_sync2;
reg fr_sync;

reg fr_end;
reg [ 7: 0 ] fr_count;

reg[ 7: 0 ] rx_data;
reg rx_data_vld_tmp;

always@( posedge clk_400M or posedge rst )
if ( rst )
begin
    rx_data <= 0;
    rx_data_vld_tmp <= 0;
    bit_count <= 0;
    bit_sft <= 0;
    fr_sync1 <= 0;
    fr_sync2 <= 0;
    fr_sync <= 0;
    fr_end <= 0;
    fr_count <= 0;
end
else
begin
    if ( rx_out_en )
    begin
        bit_sft <= { rx_out_r, bit_sft[ 7: 1 ]};
        sync_shift <= { bit_sft[ 0 ], sync_shift[ 7: 1] };
    end
    
    if ( fr_sync )
        fr_sync2 <= 1'b0;
    else if ( bit_sft == SYNC2 )
        fr_sync2 <= 1'b1;         //fr----frame
    else
        fr_sync2 <= 1'b0;

    if ( fr_sync )
        fr_sync1 <= 1'b0;
    else if ( sync_shift == SYNC1 )
        fr_sync1 <= 1'b1;
    else
        fr_sync1 <= 1'b0;

    if ( fr_end )
        fr_sync <= 1'b0;
    else if ( fr_sync1 & fr_sync2 & rx_out_en )
        fr_sync <= 1'b1;

    if ( fr_sync )
    begin
        if ( rx_out_en )
        begin
            if ( bit_count == 7 )
                bit_count <= 0;
            else
                bit_count <= bit_count + 1;
        end
    end

    rx_data_vld_tmp <= 0;

    if ( bit_count == 7 )
    begin
        rx_data <= bit_sft;
        rx_data_vld_tmp <= 1'b1;
    end

    fr_end <= 1'b0;

    if ( rx_data_vld_tmp & rx_out_en )
        if ( fr_count == 31 )
        begin
            fr_end <= 1'b1;
            fr_count <= 0;
        end
        else
            fr_count <= fr_count + 1;
end

     
wire rx_data_vld = rx_data_vld_tmp & rx_out_en;     

reg rx_data_vld_r;
reg [ 5: 0 ] count_400M;
reg rx_data_vld_x;
reg nrx_data_vld_x;
reg rx_data_vld_xrg;

always@( posedge clk_400M or posedge rst )
if ( rst )
begin
    count_400M <= 0;
    rx_data_vld_r <= 0;
end
else
begin
    if ( rx_data_vld )
        rx_data_vld_r <= 1'b1;
    else if ( count_400M == 15 )
        rx_data_vld_r <= 1'b0;

    if ( count_400M == 15 )
        count_400M <= 0;
    else if ( rx_data_vld_r )
        count_400M <= count_400M + 1;
end

always@( posedge clk_100M or posedge rst )
if ( rst )
begin
    rx_data_vld_x <= 1'b0;
    nrx_data_vld_x <= 1'b1;

    rx_data_vld_xrg <= 1'b0;

    rx_data_100Mr <= 0;
    rx_data_vld_100Mr <= 1'b0;
end
else
begin
    rx_data_vld_x <= rx_data_vld_r;
    nrx_data_vld_x <= !rx_data_vld_x;
    rx_data_vld_xrg <= nrx_data_vld_x & rx_data_vld_x;

    rx_data_vld_100Mr <= 1'b0;

    if ( rx_data_vld_xrg )
    begin
        rx_data_100Mr <= rx_data;
        rx_data_vld_100Mr <= 1'b1;
    end
end


always @ (posedge clk_100M)
    sync <= fr_sync;


recv_bit recv_bit_inst
(
    .rst        ( rst ),
    .clk_400M   ( clk_400M ),
    .rx         ( rx ),
    .rx_bit     ( rx_bit ),
    .rx_bit_vld ( rx_bit_vld )

);


endmodule

 

仿真波形:

图1

如图1 所示:紫色的为发送数据相关的信号, 黄色为接收相关的信号,从顶层仿真可以看出, 发送的数据可以被完整的接收到。

图2

图2所示:发送的tx_pcs 层,可以看到增加了aa,ab (preamble , sfd) 字节。

图3

如图3所示:在发送数据结束后,发送aa(preamble)。

图4

如图4所示:在接收端检测到aa,ab后(preamble ,sfd)启动fr_sync,定位数据流。 接下来就可以正常解码数据了。

图5

如图5所示:这时仿真顶层文件中, 发送第一包数据, 接收端并没有接收到, 从发送的第二包开始,之后的数据包,都可以被接收端正确接收。

图6

如图6所示:在每两包之间发送的aa (preamble) ,在线路上的编码是不同的。

图7

如图7 所示: 加扰后的波形,在局部也有可能出现直流不平衡。

 

具体内容讲解,请参照视频教程。

quarts 工程代码:

[content_control]

multi_scrambler_prj.zip

[/content_control]

Posted in FPGA, FPGA 教材教案, Verilog, 教材与教案, 文章

发表回复

相关链接