Data Packetization
This example shows how to generate HDL code from a MATLAB® design that packetizes a transmit sequence.
Introduction
In wireless communication systems receive data is oversampled at the RF front end. This serves several purposes, including providing sufficient sampling rates for receive filtering.
However, one of the most important functions is to provide multiple sampling points on the received waveform such that data can be sampled near the maximum amplitude point in the received waveform. This example illustrates a basic lead-lag time offset estimation core, operating recursively.
The generated hardware core for this design operates at 1/os_rate where os_rate is the oversampled rate. That is, for 8 oversampled clock cycles this core iterates once. The output is at the symbol rate.
design_name = 'mlhdlc_comms_data_packet'; testbench_name = 'mlhdlc_comms_data_packet_tb';
Let us take a look at the MATLAB design.
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);
Simulate the Design
It is always a good practice to simulate the design with the testbench prior to code generation to make sure there are no runtime errors.
mlhdlc_comms_data_packet_tb
Training Difference: 0 User Data Difference: 0 CRC decoded correctly
Create a New HDL Coder™ Project
coder -hdlcoder -new mlhdlc_dpack
Next, add the file mlhdlc_comms_data_packet.m
to the project as the MATLAB Function and mlhdlc_comms_data_packet_tb.m
as the MATLAB Test Bench.
Refer to Get Started with MATLAB to HDL Workflow for a more complete tutorial on creating and populating MATLAB HDL Coder projects.
Run Fixed-Point Conversion and HDL Code Generation
Launch the Workflow Advisor from the Workflow Advisor button and right-click on the Code Generation step and choose the option Run to selected task to run all the steps from the beginning through the HDL code generation.
Examine the generated HDL code by clicking on the hyperlinks in the Code Generation Log window.