Verilog equivalent of a variable? - Page 1
Forum section: electronics / general

author: dentaku
author_rank: Frequent Contributor
timestamp: January 17, 2021, 06:02:32 pm
content: I modified some code I found to work on my inexpensive EP2C5 mini board and it works.The 3 LEDs on the board count up at a certain speed and if I press the button they count faster.Code://clk=PIN_17, button=PIN_144, LEDs = PIN_9,PIN_7,PIN_3module bin_count_button_speed(input clk,input button, //set as weak-pullup in pin planneroutput [2:0] LED //connected to 3 onboard LEDs);reg [26:0] cnt;always @(posedge clk)begincnt <= cnt + (button ? 27'd1 : 27'd4); //button==1?, add 1... else add 4end//invert cnt because LEDs are connect to VCC and light when given a path the gndassign LED = ~cnt[26:24];endmoduleThat's all fine but I thought that in microcontroller code I could have created a variable that does the ternary operatoreven though in this simple code there's no reason to do so.I made a variable namedshiftand IT checks to see if pin 21 is high or lowPIND & 00000001 == 1 ? 0 : 2;which makes it's value either 0 or 2Without this variable I obviously could have just donePORTA = count << (PIND & 00000001 == 1 ? 0 : 2);Code:const int pushbutton_pin = 21; //pin21 is PORTD0void setup() {//set pins 27 to 29... 3 MSBs of PORTA, as outputpinMode(27, OUTPUT);pinMode(28, OUTPUT);pinMode(29, OUTPUT);pinMode (pushbutton_pin, INPUT_PULLUP); //MEGA 2560 pin21 as input with pullup for pushbutton to ground}/*when button is NOT pressed, pushbutton_pin will == 1 due to the pullup so shift will be 0when button IS pressed, pushbutton_pin will == 0 so shift will be 2*/void loop() {int shift = PIND & 00000001 == 1 ? 0 : 2; //button == 1?... shift = 0 else shift = 2for (int count = 0; count < 256; count++){PORTA = count << shift; //shift left 2 places when button is pressed}}QUESTION?What would be the Verilog equivalent to creating the variable namedshift?I know this code doesn't need that ternary operator to be it's own variable but it's just an example.I tried this code on my FPGA and it works.Code://clk=PIN_17, button=PIN_144, LEDs = PIN_9,PIN_7,PIN_3module bin_count_button_speed(input clk,input button, //set as weak-pullup in pin planneroutput [2:0] LED //connected to 3 onboard LEDs);reg [26:0] cnt;reg [2:0] increment_speed;always @(posedge clk)beginincrement_speed <= (button ? 27'd1 : 27'd4); //button==1?, add 1... else add 4endalways @(posedge clk)begincnt <= cnt + increment_speed;end//invert cnt because LEDs are connect to VCCassign LED = ~cnt[26:24];endmoduleSO, is this the correct way of creating, in Verilog, what in MCU code you would call a variable?

author: asmi
author_rank: Super Contributor
timestamp: January 17, 2021, 08:06:15 pm
content: If you want to get anywhere with HDL, you've got to drop the notion that they are anything like your regular programming languages. Despite the somewhat similar look, they are completely different beasts and describe completely different concepts. HDL is not executed in hardware (forget about simulation for a moment), instead itdescribeswhat hardware should do, and synthesizer then actually creates and wires up hardware bits and pieces to make that happen.Your code kind of works, but not exactly the way you think it does. If you look closely at the simulation waveforms, you will see that your second "always" block will only "see" the changed variable on the next clock cycle, but not on the one when you actually effect the change. And this is fundamentally different to MCU which would "see" updated variable immediately. This difference might seem subtle and irrelevant, but it's just a tip of an iceberg of fundamental differences in the way these things work.

author: hamster_nz
author_rank: Super Contributor
timestamp: January 18, 2021, 12:11:54 am
content: HDL doesn't have loops (well, not as programmers understand them). The passage of time is measured in clock ticks.There are two sorts of 'signals' inside the H/W of FPGAs- Those that update only on the clock tick ( this is combinatorial logic)- Those that update continuously during the clock tick (this is state, held in registers ('flipflops') and memory blocks).To make matters worse Verilog has the ability to blur this with what are called "blocking" and "nonblocking" assignments . Different combinations of code blocks and assignments will generate different hardware implementations.Taking time to learn and appreciate the different hardware that different code structures will generate will be essential to your long term success with HDLs.It is one of those really hard skills to pick up, like riding a bike, or rolling a kayak. But a little study and a lot of practice will make it click in place.Here's one rule of thumb that sounds close to right, but lacks nuance:• Combinational logic: Use blocking ('=') statements with always blocks with the * operator to mimic logic flow of combinational logic.• Sequential logic: Use non-blocking ('<=') statements with always blocks sensitive to rising clock edge to mimic parallel sequential logic.As always reality isn't as clean-cut as this.A simple discussion is at ttps://www.nandland.com/articles/blocking-nonblocking-verilog.html

author: james_s
author_rank: Super Contributor
timestamp: January 18, 2021, 02:40:30 am
content: As others have mentioned, you're thinking about this the wrong way. Forget about programs, programming won't help you here and it's going to hinder you until it clicks in your head what HDL is actually doing and what it is not. HDL is a "false friend" of sorts to a software programmer, it looks like a program but it isn't, it's a fundamentally different concept. You're not writing a program, you are designing a digital logic circuit. Design the circuit first, you may find it helpful to draw a schematic out on paper. Then once you have the circuit designed, think about how to describe it in Verilog. There are different levels of abstraction you can use to describe it which will all result in essentially the same circuit. There is no such thing as a variable, the closest thing to one is a register which is an array of flip flops or latches.

author: helius
author_rank: Super Contributor
timestamp: January 18, 2021, 02:40:57 am
content: Quote from: hamster_nz on January 18, 2021, 12:11:54 amI think you have this backwards... Registers are clocked. Combinatorial logic is unclocked.QuoteHard agree. You should have experience designing and debugging logic with schematics and breadboards before trying to use HDLs. This will give you insight into the difference betwen RTL and behavioral architectures that is otherwise hard to understand.QuoteThis is correct, and unfortunately the nomenclature is rather unhelpful. Blocking and Non-Blocking assignments are relative to asimulationcontext, which was Verilog's original purpose. Thesimulatorresponds to them by blocking, or not-blocking, as appropriate. The distinction is necessary in Verilog, but not in VHDL, which has its own simulation method (delta-steps) to resolve assignment conflicts.The design of Verilog can also bite when using simulator commands like $display() since they are unsynchronized with respect to assignments.

author: BrianHG
author_rank: Super Contributor
timestamp: January 18, 2021, 03:12:06 am
content: Here, this post with my illustration helped Nockieboy with the same HDL interpretation of coding issue.https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2767312/#msg2767312Only read that post + a few down to get the idea.Ignore the fact I talking about the best possible speed as your projects will never require hundreds of megahertz, but the lesson on what's going on inside the compiler with your coding still stands.

author: dentaku
author_rank: Frequent Contributor
timestamp: January 18, 2021, 03:56:35 am
content: I pretty much assumed these would be the types of answers I would get if I posted some microcontroller code in the FPGA forumThe funny thing is that the thing I hate MOST about MCUs is being stuck in loops and even worse, having to deal with nested loops and then the problems with "scope".I've always preferred logic circuits and like things that happen in parallel. It's just how my brain works better and that's why FPGAs are interesting to me.The strange thing I that I would love to just draw the schematic like you can in older versions of Quartus but whenever you do that people keep saying that it's just not the way you should use FPGAs these days and you should only use HDLs. Obviously a large project would be unmanageable as a schematic but I'm not at that point yet.BUT, when you talk about doing everything in "software" people in forums keep talking about forgetting about programming and think of it as a hardware circuit.I get what people are saying and you all have valid points but...to get back to the original questionWould it make sense to create something that is like a variable to replace that ternary operator with something more friendly or is it just something that is not done in Verilog?

author: dentaku
author_rank: Frequent Contributor
timestamp: January 18, 2021, 03:59:48 am
content: Quote from: asmi on January 17, 2021, 08:06:15 pmI didn't think about that but I can picture it now.

author: james_s
author_rank: Super Contributor
timestamp: January 18, 2021, 04:35:27 am
content: Quote from: dentaku on January 18, 2021, 03:56:35 amWhen I say "draw a schematic" I don't mean use schematic entry to program the FPGA, that is a waste of time and results in difficult to maintain and non-portable code. What I mean is as a beginner, draw the schematic on a piece of paper to help you visualize what it is that you're trying to implement and then think about ways to describe that in HDL. As you gain more experience this will be less necessary but it can still be useful to work out portions of the design. Likewise when writing code for microcontrollers I find it helpful to draw up a flowchart on paper and once I have the flow of the program worked out I start implementing the different blocks and connecting them together.I use VHDL and in that language for a "shift" variable I would typically define it as a signal. I'm much less familiar with Verilog but isn't "wire" a similar construct? How it translates to logic in the FPGA fabric depends on the context in which it's used but if you just assign it a value typically it will form a latch or register, roughly the hardware analogy of a variable. You can also define a memory which is perhaps even closer to the concept of a variable in software. In assembly language a variable is literally a pointer to a location in RAM.

author: rstofer
author_rank: Super Contributor
timestamp: January 18, 2021, 04:46:57 am
content: Look at Figure C-4 on page 7. This is a decent hardware block diagram which can be coded directly in an HDL.http://users.ece.utexas.edu/~patt/05f.360N/handouts/360n.appC.pdfSchematic Entry is no longer supported by some tools - notably Xilinx Vivado. Times change...

author: rstofer
author_rank: Super Contributor
timestamp: January 18, 2021, 04:51:52 am
content: I don't know anything about Verilog but VHDL does have the concept of variables. See:https://vhdlwhiz.com/signals-vs-variables/The only time I have used variables is when I'm copying someone else's code. The scope of variables in VHDL is limited to the process where they are declared. Signals have a much broader scope.

author: emece67
author_rank: Frequent Contributor
timestamp: January 18, 2021, 09:13:51 am
content: .

author: BrianHG
author_rank: Super Contributor
timestamp: January 18, 2021, 10:22:49 am
content: Quote from: dentaku on January 17, 2021, 06:02:32 pmI'm not sure I understand what you are asking. cnt[] is your variable. Maybe this is what you want:assign LED = button ? ~cnt[26:24] : ~cnt[24:22] ;or, maybe this more like 'C' coding example:assign LED = 3'(~cnt >> (22+button*2));The 3' in the beginning just crops out the bottom 3 bits only for the 3 leds.>> is a normal right shift.and 22=button*2, well if you cannot figure that out...You can always:assign shift = cnt >> (22+button*2);assign LED = ~shift[2:0];again, shift would be a wire of at least 3 bits.Learn to use modelsim and a testbench so you can run the design in RTL (real-time-logic) mode and see what happens when and inspect each wire and symbol both on a logic analyzer scope (in software) and compile/simulate time is under a second especially if you work 100% within modelsim and ignore Quartus until you are satisfied with your HDL and compile it in Quartus to make the hardware follow your simulation.(It took me 3 days to learn modelsim, but I do understand the frustration involved even though I was an experienced Quartus user. The 1/10th second recompiled with instant logic output every time you chaneg a line of code it just too convenient.)

author: dentaku
author_rank: Frequent Contributor
timestamp: January 19, 2021, 04:00:10 am
content: Quote from: BrianHG on January 18, 2021, 10:22:49 amThis was actually one of the first things I even bothered programming on the the actual hardware. I've spent more time simulating stuff actually.I simulate analogue/logicl circuits and even AVR code at first and once I get that working I usually understand my circuit or code well enough that once it's built on real hardware it works on the first try on a breadboard or a real microcontroller.People seem to forget how useful simulation is, both for quickly trying out changes, fixing bugs and for learning.From Quartus, yes I've sent testbenches directly to Modelsim by clicking on the RTL Simulation button but I actually like using the horribly named "University Program VWF" feature that doesn't even require you to write a testbench. It's much nicer for simple projects to be able to draw in the waveforms for things like reset or pushbuttons , tell it how fast the clock should be and it sends everything to Modelsim and gives you back the waveforms.I also use Icarus and GTKWave with VSCode and that's nice too. I found and modified a Python script that generates a testbench that does most of the hard work for you then there's a button it adds to VSCode that sends the testbench through Icarus and VVP then offers to open the output in GTKWave for you.It saves a lot of the messing around with command line stuff.

author: BrianHG
author_rank: Super Contributor
timestamp: January 19, 2021, 07:36:05 am
content: Quote from: dentaku on January 19, 2021, 04:00:10 amIt's easier to do this in modelsim.After altera starts up a blank RTL simulation, without any TB file.Just click on the clk line and set it to 'CLK' and the desired period.Then hit the run sim button set for that period or double and watch things progress.The, click on a waveform input and hit 'force' and type in a number then hit that run button again.See how things change.Change an input back and hit run and see this sim progress.*** Now for something you cannot do in your painted stimulation waveforms.click on one of your buried code registers like IE: a counter, and add it to the waveform.click on run and watch it pop up.*** now for something else...click on that counter waveform and select force value. Type in a new number and choose 'deposit'.click on run and watch your logic get fooled into that counter being in a new numeric position and your code will continue from there...You want truly advanced, get my ellipse generator code here: (read instructions)https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3413786/#msg3413786No Quartus, just run modelsim. It works stand alone and recompiles in 1/10th of a second every time you type:do run.doSee what I made my testbench do and how it roasts that paint in number settings.It takes my ascii .txt file with commands and comments, and drives/generates the input waveform to control the ellipse generator module.Then when simulation, it generates an ascii text output file with the results cleaned up and decoded.It also makes a .bmp picture of the results you can actually see.My testbench code/script is simple/stupid enough for you to adapt to any one of your own projects.While you toy around with python and other tools, I made a systemverilog test-bench code which generates the test wavefiorm for you right there. No third party tools, no third party compilers, or even Quartus needed.( I made it this far on day 2 of learning modelsim. )

author: dentaku
author_rank: Frequent Contributor
timestamp: January 20, 2021, 03:39:15 am
content: Quote from: BrianHG on January 19, 2021, 07:36:05 amI use Modelsim that way even before I got this FPGA because I was curious about the software and I got some simulations working but for some reason I can't make anything that involves a clock to work anymore.The "University Program VWF" method works fine but the counter in this simple example I found just does nothing in Modelsim.Code:module bcd_counter (clk,count);input clk;output [2:0] count;reg [2:0] count;always @(posedge clk)begincount <= count + 1'b1;endendmodule //bcd_counterI can force the clock to pulse but the counter just sits there doing nothing.Wow this thread has gone off topic

author: BrianHG
author_rank: Super Contributor
timestamp: January 20, 2021, 07:28:11 am
content: Quote from: dentaku on January 20, 2021, 03:39:15 amRed means 'UNKNOWN'... This is why:module bcd_counter (clk,count);input clk;output [2:0] count;reg [2:0] count= 3'd0;always @(posedge clk)begincount <= count + 1'b1;endendmodule //bcd_counterIt's because Modelsim checks and tells you if you have a default power-up state set. If it is unknown, the output cannot be predicted and shows all red, IE undefined. Quartus assumes the count powers up at at 0 even if you didn't specify it in code.QuoteLearning the tool the big boys use today is worth it.Having that tool force you to properly code is worth it.For me, I've been retired for almost 15 years, the days before Modelsim came for free, but thanks to C19 and a province wide lockdown, I just recently had too much time on my hands and accomplished quite a bit with it in my first week fooling around...Next, writing a test bench which calls your counter and generates that clock signal and runs it for a set time.Other than defining the IOs and calling/initializing your counter, it's only 2 always commands to do auto make the clock and auto stop at a specific time.

author: dentaku
author_rank: Frequent Contributor
timestamp: January 20, 2021, 10:59:29 pm
content: Quote from: BrianHG on January 20, 2021, 07:28:11 amInteresting.Setting it to a known value made Modelsim work correctly.

author: emece67
author_rank: Frequent Contributor
timestamp: January 21, 2021, 12:05:09 am
content: .

author: emece67
author_rank: Frequent Contributor
timestamp: January 21, 2021, 12:16:47 am
content: .