データのパケット化
この例では、伝送シーケンスをパケット化する 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 コードを確認します。