474 lines
17 KiB
Matlab
474 lines
17 KiB
Matlab
function [data_out ,state] = prms(data_in, state, para)
|
|
|
|
global loop loopmax
|
|
|
|
if nargin==0
|
|
if loop==-1,
|
|
|
|
% Abfrage der Ein- und Ausgnge
|
|
|
|
noinp=0 ;
|
|
noout=1;
|
|
|
|
% Zuordnung zu den Ausgangsvariablen
|
|
|
|
data_out=noinp;
|
|
state=noout;
|
|
else
|
|
|
|
% Parameterdefinition
|
|
|
|
para.bl=128;
|
|
comment.bl='Block length (Length of output vector)';
|
|
comment.short.bl='length';
|
|
comment.type.bl='number';
|
|
comment.level.bl=1;
|
|
|
|
para.rand=0 ;
|
|
comment.rand='Random (True) or pseudo-random (False)';
|
|
comment.short.rand='rand/prms';
|
|
comment.type.rand='boolean';
|
|
comment.level.rand=1;
|
|
|
|
para.dimension=2;
|
|
comment.dimension='dimension (i.e. number of parallel bit streams)';
|
|
comment.type.dimension='number';
|
|
comment.short.dimension='dimension';
|
|
comment.level.dimension=1;
|
|
|
|
para.order=2;
|
|
comment.order='order of PRMS (needs to be adapted to memory of DUT)';
|
|
comment.type.order='number';
|
|
comment.short.order='order';
|
|
comment.level.order=1;
|
|
|
|
para.skip=0;
|
|
comment.skip='Skip the first n Bits of sequence';
|
|
comment.type.skip='number';
|
|
comment.short.skip='skip';
|
|
comment.level.skip=1;
|
|
|
|
para.bruijn=1;
|
|
comment.bruijn='extends the PRBS sequence of length 2^n-1 to a deBruijn sequence of 2^n';
|
|
comment.type.bruijn='boolean';
|
|
comment.short.bruijn='deBruijn';
|
|
comment.level.bruijn=1;
|
|
|
|
para.reset_prms=0;
|
|
comment.reset_prms='reset the sequence generator every loop';
|
|
comment.type.reset_prms='boolean';
|
|
comment.short.reset_prms='Reset every loop';
|
|
comment.level.reset_prms=1;
|
|
|
|
para.method=1;
|
|
comment.method='false= old method , true = new method';
|
|
comment.type.method='Fast (c-file)|Slow (Matlab file)';
|
|
comment.short.method='method';
|
|
comment.level.method=1;
|
|
|
|
data_out=para;
|
|
state=comment;
|
|
end;
|
|
else
|
|
|
|
% Initialisierung
|
|
|
|
if loop==0,
|
|
|
|
% check for correct parameters
|
|
|
|
checkskalar(getfield(inputname(2),{1:length(inputname(2))-6}),para,[{'bl'} {'skip'} {'dimension'} {'order'}],...
|
|
[{'length'} {'skip'} {'dimension'} {'order'}]);
|
|
checkinteger(getfield(inputname(2),{1:length(inputname(2))-6}),para,[{'bl'} {'skip'} {'dimension'} {'order'}],...
|
|
[{'length'} {'skip'} {'dimension'} {'order'}]);
|
|
checkpos(getfield(inputname(2),{1:length(inputname(2))-6}),para,[{'bl'} {'skip'} {'dimension'} {'order'}],...
|
|
[{'length'} {'skip'} {'dimension'} {'order'}]);
|
|
|
|
% determine order of periodicity
|
|
% initializing of all state parameters
|
|
state.dimension = para.dimension;
|
|
state.order = para.order;
|
|
state.periodicity = para.dimension*para.order;
|
|
state.bl = para.bl;
|
|
|
|
|
|
state.reset_prms = para.reset_prms;
|
|
|
|
if ~para.rand % PRMS
|
|
%------------------------------------------------------------------
|
|
% prepare Matrix to map PRBS bits to PRMS values
|
|
%------------------------------------------------------------------
|
|
|
|
% create lookup-table for primitive element
|
|
if state.dimension>2,
|
|
% general case
|
|
bchpolynomial=zeros(1,state.dimension+1);
|
|
bchpolynomial([1 srgtaps(state.dimension)+1])=1;
|
|
betatable=fliplr(cyclgen_local(2^state.dimension-1,bchpolynomial).');
|
|
|
|
elseif state.dimension==2
|
|
% special case, by-hand solution
|
|
betatable=[0 1;1 0;1 1];
|
|
|
|
elseif state.dimension==1
|
|
% special case, by-hand solution
|
|
betatable=1;
|
|
|
|
end;
|
|
binvec = 2.^(state.dimension-1:-1:0);
|
|
modulo_mask = 2^state.dimension-1;
|
|
betatable_sort_forward = sum(repmat(binvec,2^state.dimension-1,1).*betatable,2);
|
|
[dummy,betatable_sort_inverse] = sort(betatable_sort_forward);
|
|
betatable_sort_inverse = betatable_sort_inverse-1;
|
|
|
|
% perform polynomial division by x+beta
|
|
|
|
dividend=zeros(state.dimension+1,2);
|
|
dividend([state.dimension-srgtaps(state.dimension)+1 end],1)=1;
|
|
|
|
h=zeros(state.dimension,2);
|
|
|
|
for digit=1:state.dimension,
|
|
|
|
% add new coefficient
|
|
|
|
h(digit,1:2)=dividend(digit,1:2);
|
|
dividend(digit,1:2)=[0 0];
|
|
|
|
% update dividend
|
|
|
|
newdiv_binary=xor(betatable(dividend(digit+1,2)+1,:)*dividend(digit+1,1),...
|
|
betatable(rem(h(digit,2)+1,modulo_mask)+1,:)*h(digit,1));
|
|
dividend(digit+1,1)=sum(newdiv_binary)>0;
|
|
|
|
% compute new dividend, exclude case of last iteration where
|
|
% dividend should end up with 0
|
|
|
|
if (digit~=state.dimension) && dividend(digit+1,1),
|
|
dividend(digit+1,2)=dividend(digit+1,1)*betatable_sort_inverse(sum(newdiv_binary.*binvec));
|
|
else
|
|
dividend(digit+1,2)=0;
|
|
end;
|
|
end;
|
|
|
|
% initialize the prms
|
|
|
|
|
|
% init parameters for deBruijn sequence
|
|
state.bruijn = para.bruijn;
|
|
state.bruijn_counter = -1;
|
|
|
|
if para.method == 1, %new way
|
|
% Initialize the PRBS registers
|
|
tmp_srgtaps = srgtaps(state.periodicity);
|
|
state.srgtaps = zeros(4,1,'int64');
|
|
|
|
mat_table = betatable(h(:,2)+1,:);
|
|
state.mat_table = int64(mat_table * 2.^(0:state.dimension-1)');
|
|
|
|
for n=1:length(tmp_srgtaps)
|
|
state.srgtaps(n)=int64(2^(tmp_srgtaps(n)-1));
|
|
end
|
|
|
|
tmp_reg = int64(2^49-1);
|
|
|
|
state.reg = zeros(state.dimension,1,'int64');
|
|
tmp_reg = prms_c(int32(1),tmp_reg,state.srgtaps);
|
|
state.reg(1)= tmp_reg;
|
|
offset = (2^state.periodicity-1)/modulo_mask;
|
|
|
|
for n=2:state.dimension
|
|
tmp_reg = prms_c(int32(offset),tmp_reg,state.srgtaps);
|
|
|
|
state.reg(n)= tmp_reg;
|
|
end
|
|
|
|
if para.skip>0
|
|
[prbs_register, bruijn, bruijn_counter,data_out ]= prms_c(int32(para.skip),...
|
|
state.reg,...
|
|
state.srgtaps,...
|
|
int32(state.order),...
|
|
state.mat_table,...
|
|
int32(state.bruijn),...
|
|
int64(state.bruijn_counter));
|
|
state.reg = prbs_register;
|
|
state.bruijn = bruijn;
|
|
state.bruijn_counter = bruijn_counter;
|
|
end
|
|
|
|
else
|
|
% Initialize the PRBS registers
|
|
state.reg = ones(1,state.periodicity);
|
|
state.srgtaps = srgtaps(state.periodicity);
|
|
|
|
state.mat_table = betatable(h(:,2)+1,:);
|
|
|
|
% determine indices into past PRBS
|
|
|
|
state.PRBS_inx=1+(0:state.dimension-1)*(2^state.periodicity-1)/modulo_mask;
|
|
|
|
% fill PRBS_memory by creating the first part of the PRBS
|
|
[state.reg,state.PRBS_memory]=prms_prbs_init_mex(state.periodicity,state.srgtaps,state.PRBS_inx(end));
|
|
% init for deBruijn sequence
|
|
|
|
% skip first bits
|
|
skipped=0;
|
|
PRBS_memory_pointer=0;
|
|
while skipped<para.skip,
|
|
|
|
% consider deBruijn symbol
|
|
if state.bruijn==2 && skipped>1,
|
|
skipped = skipped+1;
|
|
state.bruijn = 1;
|
|
continue;
|
|
end;
|
|
|
|
% compute current PRMS-symbol
|
|
|
|
PRBS_inx=mod(state.PRBS_inx+PRBS_memory_pointer-1,state.PRBS_inx(end))+1;
|
|
symbol_temp=rem(sum(repmat(double(state.PRBS_memory(PRBS_inx).'),1,state.dimension).*...
|
|
state.mat_table,1),2).';
|
|
|
|
% compute new PRBS_memory
|
|
|
|
state.reg=[rem(sum(state.reg(state.srgtaps)),2) state.reg(1:end-1)];
|
|
state.PRBS_memory(PRBS_memory_pointer+1)=state.reg(end);
|
|
|
|
PRBS_memory_pointer=mod(PRBS_memory_pointer+1,state.PRBS_inx(end));
|
|
skipped=skipped+1;
|
|
|
|
% consider deBruijn option
|
|
|
|
if state.bruijn==1,
|
|
if state.bruijn_counter<0,
|
|
% counter not yet locked
|
|
if any([~sum(symbol_temp) state.order==1]),
|
|
% zero symbol detected
|
|
state.bruijn_counter=state.bruijn_counter-1;
|
|
if any([state.bruijn_counter== -state.order state.order==1]),
|
|
% lock counter
|
|
state.bruijn_counter=2^state.periodicity-1;
|
|
state.bruijn=2;
|
|
end;
|
|
else
|
|
% no zero, so reset counter
|
|
state.bruijn_counter=-1;
|
|
end;
|
|
else
|
|
% counter already locked
|
|
state.bruijn_counter=state.bruijn_counter-1;
|
|
if state.bruijn_counter==0,
|
|
% reset counter
|
|
state.bruijn_counter = 2^state.periodicity-1;
|
|
state.bruijn=2;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end
|
|
|
|
data_out=zeros(state.dimension,state.bl);
|
|
|
|
else
|
|
|
|
% Execution Stage
|
|
|
|
% update status window
|
|
|
|
% status(getfield(inputname(2),{1:length(inputname(2))-6}));
|
|
|
|
bl = state.bl;
|
|
|
|
if ~para.rand % PRMS
|
|
|
|
if para.method == 1 % fast implementation
|
|
|
|
[prbs_register, bruijn, bruijn_counter,data_out ]= prms_c(int32(state.bl),...
|
|
state.reg,...
|
|
state.srgtaps,...
|
|
int32(state.order),...
|
|
state.mat_table,...
|
|
int32(state.bruijn),...
|
|
int64(state.bruijn_counter));
|
|
if ~state.reset_prms
|
|
state.reg = prbs_register;
|
|
state.bruijn = bruijn;
|
|
state.bruijn_counter = bruijn_counter;
|
|
end
|
|
|
|
data_out = double(data_out);
|
|
|
|
else %old way slow implementation
|
|
|
|
if ((loop==1) || ~state.reset_prms)
|
|
% Initialisierung des Ausgangsvektors
|
|
data_out = zeros(state.dimension,bl);
|
|
|
|
% Successives Berechnen der Ausgangsfolge
|
|
counter=0;
|
|
PRBS_memory_pointer=0;
|
|
|
|
while counter<bl,
|
|
|
|
% check for zero symbol to be inserted for de Bruijn
|
|
% sequence
|
|
|
|
if state.bruijn==2,
|
|
counter = counter+1;
|
|
state.bruijn = 1;
|
|
continue;
|
|
end;
|
|
|
|
% compute current PRMS-symbol
|
|
|
|
PRBS_inx=mod(state.PRBS_inx+PRBS_memory_pointer-1,state.PRBS_inx(end))+1;
|
|
|
|
data_out(:,counter+1)=rem(sum(repmat(double(state.PRBS_memory(PRBS_inx).'),1,state.dimension).*...
|
|
state.mat_table,1),2).';
|
|
|
|
% compute new PRBS_memory
|
|
|
|
state.reg=[rem(sum(state.reg(state.srgtaps)),2) state.reg(1:end-1)];
|
|
state.PRBS_memory(PRBS_memory_pointer+1)=state.reg(end);
|
|
|
|
counter=counter+1;
|
|
PRBS_memory_pointer=mod(PRBS_memory_pointer+1,state.PRBS_inx(end));
|
|
|
|
% consider deBruijn option
|
|
|
|
if state.bruijn==1,
|
|
if state.bruijn_counter<0,
|
|
% counter not yet locked
|
|
if any([~sum(data_out(:,counter)) state.order==1]),
|
|
% zero symbol detected
|
|
state.bruijn_counter=state.bruijn_counter-1;
|
|
if any([state.bruijn_counter== -state.order state.order==1]),
|
|
% lock counter
|
|
state.bruijn_counter=2^state.periodicity-1;
|
|
state.bruijn=2;
|
|
end;
|
|
else
|
|
% no zero, so reset counter
|
|
state.bruijn_counter=-1;
|
|
end;
|
|
else
|
|
|
|
% counter already locked
|
|
state.bruijn_counter=state.bruijn_counter-1;
|
|
if state.bruijn_counter==0,
|
|
% reset counter
|
|
state.bruijn_counter = 2^state.periodicity-1;
|
|
state.bruijn=2;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
% resort PRBS_memory for next block
|
|
|
|
state.PRBS_memory=[state.PRBS_memory(PRBS_memory_pointer+1:end) state.PRBS_memory(1:PRBS_memory_pointer)];
|
|
|
|
if state.reset_prms
|
|
state.data_mem = data_out;
|
|
end
|
|
else
|
|
data_out=state.data_mem;
|
|
|
|
end
|
|
end
|
|
|
|
else
|
|
|
|
data_out = round(rand(para.dimension,bl)) ;
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% A D D I T I O N A L F U N C T I O N S %
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% generate feedback taps for shift register %
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
function taps=srgtaps(inx)
|
|
|
|
data={[1] ...
|
|
[2 1] ...
|
|
[3 1] ...
|
|
[4 1] ...
|
|
[5 2] ...
|
|
[6 1] ...
|
|
[7 1] ...
|
|
[8 7 2 1] ...
|
|
[9 4] ...
|
|
[10 3] ...
|
|
[11 2] ...
|
|
[12 10 2 1] ...
|
|
[13 8 5 3] ...
|
|
[14 12 11 1] ...
|
|
[15 1] ...
|
|
[16 15 12 10] ...
|
|
[17 3] ...
|
|
[18 7] ...
|
|
[19 10 9 3] ...
|
|
[20 3] ...
|
|
[21 2] ...
|
|
[22 1] ...
|
|
[23 5] ...
|
|
[24 11 5 2] ...
|
|
[25 3] ...
|
|
[26 23 15 13] ...
|
|
[27 23 22 17] ...
|
|
[28 3] ...
|
|
[29 2] ...
|
|
[30 27 10 9] ...
|
|
[31 3] ...
|
|
[32 16 7 2] ...
|
|
[33 13] ...
|
|
[34 17 12 8] ...
|
|
[35 2] ...
|
|
[36 11] ...
|
|
[37 22 14 2] ...
|
|
[38 27 6 5] ...
|
|
[39 4] ...
|
|
[40 29 27 23] ...
|
|
[41 3] ...
|
|
[42 34 31 30] ...
|
|
[43 27 22 5] ...
|
|
[44 39 35 18] ...
|
|
[45 39 28 4] ...
|
|
[46 40 31 18] ...
|
|
[47 5] ...
|
|
[48 19 9 1]};
|
|
|
|
taps=data{inx};
|
|
end
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% adapted and faster version of generator for cyclic code %
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
function code=cyclgen_local(columns,polynomial)
|
|
rows=log2(columns+1);
|
|
code=zeros(rows,columns);
|
|
code(1,1)=1;
|
|
|
|
% create columns
|
|
|
|
for s=2:columns,
|
|
code(:,s)=[0;code(1:end-1,s-1)];
|
|
|
|
% check for overflow
|
|
|
|
if code(end,s-1),
|
|
code(:,s)=rem(code(:,s)+polynomial(1:end-1).',2);
|
|
end;
|
|
end;
|
|
|
|
end
|