- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have just readed a piece of VHDL code. It is used to average the signal value from AD(14 bit).
The code i write below here: process(CLK80) begin if(CLK80'event and CLK80='1') then if(samplingTriggerReg='1') then -- synchronization with the sampling trigger avCStateReg <= "00000"; else case avCStateReg is when "00000"=> if(sigCLatchReg='1') then avCStateReg<="00001"; end if; when "00001"=> if(sigCLatchReg='1') then avCStateReg<="00011"; end if; when "00011"=> if(sigCLatchReg='1') then avCStateReg<="00111"; end if; when "00111"=> if(sigCLatchReg='1') then avCStateReg<="01111"; end if; when "01111"=> if(sigCLatchReg='1') then avCStateReg<="11111"; end if; when "11111"=> if(sigCLatchReg='1') then avCStateReg<="11110"; end if; when "11110"=> if(sigCLatchReg='1') then avCStateReg<="11100"; end if; when "11100"=> if(sigCLatchReg='1') then avCStateReg<="11000"; end if; when "11000"=> if(sigCLatchReg='1') then avCStateReg<="10000"; end if; when "10000"=> if(sigCLatchReg='1') then avCStateReg<="00000"; end if; when others => avCStateReg<="00000"; end case; end if; end if; end process; dfTrigCReg <= '1' when avCStateReg="10000" else '0'; process(CLK80) begin if(CLK80'event and CLK80='1') then if(samplingTriggerReg='1') then -- synchronization with the sampling trigger avSStateReg <= "00000"; else case avSStateReg is --gray counter? when "00000"=> if(sigSLatchReg='1') then avSStateReg<="00001"; end if; when "00001"=> if(sigSLatchReg='1') then avSStateReg<="00011"; end if; when "00011"=> if(sigSLatchReg='1') then avSStateReg<="00111"; end if; when "00111"=> if(sigSLatchReg='1') then avSStateReg<="01111"; end if; when "01111"=> if(sigSLatchReg='1') then avSStateReg<="11111"; end if; when "11111"=> if(sigSLatchReg='1') then avSStateReg<="11110"; end if; when "11110"=> if(sigSLatchReg='1') then avSStateReg<="11100"; end if; when "11100"=> if(sigSLatchReg='1') then avSStateReg<="11000"; end if; when "11000"=> if(sigSLatchReg='1') then avSStateReg<="10000"; end if; when "10000"=> if(sigSLatchReg='1') then avSStateReg<="00000"; end if; when others => avSStateReg<="00000"; end case; end if; end if; end process; dfTrigSReg <= '1' when avSStateReg="10000" else '0'; process(CLK80) begin if (CLK80'event and CLK80='1') then if (sigCLatchReg='1') then avSigCReg(0) <= sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg; for I in 1 to 9 loop avSigCReg(I) <= avSigCReg(I-1) + (sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg); end loop; end if; end if; end process; process(CLK80) begin if (CLK80'event and CLK80='1') then if (sigSLatchReg='1') then avSigSReg(0) <= sigSReg(13) & sigSReg(13) & sigSReg(13) & sigSReg(13) & sigSReg; for I in 1 to 9 loop avSigSReg(I) <= avSigSReg(I-1) + (sigSReg(13) & sigSReg(13) & sigSReg(13) & sigSReg(13) & sigSReg); end loop; end if; end if; end process; i dont konw why the designer do this: avSigCReg(0) <= sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg; avSigCReg is is array (0 to 9) of signed(17 downto 0), I think this code is calculate the average value of 10 signal . But I dont understand it ? Thanks for giving your idea.Link Copied
13 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Use simulator, waveform says more than unknown code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yup, write a testbench and get simulating.
But you dont really specify exactly what you want? what exactly are you averaging? Notes on your code: - You dont show the whole code, so we cannot see signal declarations - WHy have you got a for loop summing together things? - This code looks messy A moving window average is easily acheived with a shift register and an adder tree, with a divider on the end. If the window is 2^n wide, all you need to divide is drop the n LSBs (with a possible rounding stage)- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- i dont konw why the designer do this: avSigCReg(0) <= sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg; avSigCReg is is array (0 to 9) of signed(17 downto 0), I think this code is calculate the average value of 10 signal . --- Quote End --- The common arithmetic average of N samples is calculated by summing the samples and then dividing by N. Since division by a number which is not power of 2 is resource consuming, you can avoid it by discarding the N factor which is actually not relevant since it's simply a constant multiplier. The multiple & sigCReg(13) simply serves for the purpose of sign extending the 14 bit ADC sample to the 18 bit wide sum.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes,Thanks for your reply .I have made simulation for this code.It looks like just summing the ten numbers last received from the AD.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Yup, write a testbench and get simulating. But you dont really specify exactly what you want? what exactly are you averaging? Notes on your code: - You dont show the whole code, so we cannot see signal declarations - WHy have you got a for loop summing together things? - This code looks messy A moving window average is easily acheived with a shift register and an adder tree, with a divider on the end. If the window is 2^n wide, all you need to divide is drop the n LSBs (with a possible rounding stage) --- Quote End --- I didn't show the whole code because it's very long.This code is writen by others and I just want to know what exactly it work and use it in my work. I have writen a copy for simulation. I will put it below. library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_unsigned.all; entity Averager is port(CLK80: in std_logic; sigCReg: in signed(13 downto 0); SigSReg: in signed(13 downto 0); samplingTriggerReg: in std_logic; sigCLatchReg: in std_logic; sigSLatchReg: in std_logic; dfTrigSReg :out std_logic ; dftrigCReg: out std_logic; WS0: out signed(17 downto 0); WS1: out signed(17 downto 0); WS2: out signed(17 downto 0); WS3: out signed(17 downto 0); WS4: out signed(17 downto 0); WS5: out signed(17 downto 0); WS6: out signed(17 downto 0); WS7: out signed(17 downto 0); WS8: out signed(17 downto 0); WS9: out signed(17 downto 0) ); end Averager; architecture Behavioral of Averager is signal avCStateReg, avSStateReg: std_logic_vector(4 downto 0):="00000"; type avSig is array (0 to 9) of signed(17 downto 0); signal avSigSReg,avSigCReg: avSig; begin process(CLK80) begin if(CLK80'event and CLK80='1') then if(samplingTriggerReg='1') then -- synchronization with the sampling trigger avCStateReg <= "00000"; else case avCStateReg is when "00000"=> if(sigCLatchReg='1') then avCStateReg<="00001"; end if; when "00001"=> if(sigCLatchReg='1') then avCStateReg<="00011"; end if; when "00011"=> if(sigCLatchReg='1') then avCStateReg<="00111"; end if; when "00111"=> if(sigCLatchReg='1') then avCStateReg<="01111"; end if; when "01111"=> if(sigCLatchReg='1') then avCStateReg<="11111"; end if; when "11111"=> if(sigCLatchReg='1') then avCStateReg<="11110"; end if; when "11110"=> if(sigCLatchReg='1') then avCStateReg<="11100"; end if; when "11100"=> if(sigCLatchReg='1') then avCStateReg<="11000"; end if; when "11000"=> if(sigCLatchReg='1') then avCStateReg<="10000"; end if; when "10000"=> if(sigCLatchReg='1') then avCStateReg<="00000"; end if; when others => avCStateReg<="00000"; end case; end if; end if; end process; dfTrigCReg <= '1' when avCStateReg="10000" else '0'; process(CLK80) begin if(CLK80'event and CLK80='1') then if(samplingTriggerReg='1') then -- synchronization with the sampling trigger avSStateReg <= "00000"; else case avSStateReg is --gray counter? when "00000"=> if(sigSLatchReg='1') then avSStateReg<="00001"; end if; when "00001"=> if(sigSLatchReg='1') then avSStateReg<="00011"; end if; when "00011"=> if(sigSLatchReg='1') then avSStateReg<="00111"; end if; when "00111"=> if(sigSLatchReg='1') then avSStateReg<="01111"; end if; when "01111"=> if(sigSLatchReg='1') then avSStateReg<="11111"; end if; when "11111"=> if(sigSLatchReg='1') then avSStateReg<="11110"; end if; when "11110"=> if(sigSLatchReg='1') then avSStateReg<="11100"; end if; when "11100"=> if(sigSLatchReg='1') then avSStateReg<="11000"; end if; when "11000"=> if(sigSLatchReg='1') then avSStateReg<="10000"; end if; when "10000"=> if(sigSLatchReg='1') then avSStateReg<="00000"; end if; when others => avSStateReg<="00000"; end case; end if; end if; end process; dfTrigSReg <= '1' when avSStateReg="10000" else '0'; process(CLK80) begin if (CLK80'event and CLK80='1') then if (sigCLatchReg='1') then avSigCReg(0)<= sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg; for I in 1 to 9 loop avSigCReg(I) <= avSigCReg(I-1)+ (sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg(13) & sigCReg); end loop; end if; end if; end process; process(CLK80) begin if (CLK80'event and CLK80='1') then if (sigSLatchReg='1') then avSigSReg(0) <= sigSReg(13) & sigSReg(13) & sigSReg(13) & sigSReg(13) & sigSReg; for I in 1 to 9 loop avSigSReg(I) <= avSigSReg(I-1) + (sigSReg(13) & sigSReg(13) & sigSReg(13) & sigSReg(13) & sigSReg); end loop; end if; end if; Ws0<=avSigcReg(0);WS1<=avSigcReg(1);WS2<=avSigcReg(2);WS3<=avSigcReg(3);WS4<=avSigcReg(4); Ws5<=avSigcReg(5);WS6<=avSigcReg(6);WS7<=avSigcReg(7);WS8<=avSigcReg(8);WS9<=avSigcReg(9); end process; end Behavioral; I have simulate it, it looks like adding the ten value last received from the AD. The divider is not occured in this part of code(or just discarding). I wanted to know more about a shift register and an adder tree you have mentioned. Thanks for your reply. I'm a new learner so that I don't understand why this code is messy.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- The common arithmetic average of N samples is calculated by summing the samples and then dividing by N. Since division by a number which is not power of 2 is resource consuming, you can avoid it by discarding the N factor which is actually not relevant since it's simply a constant multiplier. The multiple & sigCReg(13) simply serves for the purpose of sign extending the 14 bit ADC sample to the 18 bit wide sum. --- Quote End --- Than you for your reply. But whether you mean I can discard the 10(the N in this code),and calculate the turth value when those datas uploaded to the computer.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For averaging 2^n samples all you need is discard n LSBs from result of accumulator (as explained in some of above posts). for non power of 2 samples there are some tricks to avoid division e.g. if number of samples is 1000 then average = sum/1000 = sum/1024 * 1.024
~= sum/1024 *(1+1/64+1/128) hence average = sum(discard 10 LSBs) + sum(discard 16 LSBs) + sum(discard 17 LSBs)- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- For averaging 2^n samples all you need is discard n LSBs from result of accumulator (as explained in some of above posts). for non power of 2 samples there are some tricks to avoid division e.g. if number of samples is 1000 then average = sum/1000 = sum/1024 * 1.024 ~= sum/1024 *(1+1/64+1/128) hence average = sum(discard 10 LSBs) + sum(discard 16 LSBs) + sum(discard 17 LSBs) --- Quote End --- Thanks ,Kaz! It's a wonderful ideal !!!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- For averaging 2^n samples all you need is discard n LSBs from result of accumulator (as explained in some of above posts). for non power of 2 samples there are some tricks to avoid division e.g. if number of samples is 1000 then average = sum/1000 = sum/1024 * 1.024 ~= sum/1024 *(1+1/64+1/128) hence average = sum(discard 10 LSBs) + sum(discard 16 LSBs) + sum(discard 17 LSBs) --- Quote End --- Ok Kaz, but this way you need more system resources, I mean logic gates in fpga or computation time in a programming language. In other words you are still implementing some sort of division algorithm. I would keep on my idea, which is also the one exploited by the sample code at start of this thread: if you don't mind the x1000 (or whatever) factor you can quietly avoid the division. If you later need to compare this 'average x 1000' with something else, it will be easier to multiply this one x1000 than dividing the average result.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Ok Kaz, but this way you need more system resources, I mean logic gates in fpga or computation time in a programming language. In other words you are still implementing some sort of division algorithm. I would keep on my idea, which is also the one exploited by the sample code at start of this thread: if you don't mind the x1000 (or whatever) factor you can quietly avoid the division. If you later need to compare this 'average x 1000' with something else, it will be easier to multiply this one x1000 than dividing the average result. --- Quote End --- Yes I needed two adders (not that bad as a divider). I agree you don't need to divide if you want the sum rather than the average but in many cases we do need the average itself over a given time window.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
hi kaz!
Maybe I can ask you another VHDL code after this one. The data which is summed will be taken into a digital filter. The code is shown below:------------------- FIR FILTER ------------------ process(CLK80) begin if (CLK80'event and CLK80='1') then if (DFTrigCReg='1') then for I in 0 to firLength-1 loop CQRealReg(I) <= avSigCReg(9)(17 downto 4) * DFcoeff(I); end loop; CSRealReg(0) <= CQRealReg(0)(23) & CQRealReg(0)(21 downto 0); for I in 1 to firLength-1 loop CSRealReg(I) <= CSRealReg(I-1) + (CQRealReg(I)(23) & CQRealReg(I)(21 downto 0)); end loop; end if; -- end if; -- CLK end process; I think the DFcoeff is filter coefficient. But why the designer do the process like this" CSRealReg(0) <= CQRealReg(0)(23) & CQRealReg(0)(21 downto 0);"- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That will be sign extension, ensuring that the slices arrays stay +ve or -ve correctly.
It reads better if you use the resize() function. Looking at that code, it wont build the adder tree as I expect it, it just creates FirLength-1 output values (you usually end up with a single output).- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- That will be sign extension, ensuring that the slices arrays stay +ve or -ve correctly. It reads better if you use the resize() function. Looking at that code, it wont build the adder tree as I expect it, it just creates FirLength-1 output values (you usually end up with a single output). --- Quote End --- Yes, but I dont know the resize() function. And maybe the CSRealReg(FirLength-1) is the output which I want . If you're interesting the complete vhdl code you can see it in the attchment, Tricky. Thanks for your help.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page