В этом примере показано, как сгенерировать HDL-код из проекта MATLAB ®, который пакетизирует последовательность передачи.
В системах радиосвязи данные приема переизбираются на РЧ переднем конце. Это служит нескольким целям, включая обеспечение достаточных частот дискретизации для фильтрации приема.
% 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';
Давайте рассмотрим проект 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_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos'); mlhdlc_temp_dir = [tempdir 'mlhdlc_dpack']; % Create a temporary folder and copy the MATLAB files. cd(tempdir); [~, ~, ~] = rmdir(mlhdlc_temp_dir, 's'); mkdir(mlhdlc_temp_dir); cd(mlhdlc_temp_dir); copyfile(fullfile(mlhdlc_demo_dir, [design_name,'.m*']), mlhdlc_temp_dir); copyfile(fullfile(mlhdlc_demo_dir, [testbench_name,'.m*']), mlhdlc_temp_dir);
Всегда рекомендуется моделировать проект с помощью тестбенча перед генерацией кода, чтобы убедиться, что нет ошибок во время выполнения.
mlhdlc_comms_data_packet_tb
Training Difference: 0 User Data Difference: 0 CRC decoded correctly
coder -hdlcoder -new mlhdlc_dpack
Затем добавьте файл 'mlhdlc _ comms _ данные _ packet.m' к проекту в качестве функции MATLAB и 'mlhdlc _ comms _ данные _ packet _ tb.m' в качестве испытательного стенда MATLAB.
Более полное руководство по созданию и заполнению проектов MATLAB HDL Coder см. в разделе «Начало работы с MATLAB в HDL».
Запустите Workflow Advisor на вкладке Build и щелкните правой нажатие кнопки по шагу 'Генерация Кода' и выберите опцию 'Run to selected task', чтобы запустить все шаги от начала до генерации HDL-кода.
Исследуйте сгенерированный HDL-код, нажав на гиперссылки в Генерацию кода Журнала окне.
Для очистки временной папки проекта можно запустить следующие команды.
mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos'); mlhdlc_temp_dir = [tempdir 'mlhdlc_dpack']; clear mex; cd (mlhdlc_demo_dir); rmdir(mlhdlc_temp_dir, 's');