For a project I am currently working on, I am trying to take some inputs, store them in a register then find the arithmetic mean of the register. All of my inputs are 24-bits long. My registers are 4-inputs long therefore I simply remove the last 3-digits of the least-significant bits while dividing them by 4 in order to calculate the arithmetic mean, then simply add them.
mean is my register(95 downto 0)
(4 x 24 = 96), and mean_medium
is type unsigned
.
When I code the following line
signal mean_medium : unsigned (23 downto 0) := (others => '0');
mean_medium <= unsigned(medium (95 downto 75)) +
unsigned(medium (71 downto 51)) +
unsigned(medium (47 downto 27)) +
unsigned(medium (23 downto 3)) ;
I took the following warning:
Width mismatch. mean_medium has a width of 24 bits but assigned expression is 21-bit wide.
Do you have any suggestions to fix this?
An error already is that you divide by four by shifting 3 bits. You only need to shift 2 bits.
But for correct/precise arithmetic you should not pre-shift the operants of that expression, as you lose precision due to trunctation. First add all the 4 full 24-bit values to one 26-bit output. Then shift-and-round the output. Example
signal mean_medium : unsigned (23 downto 0); -- redundant := (others => '0');
signal mean_temp : unsigned(25 downto 0);
mean_temp <=
resize(unsigned(medium (95 downto 72)), mean_Temp'length) +
resize(unsigned(medium (71 downto 48)), mean_Temp'length) +
resize(unsigned(medium (47 downto 24)), mean_Temp'length) +
resize(unsigned(medium (23 downto 0)), mean_Temp'length) +
2; -- round factor
mean_medium <= shift_right(mean_temp, 2); --divide by 4
p.s. you could also combine this in one line, removing the necessity of mean_temp
.