Golborne Vintage Radio

Full Version: New language....
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
So, for a lot of my career I've done both software and hardware development... More years of many languages, especially C++, than I care to try to remember....

But never VHDL until now!

Been reading up for some months and working through loads of examples. Really liked the free pdf "Free range VHDL" by Bryan Mealy and Fabrizio Tappero. My sort of book at a price I like...

Now have bought a Digilent BASYS3 board. Comes with Xilinx Vivado licenses and a raft of tutorials...
For some reason I thought you already had one of these: https://www.xilinx.com/products/boards-a.../arty.html

I've been doing VHDL for some years. Not in any very clever way but I've found methods and styles that suit me and my designs. In particular I've not done much simulation - I tend to compile the code and see how it flies.

One of the biggest adjustments that software guys have to make when doing VHDL is remembering that it's not executed sequentially. And that it's generating hardware. In many cases the order of statements is unimportant. So for example:

COUNT <= COUNT + 1;

synthesises a simple up counter (of however many bits you declared) but

COUNT <= COUNT + 1;
COUNT <= COUNT + 2;

is a horrible thing to say in VHDL. In many languages it would add 1, then add 2 to COUNT. Honestly not sure what it would do in VHDL. It's legal (I think) and will synthesise but should never be done.

Please feel free to ask questions.

Thanks for the book recommendation.
The BASYS3 is just like an Arty on steroids. Same device, just more peripherals...

Having a hardware background helps in getting my head round concurrent vs. sequential statements and the hybrid that is processes...

Having a deep real-time software background is helpful in rationalising the different architectural paradigms.

I like to understand everything I can up front.
Concurrent vs sequential isn't an easy concept at first. The way I think about it is that if the logic is outside a process then it's just gates. If it's inside a process with a clock then it's a bunch of flipflops that all get clocked together. Here's a simple example from one of my designs with a clock enable. It's a 4 bit wide control register that's memory mapped at 070 hex. CWR is a write enable.

process (CKC) begin
if rising_edge(CKC) then
if (CONTROL_ADDRESS(11 downto 0) = X"070") and CWR = '1' then SET_WINDOW_START <= CONTROL_DATA(3 downto 0); end if;
end if; -- CKC
end process;

Intelligent use of boolean signals makes life easier. As does use of unsigned, signed and integer instead of SLV where sensible.

This function, in a "useful functions" file that's declared in all modules is a godsend:

-----------------------------------Boolean to standard logic----
Function to_std_logic(X: in Boolean) return std_logic is
variable ret : std_logic;
begin
if x then ret := '1'; else ret := '0'; end if;
return ret;
end to_std_logic;
--======================================

You can then write: my_standard_logic_signal <= to_std_logic(my_boolean_signal);

Another useful hint. When you've got an SLV that you need to assign to a constant it can get a bit tedious. Espeically when it's not a multiple of 4 bits long. This assigns a 27 bit SLV to 45(decimal) with minimum effort:
my_27_bit_slv <= conv_std_logic_vector(45,26));

The conversions between unsigned, signed, SLV and intgeger vary slightly according to which libraries you use. For historic reasons I still use:

use IEEE.std_logic_1164.ALL;
use IEEE.std_logic_ARITH.ALL;
use IEEE.std_logic_UNSIGNED.ALL;

This is old fashionedand strictly speaking proprietary to Synopsis but fully supported by everyone and always will be.

The modern way is to use:

use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

If I changed my library declarations it would break a load of stuff in my designs and I'd get horribly confused. So I stick with the old ways. With the Vivado tools (it's a bit different on the old ISE tools) my library delcarations tend to read:

library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.std_logic_ARITH.ALL;
use IEEE.std_logic_UNSIGNED.ALL;
library UNISIM;
use UNISIM.VComponents.all;
library jb_lib;
use jb_lib.GENERAL_CONSTANTS.all; -- Constants that stay that way
use jb_lib.USEFUL_FUNCTIONS.all; -- Useful functions such as "to_std_logic" (boolean to std_logic)

Hope this helps a little.
I've not really had any problem with the concepts involved - they're different, sure, but not that bad.

I'm really enjoying it - I've always had a very structured and disciplined approach to software and h/w design, so that fits well with VHDL.

Like most technologies, it's not really about learning the language - anyone can do that - it's more about getting into the correct mindset. Once you achieve that, then it's actually pretty straightforward.

Over the years I've met many developers who know a language really well, but are actually pretty poor programmers. It's like the distinction between folk who do maths, and mathematicians.

Folk who do maths follows paths set down by others - they follow known rules to achieve their objective. However they have little originality and have problems with situations which aren't already covered by their knowledgebase.

Mathematicians, OTOH, are original - they see and feel the problem. Yes, they use the same tools as the previous lot, but are also capable of original thought in tackling unfamiliar problems.

In a 35 year career in the City of London, I've only met a handful of truly creative developers. Plus an awful lot of journey(wo)men...
VHDL is certainly very strongly typed. (who said "strong typing is for programmers with weak memories"?) I've not looked at Verilog much but I think it's much less so. In particular std_logic and boolean aren't distinguished.. Rather like the old ABEL language that I used many years ago for programming early PLDs.

VHDL conditional statements (IF, WHEN, WITH, CASE) all have little wrinkles. It's annoying that IF and CASE must always be used inside processes. Though these needn't be clocked. The syntax of IF is more intuitive than WHEN though both do the same job, likewise CASE makes more sense than WITH.

I'm sure you've realised that CASE and WITH must always be complete, using an OTHERS clause. The daft thing is that the synthesis engine usually complains about lack of OTHERS even if you have specified all cases explicitly. IF generates logic with priority which is probably obvious to software folk but a potential trap for many. It's one place where the order of statements really does matter.

On the subject of mindset, it's really important to get away from thinking about the old 74 and 4000 series devices. That can be hard for older engineers who have used them extensively.
(20-05-2018, 07:47 AM)ppppenguin Wrote: [ -> ]On the subject of mindset, it's really important to get away from thinking about the old 74 and 4000 series devices. That can be hard for older engineers who have used them extensively.

That's where behavioral modelling wins...
I was only too happy to abandon 74 and 4000 logic chips which were rarely just right for the job. Notably very few had clock enables (377 register, 161 and 163 counters were exceptions) so you could do good quality synchronous design.
Well, it seems that I can't download the Vivado suite here - it's "export control" blocked as my ip address is in Dubai and that's in group D of the USA government's export control list, meaning that Xilinx block downloads.

VPNs don't work either as all the endpoints are blacklisted, so I'll have to wait until I'm back in the UK for a conference  in a week.