HDL coder implementation of dsp.MovingAverage (moving/block average)

We're having some trouble with a very simple moving average type code that compiles fine into VHDL, but either crashes the FPGA simulator or uses an insane number of resources. I tried to recode it using dsp.MovingAverage, but it won't compile (System object 'dsp.MovingAverage' is not supported for HDL code generation.) Is there an equivalent dsphdl module or some other ready to use block?
I really need a block average, not moving average (i.e. take a streaming set of numbers and average them in blocks).
Thanks.

 採用された回答

Kiran Kintali
Kiran Kintali 2022 年 12 月 9 日
編集済み: Kiran Kintali 2022 年 12 月 9 日

0 投票

function [y, validOut] = moving_average(x, validIn) %#codegen
% Declare persistent array and persistent window size
persistent array window_size window_size_inverse;
% During the first call of the function, variables are initialized.
if isempty(array)
window_size = fi(25,0,8,0);
window_size_inverse = fi(coder.const(1/25),0,16,19);
array = fi(zeros(1, 25),0,8,4); % size of the window in this example is 25
end
% The following loop maintains the values needed by moving window.
% This for loop also sums up the values of the array.
sum = fi(0,0,32,15);
if(validIn)
for i = 1:24
% window size can be configured via non-tunable input parameter
% window_size-fi(1,0,8,4) window size -1
sum = fi(sum + array(i+1),0,32,15);
array(i) = array(i+1);
end
% The last position is updated based on the most recent input.
array(window_size) = x;
sum = fi(sum + array(window_size),0,32,15);
end
y = fi(sum * window_size_inverse,0,8,4); % Divided by window size
validOut = validIn;
end
You should be able to implement a basic MATLAB function implementation. This can work stand alone in MATLAB to HDL workflow or MATLAB Function Block.
Attaching out of the box resource consumption for this code. You could further pipeline and optimize the design.

4 件のコメント

Anze Slosar
Anze Slosar 2022 年 12 月 16 日
Thanks.
I can't help but notice that in some sense this example illustrates perfectly, just how out of touch matlab is with modern coding practices. The compile-time window length constant (25) it specified manually in at least three different places. There is not even a simple "#define" style statement.
Moreover, shifting the entire array and adding new element at the end seems rather inefficient. Normally one would have a pointer to the oldest element in the array that would wrap around as new data are added. For computer code that would be way more efficient, although I am unsure about compilation into VHDL. But it is precisely these wrapping element pointers that seem to give us constant headache...
Kiran Kintali
Kiran Kintali 2022 年 12 月 16 日
MATLAB does not have such limitations. You can make window length as input argument and pass in the necessary constant values.
As you have rightly guessed if you do not declare the input arguments properly you will end up with extra ports in HDL and unnecessary hardware.
You can use https://www.mathworks.com/help/coder/ref/coder.const.html when using the codegen command. I realize there is no ready to use example doc on this. I will create an documentation request for the VHDL coding design pattern.
For defining these in the project GUI you need to right click on the input argument for the window length and mark it as a constant (and not an input variable).
Let us know if this is not clear.
There are forms of indexing and shifting supported in HDL Coder as long as you do not grow array sizes on the fly in doing so.
zs-ea11r
zs-ea11r 2023 年 5 月 18 日
編集済み: zs-ea11r 2023 年 5 月 18 日
Trying to implement your code (with slight modifications) and I keep getting errors when running Generate HDL Code.
The error I get is as follows: "Found division expression with unsupported Rounding Method for HDL code generation at Function 'divide'.... "
The only changes I made to your code listed above are the window size is an input (SIZE) to the function and the variable is then passed to the persistent call. The issue is the window_inverse persistent call creates an error when I perform fi casting to 1/SIZE.
I cannot use code.const since it cannot make an expression a constant.
When looking up the error above, I found solutions that suggest changing the properties of the MATLAB Functions to fimath("RoundingMethod','Floor'....
I entered the following into the Specify Other Field Entry box in properties:
fimath('RoundingMethod','Floor','OverflowAction','Saturate','ProductMode','FullPrecision','SumMode',FullPrecision').
I get this error: "Conversion to double from embedded.fimath is not possible."
Not sure what is a double, since I am initializing each input as fixdt.
Please help with a work around.
Kiran Kintali
Kiran Kintali 2023 年 5 月 18 日
Can you share your design, testbench and project files?

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

製品

リリース

R2022a

質問済み:

2022 年 12 月 8 日

編集済み:

2023 年 5 月 18 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by