Main Content

データのパケット化

この例では、伝送シーケンスをパケット化する MATLAB® 設計からの HDL コードの生成方法を示します。

はじめに

無線通信システムの RF フロント エンドで受信データがオーバーサンプリングされています。これは、受信フィルターのために十分なサンプリング レートを提供するなど、いくつかの目的を果たします。

その中でも最も重要な役割の 1 つは、受信波形の最大振幅点の近くでデータをサンプリングできるように、受信波形で複数のサンプリング点を提供することです。この例では、再帰的に動作する基本的なリードラグ時間オフセット推定コアを示します。

この設計で生成されるハードウェア コアは 1/os_rate で動作します。os_rate はオーバーサンプリング レートです。つまり、このコアはオーバーサンプリングされた 8 クロック サイクルごとに 1 回反復されます。出力はシンボル レートです。

design_name = 'mlhdlc_comms_data_packet';
testbench_name = 'mlhdlc_comms_data_packet_tb';

この MATLAB 設計を見てみましょう。

type(design_name);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MATLAB design: Data packetization
%
% Introduction: 
%
% This core is meant to illustrate packetization of a transmit sequence.
% There is a "pad" data section, which allows for the transmit amplifier to
% settle. This is then followed by a 65-bit training sequence. This is
% followed by the number of symbols beginning encoded into two bytes or
% 16-bits. This is then followed by a variable length data sequence and a
% CRC. All bits can optionally be differentially encoded.
%
% Key design pattern covered in this example:
% (1) Design illustrates the us of binary operands, such as bitxor
% (2) Shows how to properly segment persistent variables for register an
% BRAM access
% (3) Illustrates the use of fi math
% (4) Shows how to properly format and store ROM data, e.g., padData

%   Copyright 2011-2015 The MathWorks, Inc.

%#codegen
function [symbolOut, reByte] = ...
    mlhdlc_comms_data_packet(emptyFlag, byteValue, numberSymbols, diffOn, Nts, Npad)

persistent trainBits1 padData
persistent valueCRC crcVector bitPrev
persistent inPacketFlag  bitOfByteIndex symbolCount

fm = hdlfimath;
if isempty(symbolCount)
    symbolCount = 1;
    inPacketFlag = 0;
    valueCRC = fi(1, 0,16,0, fm);
    bitOfByteIndex = 1; 
    bitPrev = fi(1, 0,1,0, fm);
    crcVector = zeros(1,16);
end
if isempty(trainBits1)
    % data-set already exists
    trainBits1 = TRAIN_DATA;
    padData = PAD_DATA;
end

%genPoly = 69665;
genPoly = fi(65535, 0,16,0, fm);
byteUint8 = uint8(byteValue);

reByte = 0;
symbolOut = fi(0, 0,1,0, fm);

%the first condition is whether or not we're currently processing a packet
if inPacketFlag == 1
    bitOut = fi(0, 0,1,0, fm);
    if symbolCount <= Npad
        bitOut(:) = padData(symbolCount);
    elseif symbolCount <= Npad+Nts
        bitOut(:) = trainBits1(symbolCount-Npad);
    elseif symbolCount <= Npad+Nts+numberSymbols
        bitOut(:) = bitget(byteUint8,9-bitOfByteIndex);
        bitOfByteIndex = bitOfByteIndex + 1;
        if bitOfByteIndex == 9 && symbolCount < Npad+Nts+numberSymbols
            bitOfByteIndex = 1;
            reByte = 1; % we've exhausted this one so pop new one off
        end
    elseif symbolCount <= Npad+Nts+numberSymbols+16
        bitOut(:) = 0;
    elseif symbolCount <= Npad+Nts+numberSymbols+32
        bitOut(:) = crcVector(symbolCount-(Npad+Nts+numberSymbols+16));
    else
        inPacketFlag = 0; %we're done
    end
    
    %leadValue = 0;
    % here we have the bit going out so if past Nts+Npad then form CRC.
    % Note that we throw 16 zeros on the end in order to flush the CRC
    if symbolCount > Npad+Nts && symbolCount <= Npad+Nts+numberSymbols+16
        
        valueCRCsh1 = bitsll(valueCRC, 1);
        valueCRCadd1 = bitor(valueCRCsh1, fi(bitOut, 0,16,0, fm));
        leadValue = bitget(valueCRCadd1,16);
        if leadValue == 1
            valueCRCxor = bitxor(valueCRCadd1, genPoly);
        else
            valueCRCxor = valueCRCadd1;
        end
        valueCRC = valueCRCxor;
        if symbolCount == Npad+Nts+numberSymbols+16
            crcVector(:) = bitget( valueCRC, 16:-1:1);
        end
    end

    if diffOn == 0 || symbolCount <= Npad+Nts
        symbolOut(:) = bitOut;
    else
        if bitPrev == bitOut
            symbolOut(:) = 1;
        else
            symbolOut(:) = 0;
        end
    end
    bitPrev(:) = symbolOut;

    symbolCount = symbolCount + 1; %total number of symbols transmitted
else
    % we're not processing a packet and waiting for a new packet to arrive
    if emptyFlag == 0
        % reset everything
        inPacketFlag = 1;
        % toggle re to grab data
        reByte = 1;
        symbolCount = 1;
        bitOfByteIndex = 1;
        valueCRC(:) = 65535;
        bitPrev(:) = 0;
    end
end
	  
end
type(testbench_name);
function mlhdlc_comms_data_packet_tb
%

%   Copyright 2011-2015 The MathWorks, Inc.

% generate transmit data, note the first two bytes are the data length
numberBytes = 8; % this is total number of symbols
numberSymbols = numberBytes*8;
rng(1); % always default to known state
data = [floor(numberBytes/2^8) mod(numberBytes,2^8) ...
    round(rand(1,numberBytes-2)*255)];

% generate training data helper function
make_train_data('TRAIN_DATA');

% make sure training data is generated
pause(2)
[~] = which('TRAIN_DATA');

trainBits1 = TRAIN_DATA;
Nts = length(trainBits1);

make_pad_data('PAD_DATA');
pause(2)
[~] = which('PAD_DATA');
Npad = 2^9;

% Give number of samples, where the start of the sequence flag will be
% (indicated by a zero), as well as an output buffer for generated symbols
Nsamp = 1000;
Noffset = 20;
emptyFlagHold = ones(1,Nsamp); emptyFlagHold(Noffset) = 0;
symbolOutHold = zeros(1,Nsamp);

dataIndex = 1;
byteValue = 0;
diffOn = 1; % 0 - regular encoding, 1 - differential encoding
for i1 = 1:Nsamp
    emptyFlag = emptyFlagHold(i1);
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Call to the design
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    [symbolOut, reByte] = ...
        mlhdlc_comms_data_packet(emptyFlag, byteValue, numberSymbols, diffOn, Nts, Npad);
    
    % This set of code emulates the external FIFO interface
    if reByte == 1 % when high, pop a value off the input FIFO
        byteValue = data(dataIndex);
        dataIndex = dataIndex + 1;
    end
    symbolOutHold(i1) = symbolOut;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This is all code to verify we did the encoding properly
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% grad training data - not differentially encoded
symbolTrain = symbolOutHold(1+Noffset+Npad:Noffset+Npad+Nts);

% grab user data and decode if necessary
symbolEst = zeros(1,numberSymbols);
symbolPrev = trainBits1(end);
if diffOn == 0
    symbolData = ...
        symbolOutHold(1+Noffset+Npad+Nts:Noffset+Npad+Nts+numberSymbols); %#ok<NASGU>
else
    % decoding is simply comparing adjacent received symbols
    symbolTemp = ...
       symbolOutHold(1+Noffset+Npad+Nts:Noffset+Npad+Nts+numberSymbols+32);
    for i1 = 1:length(symbolTemp)
        if symbolTemp(i1) == symbolPrev
            symbolEst(i1) = 1;
        else
            symbolEst(i1) = 0;
        end
        symbolPrev = symbolTemp(i1);
    end
end

% training data
trainDataEst = symbolTrain(1:Nts);
trainDiff = abs(trainDataEst-trainBits1');

% user data
userDataEst = symbolEst(1:numberSymbols);
dataEst = zeros(1,numberBytes);
for i1 = 1:numberBytes
    y = userDataEst((i1-1)*8+1:i1*8);
    dataEst(i1) = bin2dec(char(y+48));
end
userDiff = abs(dataEst-data);    

disp(['Training Difference: ',num2str(sum(trainDiff)), ...
    ' User Data Difference: ',num2str(sum(userDiff))]);

% run it through and check CRC
genPoly = 69665;
c = symbolEst;
cEst = c(1,:);
cEst2 = [cEst(1:end-32) cEst(end-15:end)];
cEst = cEst2;

valueCRCc = 65535;
for i1 = 1:length(cEst)
    valueCRCsh1 = bitsll(uint16(valueCRCc), 1);
    valueCRCadd1 = bitor(uint16(valueCRCsh1), cEst(i1));
    leadValue = bitget( valueCRCadd1, 16);
    if (leadValue == 1)
        valueCRCxor = bitxor(uint16(valueCRCadd1), uint16(genPoly));
    else
        valueCRCxor = bitxor(uint16(valueCRCadd1), 0);
    end
    valueCRCc = valueCRCxor;
end
if valueCRCc == 0
    disp('CRC decoded correctly');
else
    disp('CRC check failed');
end

function make_train_data(filename)
x  = load('mlhdlc_dpack_train_data.txt');
fid = fopen([filename,'.m'],'w+');
fprintf(fid,['function y = ' filename '\n']);
fprintf(fid,'%%#codegen\n');
fprintf(fid,'y = [\n');
fprintf(fid,'%1.0e\n',x);
fprintf(fid,'];\n');
fclose(fid);

function make_pad_data(filename) 
rng(1);
x = round(rand(1,2^9));
fid = fopen([filename,'.m'],'w+');
fprintf(fid,['function y = ' filename '\n']);
fprintf(fid,'%%#codegen\n');
fprintf(fid,'y = [\n');
fprintf(fid,'%1.0e\n',x);
fprintf(fid,'];\n');
fclose(fid);

設計のシミュレーション

コードの生成前にテスト ベンチを使用して設計のシミュレーションを実行し、実行時エラーが発生しないことを常に確認することをお勧めします。

mlhdlc_comms_data_packet_tb
Training Difference: 0 User Data Difference: 0
CRC decoded correctly

HDL Coder™ プロジェクトの新規作成

coder -hdlcoder -new mlhdlc_dpack

次に、mlhdlc_comms_data_packet.m ファイルを MATLAB 関数としてプロジェクトに追加し、mlhdlc_comms_data_packet_tb.m を MATLAB テスト ベンチとして追加します。

MATLAB HDL Coder プロジェクトの作成と入力に関する詳細なチュートリアルについては、MATLAB から HDL へのワークフロー入門を参照してください。

固定小数点変換と HDL コード生成の実行

[ワークフロー アドバイザー] ボタンからワークフロー アドバイザーを起動し、[コード生成] のステップを右クリックして [選択したタスクまで実行] オプションを選択し、最初から HDL コード生成までのすべてのステップを実行します。

コード生成ログのウィンドウにあるハイパーリンクをクリックして、生成された HDL コードを確認します。