- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello everybody,
I have a problem... I try to relized a simple iir filter (to simply this i choose the first order) with one tap, only one mobile average coeff (b0=1) and only one auto-regressive coeff (a1=2), so implement this using std_logic_vector signal to realize the delay for every clock impulse. I implement two lpm moltiplicator to realized input moltiplication (b*input) and output moltiplication (a*output).. so these performe moltiplication always (because i don't use the clock with pipeline). So when i sum the mobile part (pnum) with autoregressive part (pden) there is a delay due to signal in the adder operation because the autoregressive part depend of the output y.. See program iir_1 with image 01:confused: I think to resolve this problem introduce a delay in the mobile part but i can't resolve this problem with this.. because then i don't sum the auto regressive part in the first adder so the output don't change and go to 0... See program iir_1_delay with image 02:( Someone can help me, please? thank you! The program is structured with array because i had tried to implement an 3 order iir filter.. so in this case (1°order) i use only the first element..Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't quite get it. I assume your simple test filter is y(i) = x(i) + 2*y(i-1)
thus you need one delay stage for output (y) to be added to input (x) [obviously you don't need any multipliers for this example). You should not put any delay on multiplier outputs but just one on adder output to serve as one delay stage as well as assist timing. x => *1 => + => register => *2 => back to +- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- I don't quite get it. I assume your simple test filter is y(i) = x(i) + 2*y(i-1) thus you need one delay stage for output (y) to be added to input (x) [obviously you don't need any multipliers for this example). You should not put any delay on multiplier outputs but just one on adder output to serve as one delay stage as well as assist timing. x => *1 => + => register => *2 => back to + --- Quote End --- Thank you for your response. Ok, the equation of the filter is ok.. I choice to implement an transponse structure, so in the process the instruction (first program iir_1 without delay..) adder(0)<=pnum(0)+pden(0)+adder(1) where these are signal so this register is update at the end of the process.. I use the lpm.mult because the signal is std_logic_vector so i implement with these megafunction the moltiplication 1*x and 2*y. the problem is that.. the signal pden (auto-regressive part) is summed with one cycle of delay.. image 01 (y_out) the correct development of the output is showed in the image iir_1_ok.pdf So.. i try to introduce a delay of the first part (moving average part 1*x) to sum this with the second part correctly.. but i don't do this well..:confused: because the signal become zero after the sum of the first two number. (10-20-0-0-0-0-ecc..). I expect to see (10-20-40-80-160 ecc...) This is only the first tap of a generic iir filter order.. if this structur function correctly i can add other part using array.. do you understand? thank you! :o by Kikko
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That is not a problem. You are supposed to add previous (y) to current (x) so the delay is part of filter structure.
Thus if x stream is 1, 2, 3 then y1 = 1+2*0 = 1 y2 = 2+2*1 = 4 y3 = 3+2*4 = 11 and so on- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- That is not a problem. You are supposed to add previous (y) to current (x) so the delay is part of filter structure. Thus if x stream is 1, 2, 3 then y1 = 1+2*0 = 1 y2 = 2+2*1 = 4 y3 = 3+2*4 = 11 and so on --- Quote End --- I think that you don't understad my problem..! i want realized the output iir_1_ok.pdf.. but the result of my first program iir_1.txt is 01.pdf.. where there are 0 between one result and other (10-0-20-0-40-0-80..) so in this case the "filter" (equation) is: y(k)=1*x(k)+2*y(k-2) and input is a impulse x(0)=10 x(0)=0 x(1)=0 ecc.. :cry: but i want realize y(k)=1*x(k)+2*y(k-1) :o so.. the problem is in the second iteration.. where the result of autoregressive part (pnum(0) that is 20) is summed to adder(0) but the result is showed in the next iteration (next clock) because adder is a signal and it is in the process, so in this iteration adder(0) is equal to 0...and the update value is showed next.. and this result (0) is read every cycle so it's reply at every 2 clock.. I try to delay the moving average part to sum these two part together correctly.. (program iir_1_delay.txt) but i don't do these operation correctly so.. the result is showed in 02.pdf do you understand my problem? How can i work to resolve this problem ( the adder is a signal to develop the delay between each tap..)??? thank you!:(
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok so you get wrong zero after every output.
Your coding is too much for such a simple task and I don't see any feedback to adder. In fact adder(1) seems undriven. May be the best way is to see following code to implement what you do (basically an accumulator):
process
begin
wait until clk = '1';
y_d <= adder_output & '0'; -- delay stage and multiply by 2 using shift
end process;
...outside clocked process, y_d is fedback as input to adder
adder_output = xin + y_d;
you will need to look after type and size issues
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Ok so you get wrong zero after every output. Your coding is too much for such a simple task and I don't see any feedback to adder. In fact adder(1) seems undriven. May be the best way is to see following code to implement what you do (basically an accumulator):
process
begin
wait until clk = '1';
y_d <= adder_output & '0'; -- delay stage and multiply by 2 using shift
end process;
...outside clocked process, y_d is fedback as input to adder
adder_output = xin + y_d;
you will need to look after type and size issues --- Quote End --- thank you for your reply. yes, i have stuctured my code for a filter with 3 coeff b (moving average) and 2 coeff a (autoreg)... so the register adder(1) should contain the result of the previous stage.. see figure transposed structure.. But the goal is realized a filter with more one stage so.. i use array! but in this case only the first element it is only a simple example..y(k)=x(k)+2y(k-1) but with real coefficient i can't use the structure y_d <= adder_output & '0'; because the coeff.. it's for example 281 so i must use lpm.moltiplicator with input std_logic_vector and i provide coefficient serialy with a structure show in my program iir_1.txt One advantage of transpose structure is that we don't use to sum the products at the end , but the sums is realized step by step using the structure recorsive adder(i)=num(i)+den(i)+adder(i+1)... So i can rewrite my core code here... for the first order filter ... sop: PROCESS(CLK) --- PROCESS for the sum of product BEGIN IF clk'event and (clk='1') then adder<=pnum+pden; -- sum the result for every stage.. valide only for first filter type y<=adder; end PROCESS sop; -- ISTANTIATE L PIPELINED MULTIPLIER NUM MulGen: FOR I IN 0 TO L-1 GENERATE Mulsnum: lpm_mult --Moltiplication pnum(i)=c(i)*x ... PORT MAP ( dataa=>x, datab=>c(I), result =>pnum(I)); -- with first order i don't use cycle but only pnum(0) END GENERATE; -- ISTANTIATE L PIPELINED MULTIPLIER DENUM MulGen2: FOR K IN 0 TO L-2 GENERATE --Moltiplication pden(i)=a(i)*y(i)) Mulsden: lpm_mult .... PORT MAP ( dataa=>a(K), datab=>y, result =>pden(K)); -- with first order i don't use cycle but only pden(0) END GENERATE; y_out<=adder; END architecture; Thank you for your interest in my problem but if the problem is only resolve y(k)= x(k)+2y(k-1) i have just resolved it using direct form.. that is more simple than transposed but haven't some advantage.:( Have you other ideas? in this moment i think that delay the first part is the only solution.. but i haven't realized it correctly..:evil: thank you! by Enrico:o
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is how I will do transposed IIR of 2nd order (using forward coeffs b0,b1,b2 & recursive coeffs a1,a2)
process
begin
wait until clk = '1';
y1 <= xin*b2 + y*a2;
y2 <= xin*b1 + y*a1 + y1;
end process;
y <= xin*b0 + y2; -- feedback
if it passes speed...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I try your example and the result it's wrong...
using language vhdl y can't be an output .. because the compiler send me the error that an output can't be read.. so i use always signal and i use output only for the debug...: so i write this to test your example signal y1,y2,y3 : integer :=0; shared variable a1,a2,b0,b1,b2; process wait until clk='1' a1:=2; a2:=1; b0:=1; b1:=2; b2:=3; y1<=x_in*b2+y*a2; y1debug<=y1; y2<=x_in*b1+y*a1+y1; y2debug<=y2; end process; y<=b0*x_in+y2; yout<=y; end architecture; using the coefficient a1=2 a2=1 b0=1 b1=2 b2=3 and x(0)=1 x(1)=0 x(2)=0 y must be: y(0)=1 y(1)=4 y(2)=12 y(3)=28 y(4)=68 ecc... but using your code (readapted) the output is show in figure example.pdf simulate with qsim. and the number are different.. there is something that not function well...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
my code is just to demonstrate the algorithm. You are supposed to look after bitwidth, data type, port direction etc.
How do get your figures. If I type in matlab that b0 = 1,b1=2,b2 =3,a1 = 2, a2 = 1then num = [1 2 3]; den = [1 2 1]; x =[1 0 0 0 0]; y= filter(num,den,x) ; what do you get. if your orientation of feedback terms is opposite then den = [1 -2 -1] y = filter(num,den,x); what do you get. You need also to look after signed operations if delaing with std_logic.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should get as you say 1,4,12,28,64,... try use signed type instead of full width integer.
The code is direct translation of your diagram so it must work. You have some strange initial values on y1,y2...what are those?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- You should get as you say 1,4,12,28,64,... try use signed type instead of full width integer. The code is direct translation of your diagram so it must work. You have some strange initial values on y1,y2...what are those? --- Quote End --- The strange value assigned at my debug variables is because i don't assign a standard value when i write out port.. so it assign the first value that is..-(2^32)-1, when i impose a value y1 or y2 they become these numer. At the begin i'm expected 0.. but i note that when i use for the first time alter compiler.. So i haven't use the signed type before.. what type i must use??? can you write me something example.. and you can tell me why the scale of subtype bits11 is integer range -1023 to 1024; -- 11 bit when i define variable like... a: bits11; if i don't impose the default value they are initializated to least value and not to zero. so.. thank you!:rolleyes:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
assume input x is 16 bits signed
y_out is 16 bits signed coeffs 16 bits signed then you can either use integer computation or signed. to simplify example, let us assume we can truncate y_int below without check, I also assume a coeff of say 2 means 2 in terms of gain. This code is untested but should give you an idea.
signal y1 : signed(32 downto 0) := (others => '0');
signal y2 : signed(33 downto 0) := (others => '0');
signal y_int : signed(34 downto 0) := (others => '0');
constant b0 : signed(15 downto 0) := x"0001";
constant b1 : signed(15 downto 0) := x"0002";
constant b2 : signed(15 downto 0) := x"0003";
constant a1 : signed(15 downto 0) := x"0002";
constant a2 : signed(15 downto 0) := x"0001";
begin
process
begin
wait until clk = '1';
y1 <= x*b2 + y_int(15 downto 0)*a2; -- 16*16 + 16*16cbits, needs 33 bits
y2 <= x*b1 + y_int(15 downto 0)*a1 + y1; -- 16*16 + 16*16 + 33bits, needs 34 bits
end process;
y_int <= x*b0 + y2; -- 16 * 16 + 34 bits, requires 35 bits
y <= y_int(15 downto 0);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- assume input x is 16 bits signed y_out is 16 bits signed coeffs 16 bits signed then you can either use integer computation or signed. to simplify example, let us assume we can truncate y_int below without check, I also assume a coeff of say 2 means 2 in terms of gain. This code is untested but should give you an idea.
signal y1 : signed(32 downto 0) := (others => '0');
signal y2 : signed(33 downto 0) := (others => '0');
signal y_int : signed(34 downto 0) := (others => '0');
constant b0 : signed(15 downto 0) := x"0001";
constant b1 : signed(15 downto 0) := x"0002";
constant b2 : signed(15 downto 0) := x"0003";
constant a1 : signed(15 downto 0) := x"0002";
constant a2 : signed(15 downto 0) := x"0001";
begin
process
begin
wait until clk = '1';
y1 <= x*b2 + y_int(15 downto 0)*a2; -- 16*16 + 16*16cbits, needs 33 bits
y2 <= x*b1 + y_int(15 downto 0)*a1 + y1; -- 16*16 + 16*16 + 33bits, needs 34 bits
end process;
y_int <= x*b0 + y2; -- 16 * 16 + 34 bits, requires 35 bits
y <= y_int(15 downto 0);
--- Quote End --- Ok. thank you for your response.. in your code there isn't extension of sign.. so when compile there are some errors.. due to different dimension of register... so i put they of the same length ignoring for this time the correct length of the registers.. do you know some function that extent the sign automatically? I simulate this example of qsim and this is correct.. thank you!:o i show this on the file sim_solution.pdf with coeff b0=1 b1=2 b3=3 a1=2 a2=1
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
example resize:
for above y1 <= x*b2 + y_int(15 downto 0)*a2; try this y1 <= resize(x,33)*resize(b2,33) + resize(y_int(15 downto 0),33)*resize(a2,33);- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I already recommended you use numeric_std for the signed/unsigned types. Using std_logic_vector is just messy, and there is no need to use the LPM library. why are you insisting on this?
Secondly - your attempt to use shared variables shows lack of understanding of VHDL, and given your postings here and elsewhere, I suspect your knowledge of digital logic could also use some revision. I also recommend you try using modelsim as well.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- I already recommended you use numeric_std for the signed/unsigned types. Using std_logic_vector is just messy, and there is no need to use the LPM library. why are you insisting on this? Secondly - your attempt to use shared variables shows lack of understanding of VHDL, and given your postings here and elsewhere, I suspect your knowledge of digital logic could also use some revision. I also recommend you try using modelsim as well. --- Quote End --- I'm sorry.. i'm only a student of vhdl.. i started use vhdl two mouths ago, so i read only some notes. but i must use vhdl.:( if you help me i can improve my knowledge. thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

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