- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Hello,
I am trying to implement a low pass frequency filter in Verilog. I know that the input is a sine wave that oscilates around 0. The threshold is 500hz. Here is my code: module filter(clk, in, out); input signed [11:0]in; output signed [13:0]out; input clk; reg [17:0]counter; wire [13:0]out; reg q; reg [11:0]true; reg s; initial begin counter=18'b000000000000000000; q=1; true=12'b000000000000; s=1; end always @(posedge clk) begin if(counter[17]==0) counter=counter+1; if(~q==s) begin s=q; counter=18'b00000000000000; end end always @(negedge in[11]) begin true={counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17]}; q=~q; end assign out=(in & true)<<< 2; endmodule The output is just 0 for no matter what frequency of the input.(The input is converted in a 2's complement system) Will be very happy to hear how to fix my program... but if it desperately stupid, would like to see a code for LPFF. Thanks in advance링크가 복사됨
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
You could use signaltap to check what your system is doing.
While I'm not a Verilog specialist, I see that you use one bit of your 'in' vector as a clock, and this isn't a good idea. You could have metastability issues between your two always blocks, and your second block is sensitive to glitches. Your design would be a lot safer if you could include both parts inside the always @(posedge clk) block, and for example detect a falling edge on in[11] by comparing the signal to it's previous value.- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Here is my new code:
module filter(in,out,clk); input signed [11:0] in; output signed [13:0] out; input clk; wire [13:0]out; reg [17:0]counter; reg q; reg [11:0]t; assign out=(~in & t) <<< 2; always @(posedge clk) begin if(counter[17]==0) counter=counter+1; if((q==0) & (in[11]==1)) begin q=in[11]; t={counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17]}; counter=18'b000000000000000000; end if((q==1) & (in[11]==0)) q=in[11]; end endmodule The output is still 0.... what do I do wrong?- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
The new code is working great for lower bites...(if you set the controlling bite of the counter 12 for example) but it seems not to work that great for 15,16,17... the output is just 0. Can someone explain why??? Moreover the output is still zero for frequencies as 1khz even if the counter is set on the 12th bite, but it works perfectly in the range higher than that.
Thanks- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
--- Quote Start --- Here is my new code: module filter(in,out,clk); input signed [11:0] in; output signed [13:0] out; input clk; wire [13:0]out; reg [17:0]counter; reg q; reg [11:0]t; assign out=(~in & t) <<< 2; always @(posedge clk) begin if(counter[17]==0) counter=counter+1; if((q==0) & (in[11]==1)) begin q=in[11]; t={counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17],counter[17]}; counter=18'b000000000000000000; end if((q==1) & (in[11]==0)) q=in[11]; end endmodule The output is still 0.... what do I do wrong? --- Quote End --- in my opinion you should assign the counter to : counter <= counter + 1 , the register counter is a D ff and it is under , in this case you are specified the edge-sensitive behavior of the circuit (posedge clk) so you have to put the none-Blocking (<= )assignments for your registers .
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Does anyone understand what the code is supposed to do? It's apparently not what we know as a low pass filter.
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
It is supposed to do the following:
If the frequency of the input is lower or equal than the threshold frequency the output will look exactly as the input, else the output will be 0.- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
--- Quote Start --- It is supposed to do the following: If the frequency of the input is lower or equal than the threshold frequency the output will look exactly as the input, else the output will be 0. --- Quote End --- and what is the nature of your input(sine waves or any signal). Your filter sounds ideal pass/not pass but yo haven't explained your algorithm. How you going to detect frequency of input?
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Yeah... I think you are right, and I should explain a little bit more about the idea of the code.
The input is a sine wave. The design will be implemented on a Altera Cyclone FPGA, installed on a USRP. The input clock has a frequency of 64Mhz. The input signal is compared to a counter(whose frequency I can change... knowing the frequency of the clock). At every time that input goes from positive value to negative(we use the 2's complement properties here... and exactly the fact that if the signal is negative the first bit is 1 and if positive the first bit is 0) the control wave is restored to 0 and the comparison between the input signal and the control one is done one more time. Hope this helps, Sorry for not doing it from the start.- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
--- Quote Start --- Yeah... I think you are right, and I should explain a little bit more about the idea of the code. The input is a sine wave. The design will be implemented on a Altera Cyclone FPGA, installed on a USRP. The input clock has a frequency of 64Mhz. The input signal is compared to a counter(whose frequency I can change... knowing the frequency of the clock). At every time that input goes from positive value to negative(we use the 2's complement properties here... and exactly the fact that if the signal is negative the first bit is 1 and if positive the first bit is 0) the control wave is restored to 0 and the comparison between the input signal and the control one is done one more time. Hope this helps, Sorry for not doing it from the start. --- Quote End --- OK, so your sine input is running at system clock of 64MHz and for sine threshold of 500Hz you need to count up to 64000 (on 64MHz clock) for half cycle to see if sign bit changes(zero crossing) then pass it if so or more than 64000 clocks else mute it. Naturally you need to count 1/2 cycle and decide and may be you don't need to store that first half i.e. is it one check only to decide or you keep tracking your input in which case you need to store each half before deciding. My simplest algorithm would be: run counter 0 ~ 64000-1, checking sign bit regularly. if sign bit didn't change right to end pass input else mute. Thus you need first to determine the algorithm before writing code. We are also ignoring phase of sine input.
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Thanks kaz... though, can you please explain what is the disadvantage of checking the whole period of the input instead of checking only one half?
Thanks- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
--- Quote Start --- Thanks kaz... though, can you please explain what is the disadvantage of checking the whole period of the input instead of checking only one half? Thanks --- Quote End --- just to save on counting. Either way it works. It is also much easier to check is sign bit changed value relative to previous value. than to check if sign bit changed then changed back.
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Thanks. Do you have any idea why the code is behaving weird when the frequencies are low?
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
I haven't done verilog for years but in vhdl I will do this:
clocked process: --run counter 0 @ 64000-1; sign_bit_d <= sign_bit; output <= input; if sign_bit /= sign_bit_d and count < 64000 then output <= (others => '0'); end if; end process;- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
For low frequencies you also need to reset your counter in some way e.g. at zero crossing.
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Yes I do reset it at zero crossing, but it mutes the output when the frequencies are low and then behaves exactly as expected...
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
Well let me have a go at it in vhdl off my head(not tested) assuming sine phase starts at 0:
let count be binary of suitable width e.g. 20 bits free running i.e. donot stop at 64000-1
process
begin
wait until clk = '1';
count <= count +1;
sign_bit_d <= sign_bit;
if sign_bit /= sign_bit_d then
count <= (others => '0');
mute <= '0';
if count < 64000-1 then
mute <= '1';
end if;
end if;
end process;
output <= input when mute = '0' else (others => '0');
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
see my editing of code. Also it is too simplistic regarding mute as you need to keep it latched until next check so I leave that to you.
- 신규로 표시
- 북마크
- 구독
- 소거
- RSS 피드 구독
- 강조
- 인쇄
- 부적절한 컨텐트 신고
I think my another last edit of code should work with mute as well. A check is done at zero crossing to reset count and update mute.
Good luck.