[I]module CircularBuffer(Audio_in, Clk, Reset,control,t);
input signed [11:0] Audio_in;
input Clk,Reset,control,t;
reg [11:0]Buff_Array[4095:0];
integer k;
always @ (posedge Clk)
begin
if (Reset == 1)
for (k = 0; k <= 4095; k = k+1)
Buff_Array[k] <= 0;
else
begin
Buff_Array[0] <= Audio_in;
for (k = 1; k <= 4095; k = k+1)
Buff_Array[k] <= Buff_Array[k-1];
end
end
endmodule
module echo(Buff_Array,Audio_out,Clk,Buff_Array1);
input [11:0]Buff_Array;
input Clk;
output reg[11:0]Audio_out;
inout [11:0]Buff_Array1;
integer k;
assign Buff_Array1=Buff_Array>>1;
always @ (posedge Clk)
begin
assign Audio_out=Buff_Array[0]+ Buff_Array1[k];
end
endmodule
module chorus(Buff_Array,Buff_Array1,Audio_out1,Clk);
input [11:0] Buff_Array,Buff_Array1;
input Clk;
output reg[11:0] Audio_out1;
integer G;
integer k;
assign Buff_Array1=Buff_Array>>1;
always @(posedge Clk)
begin
for (k=1;k<=801;k=k+1)
case (k)
...
endcase
assign Audio_out1=Buff_Array[0]+Buff_Array1[G];
end
endmodule
module Flanger(Buff_Array,Audio_out2,Clk,Buff_Array1);
input [11:0]Buff_Array;
input Clk;
output reg [11:0]Audio_out2;
inout [11:0]Buff_Array1;
integer G;
integer k;
always @(posedge Clk)
begin
for (k=1;k<=400;k=k+1)
case (k)
...
endcase
assign Audio_out2=Buff_Array[0]+Buff_Array1[G];
end
endmodule
module Phaser(Buff_Array,Audio_out3,Clk,Buff_Array1);
input [11:0]Buff_Array;
input Clk;
output reg[11:0]Audio_out3;
inout [11:0]Buff_Array1;
integer G;
integer k;
always @ (posedge Clk)
begin
for (k=1;k<401;k=k+1)
case (k)
...
endcase
assign Audio_out3=Buff_Array[0]-Buff_Array1[G];
end
endmodule
module Mux(out1,a,b,s);
input [11:0]a,b;
input [11:0]s;
output [11:0]out1;
wire [11:0]w2,w3;
wire [11:0]w1;
not(w1,s);
and(w2,a,w1);
and(w3,s,b);
and(out1,w2,w3);
endmodule
module mux4to2(Audio_out,Audio_out1,Audio_out2,Audio_out3,s1,s0,out);
input [11:0]Audio_out,Audio_out1,Audio_out2,Audio_out3;
input [11:0]s1,s0;
output [11:0]out;
wire [11:0]w1,w2;
Mux m1(w1,Audio_out,Audio_out1,s0);
Mux m2(w2,Audio_out2,Audio_out3,s0);
Mux m3(out,w1,w2,s1);
endmodule[/I]
It gave a green OK Tick! I thank you both, although you mocked me a little but also made my program work which is deeply appreciated.
But Still I have way to go...If you have any advice about the coming approach I am ready to learn!
A next step could be to implement BuffArray in a way that it can use internal FPGA RAM instead of logic cell registers.
Indeed. Hence my advice earlier on to use block ram resources, and use core generator to pointey clickey the module together. I suspect that's the fastest way to something working, taking into account the current code. As in, least painful learning curve at this point I suspect.
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 always @* begin case (s[1:0]) 2'd0 : out = in[0][11:0]; 2'd1 : out = in[1][11:0]; 2'd2 : out = in[2][11:0]; 2'd3 : out = in[3][11:0]; default : out = {12{1'bx}}; // you'll end up with x's if your s input is not 1's or 0's endcase end
Yeah, sometimes one must be willing to throw away a dead end approach and try something different.
I tried to subtly point out that using 49K of registers was ridiculous. I guess I should have just said use a block RAM.
I also think there are too many modules, the design is broken up too much. There was no reason for doing that. I'd also like to know how mux4to2 or any of the modules communicates with the CircularBuffer as there isn't any top-level file. Besides having modules like mux4to2 and mux would never be used outside of a school environment. The mux module is also a problem as the primitives and and not take scalar inputs/outputs.
This is how you code a 4-to-1 mux (4 inputs with 1 output mux4to2 implies something entirely different)
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 always @* begin case (s[1:0]) 2'd0 : out = in[0][11:0]; 2'd1 : out = in[1][11:0]; 2'd2 : out = in[2][11:0]; 2'd3 : out = in[3][11:0]; default : out = {12{1'bx}}; // you'll end up with x's if your s input is not 1's or 0's endcase end
Now I won't even go into what is wrong with having a for loop indexing through all the Gs in the Audio_out3=Buff_array - Buff_Array1[G] statements.
I detest the upper/lower case garbage for names. I know that is sort of a religious issue for people, but I think it reduces code maintainability and increases the likely hood of having signals that don't go anywhere as Buff_Array and Buff_array are two different signals.
You need to throw this code away and write a hardware description of a viable hardware design.
Regards
Indeed. Hence my advice earlier on to use block ram resources, and use core generator to pointey clickey the module together. I suspect that's the fastest way to something working, taking into account the current code. As in, least painful learning curve at this point I suspect.
You'll have a sample clock (e.g. 44 or 48 kHz) which is shared by all signal processing functions, also ADC and DAC.Now, I have a question. Circular buffer needs a clock pulse, given that other effects take benefit of it, Do they need clock pulses too ? or are good on their own ?
Re: Mux confuzlement: I said you should put a mux where you had that case statement. To be clear: the case statement you had did not describe any synthesizable hardware. So the idea is to remove your non-synthesizable stuff (case statement) and replace it with a synthesizable description of a mux. And where the confusion starts is that one of the ways to describe a mux is by using a case statement. Now note that not all case statements are magically a mux. Nor does a mux require a case statement.
For some examples on different MUX styles, see this: https://www.asic-world.com/examples/verilog/mux.html
Also note the difference between your original case statement and the one in the example.
You'll have a sample clock (e.g. 44 or 48 kHz) which is shared by all signal processing functions, also ADC and DAC.
Buff_Array[0] <= Audio_in;
for (k = 1; k <= 4095; k = k+1)
for (t=1,t<=k,t=t+1)
Buff_Array[t] <= Buff_Array[t-1];
end
end
ZZZZZZZZZZZZs and everything else was XXXXXXXXXXXX.
Code Verilog - [expand] 1 2 3 reg some_reg_i_forgot_to_initialize; // not initialized, so sim will show an X. reg some_reg_i_actually_did_initialize = 1'b0; // initialized
Buff_Array[0] <= Audio_in;
for (k = 1; k <= 4095; k = k+1)
for (t=1,t<=k,t=t+1)
Buff_Array[t] <= Buff_Array[t-1];
I already pointed out that there is no top level file that says how all the module are connected to each other. Which translates to a lot of zzzz's in simulation.
I also mentioned that having all of the code in separate modules is probably not a good way to implement this as each module contains very little code. Like the separate modules for a 2-to-1 mix and a 4-to-1 mux.
Code:Buff_Array[0] <= Audio_in; for (k = 1; k <= 4095; k = k+1) for (t=1,t<=k,t=t+1) Buff_Array[t] <= Buff_Array[t-1];
I don't understand the purpose of the nested iteration for the circular buffer. But apart from this point, it's not a reasonable way to design the buffer, because it's no synthesizable in block RAM.
Instead you'll have a circulating write pointer. To generate a delay, you read the data at specific distance from the write pointer.
You weren't supposed to remove the muxes in the first place (i.e. the CASE statement). The problem was you were multiplexing task calls (like you can in SW). What you coded wasn't synthesizable as tasks are only synthesizable when they represent combinational logic.You guys told me to use modules instead of tasks,I did but now I can't think of any other way to make them less! They are all Vital for this project. I was also told to use MUXes, but now ads-ee is telling me the code very similar to the one I had first optimized.
No, I am not trying to be a stringent teacher (besides the recommendations about the signal naming conventions) and my intention is not to humiliate you. I'm trying to get you to stop being a software programmer and think like a hardware engineer. I also asked you what you meant by the green tick, I already knew that given the code you've posted it didn't mean much besides a single module could be compiled correctly.Now please, Are you trying to help me or just want to play the role of a stringent teacher ? your way of talking is humiliating. people are not born with FPGAs in their hands. Well, I wrote a code and got a green OK Tick at the stage of synthesizing, I did not say I implemented the code on my device and everything worked. I just paced a small step forward which was,to me, very relieving and yes,thanks to you.
the green tick is uttered out when MUX4to2 is the topmodule.
Why do you insist on being so attached to this code. Is this something to do with your pride? I've been trying to get you to dump this code and approach writing it with a hardware mindset. Given you've spent enough time on the current code to have rewritten the entirety of it, I can only assume you are not able to realize that you might not be coding the design correctly.I understood what you tried to make me learn, and i did my best to do so. But really I can't throw this code away, I've got to bite the bullet and proceed with what I've done till now. I may not get any physical results but surely will have to make the best out of it.
If you interpret the code as a software program, it probably looks, to you, like it does what you desire. Looking at it from a hardware perspective you don't even index the buffer array with a hardware address generator. Using a for loop to access the array doesn't translate to implementing a RAM access.Now see it this way,I want to have a concise overview of what I think/hope my code will do.
I have a circular buffer. Audio samples go through it and get out at the end of it by a precise clock pulse. 4096 Blocks( Preferably on an external RAM). clock must be synchronized with the sample rate of my A/D converter. now I have some customers who pick the samples from the RAM and take it out. Echo always takes the sample from the first block and a sample from the t block. adds them and gives them out. the other 3 do the similar thing with some variance. and finally MR.MUX chooses which customer's load can get out.
The codes are meant to do the above. Buff_Array (input of every effect module) is taken from circular buffer.
Interpreting the code seems to do what I hope for.
Now, I have a question. Circular buffer needs a clock pulse, given that other effects take benefit of it, Do they need clock pulses too ? or are good on their own ?
Why is it impossible to put everything in one module? Please explain why, if we understand why you think this is how Verilog behaves then perhaps we can give you an explanation that makes sense to you. I suspect you are still stuck thinking of Verilog as if it behaves like a software program.Yes, that's right. that's why My simulation does not return meaningful output because my output is in another module. even if I shorten my MUX into one module it doesn't do any good, I have to merge my MUX with circular Buffer in some way. when I used tasks There were only two modules, But I'm sure even that wouldn't give proper results. So what's your suggestion ? putting everything in one module ? seems impossible without tasks.
This point seems to be a software oriented way of thinking about buffers. Do you think that passing the Buff_Array and Buff_Array1 names through the ports automatically passes a pointer to the Kth element to the module?that's the point. the stream of data circulates through the so called buffer and I Specify read pointers for each effect. But I doubt that Buff_Array in other modules is taken from the circular buffer.
Now, I have a doubt that tickles me much. Do you think the program understands that the input [11:0]Buff_Array in that 4 modules, is the Buff_Array[k] from the circular Buffer Module ?
You keep writing Verilog as if it was a software language. Both mrfibble and I have told you to not use for loops. Unless you really understand that for loops unravel (and what that really means in hardware) you shouldn't use them at all. You need to be experienced writing Verilog code without those types of constructs before you start using them.To let you know, I had a simulation with verilog test fixture and the result was not good. Inputs though declared were all ZZZZZZZZZZZZs and everything else was XXXXXXXXXXXX. I chose Circular Buffer as the top module. which is also a doubt. is the top module chosen properly ? Whereas MUXes need control too... Think I just have to merge the MUX with circular Buffer... I even doubt that my circular Buffer does what I expect to... I think it needs another for within the second for. something like:
Code:Buff_Array[0] <= Audio_in; for (k = 1; k <= 4095; k = k+1) for (t=1,t<=k,t=t+1) Buff_Array[t] <= Buff_Array[t-1]; end end
I already pointed out that there is no top level file that says how all the module are connected to each other. Which translates to a lot of zzzz's in simulation.
I also mentioned that having all of the code in separate modules is probably not a good way to implement this as each module contains very little code. Like the separate modules for a 2-to-1 mix and a 4-to-1 mux.
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 module top ( input clock, input reset, input [1:0] select, output reg [11:0] mux_count ); // four counters that count by 1, 2, 3, or 4 reg [11:0] counter1; reg [11:0] counter2; reg [11:0] counter3; reg [11:0] counter4; always @ (posedge clock) begin // clear all the counters on a reset if (reset) begin counter1 <= 12'b0; counter2 <= 12'b0; counter3 <= 12'b0; counter4 <= 12'b0; end else begin // based on select input increment one of the counters // leaving the other counts alone. case (select) 2'd0 : counter1 <= counter1 + 1; 2'd1 : counter2 <= counter2 + 2; 2'd2 : counter3 <= counter3 + 3; 2'd3 : counter4 <= counter4 + 4; endcase end end always @ (posedge clock) begin // multiplex the counter outputs to a single output if (reset) begin mux_count <= 12'b0; end else begin case (select) 2'd0 : mux_count <= counter1; 2'd1 : mux_count <= counter2; 2'd2 : mux_count <= counter3; 2'd3 : mux_count <= counter4; endcase end end endmodule
There is that word again...program. You're not writing a program, you are describing hardware. There is a difference.Not willing to change the program completely is because I fear it might take too long. Do you think I can Redo everything the hardware way in less than a week ? If so, Ready to go!!
You add it to your top level module, which you still haven't written. You seem to have a misconception of how to structure the Verilog code. Maybe it has something to do with your difficulties in understanding Verilog is a hardware description language and not a programming language like C, C++, Fortran, Pascal, C#, Java, Basic, etc.I built a true dual-port Block Ram using Core generator. I added it to my project, Now do I have to take it into circular Buffer Module(if possible) or take it as an independent module ?
Not willing to change the program completely is because I fear it might take too long. Do you think I can Redo everything the hardware way in less than a week ? If so, Ready to go!!
I built a true dual-port Block Ram using Core generator. I added it to my project, Now do I have to take it into circular Buffer Module(if possible) or take it as an independent module ?
I'd have to agree with that... When I started out with verilog I got me a book for the basics, and that saved me a lot of time. I got "A Verilog HDL Primer" from Bhasker at the time, but maybe that is a bit dated by now. Anyone with up-to-date book tips? If I were me and I'd have to get a book again I'd try to get one in roughly Bhasker's style (okay as far as I'm concerned), but with more emphasis on synthesizable logic. Because what synthesizes and what doesn't I unfortunately did not learn from that book. I got that from reading papers & watching xilinx training youtube vids and such."Besides that your resistance to reading a book on Verilog has me perplexed."
There is that word again...program. You're not writing a program, you are describing hardware. There is a difference.
You never answered my question...Why do you think that you have to use a task to put all the code in a single file? I really want to understand the disconnect you have with understanding how to write Verilog code.
You add it to your top level module, which you still haven't written. You seem to have a misconception of how to structure the Verilog code. Maybe it has something to do with your difficulties in understanding Verilog is a hardware description language and not a programming language like C, C++, Fortran, Pascal, C#, Java, Basic, etc.
Regards
- - - Updated - - -
If you actually knew Verilog, and I mean from reading/studying a book that describes how to write Verilog code for use with a synthesis tool for describing hardware, then a week would be more than enough time to implement the simplest solution with all of the possible algorithms implemented in parallel and the selection of which algorithm to use being multiplexed out to the user. I'm pretty sure if you knew Verilog even half as well as FvM, mrfibble, or myself you would have completed this design with the architecture you're using (brute force approach) in only a few days time. So far, you haven't been "listening" to us as you continually keep approaching the problem as if it was software, even though we've continually told you otherwise. Therefore I'm not at all sure if you will successfully complete your project in the time allowed. You may have to hire a consultant to implement your algorithm.
Besides that your resistance to reading a book on Verilog has me perplexed. I don't understand why you won't read a Verilog book. I read the first Verilog book I bought over a single weekend. http://www.amazon.com/The-Verilog%C2%AE-Hardware-Description-Language/dp/0387849300 (mine is the 1st edition). Just from reading that single book I learned enough to use Verilog to write a hardware description for a design.
Mmmh, hard to give an answer to.Depends on how fast you learn and how much of your current design you are willing to let go. As an alternative, look at it as a DSP problem. As a hint for alternate solutions that do not need to take forever to implement, read this: **broken link removed**
Describe your audio filter in terms of FIR, and you are already half way there. With as added bonus that you can use this technique for more advanced stuff later on as well.
If your circular buffer module does what I think it does, then you put it in the circular buffer. As in you have a circular buffer module, and that instantiates the block ram module. As in, the bram module is a submodule of the circular buffer module.
PS: Out of interest, what is your background? Any EE in it, or more of a programming background. Well, I could just ask "what programming languages?" because it seems obvious you come from a programming background. If so, which one? Oh oh oh, can I guess? It's going to be C# right? That is potentially even worse than java for this sort of thing I just realized. For some strange reason C/C++ people tend to do okay-ish, especially if they've mucked about in asm. But java seems to warp the mind in the direction of abstract interface abstraction factory serializers, which in turn is not good for thinking in terms of hardware.And I'd expect C# to do something similar, but possibly more painful.
PPS: Coming back to the circular buffer thing, I'd make a small & simple testbench for that if I were you. Do some reads/writes. That way you can check the waveforms and see if it behaves as you think it behaves. Also, did you notice the Documentation button in core generator? That should open up a pdf with info on that bram core.
- - - Updated - - -
I'd have to agree with that... When I started out with verilog I got me a book for the basics, and that saved me a lot of time. I got "A Verilog HDL Primer" from Bhasker at the time, but maybe that is a bit dated by now. Anyone with up-to-date book tips? If I were me and I'd have to get a book again I'd try to get one in roughly Bhasker's style (okay as far as I'm concerned), but with more emphasis on synthesizable logic. Because what synthesizes and what doesn't I unfortunately did not learn from that book. I got that from reading papers & watching xilinx training youtube vids and such.
Check this one for lots of good stuff: http://www.sunburst-design.com/papers/
Anyways, if you don't want to spend the moneys for a book, check those sunburst papers. If you don't want to spend the time to read, then you are out of luck.
- - - Updated - - -
At a minimum: I'd say read this one on verilog-2001: http://www.sunburst-design.com/papers/CummingsHDLCON2001_Verilog2001.pdf
Verilog-2001 is supported by xilinx xst (the synthesis tool).
- - - Updated - - -
Also, quick FIR intro: http://www.dspguru.com/dsp/faqs/fir/basics
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?