AXI-Lite register bank

This (relatively large) code snippet is about implementing a register bank with an AXI-Lite interface.

Some time ago I published a previous version of this module, based on an AXI-Lite code from Xilinx. From the feedback I received on Reddit, I understood that the Xilinx code for AXI-Lite slave, regretfully, is broken. So I wrote down my own version of the code and tested it thoroughly.

Continue reading “AXI-Lite register bank”

Parallel to serial converter

This VHDL module receives parallel data as input at it outputs the data in serial format.

This VHDL module receives parallel data from the data_in bus when load is asserted. One clock after load is de-asserted, the data is serially transmitted out on the data_out line, MSB first, and valid is also asserted. The frame signal is asserted together with the end of the transmission (i.e. when the LSB is transmitted).

Continue reading “Parallel to serial converter”

VHDL Modulo counter, how to code and test it

A modulo counter is a counter that wraps around when it reaches a certain value. For example, a counter modulo 5 will count 0, 1, 2, 3, 4, 0, 1, …; namely, after 4 it will wrap around to 0. The reason the counter wraps after 4 is that to count five clock pulses starting from zero, the maximum value of the counter must be (modulo-1), in this case, 5-1=4.

Every VHDL counter is a modulo counter. If you define a two-bit counter, it will wrap around automatically from 3 to 0 without the need of writing special logic for that.

Continue reading “VHDL Modulo counter, how to code and test it”

FPGA internal tri-state buses

For me, and for many other designers, the first time we saw the internal memory blocks in an FPGA came as a little shock.

Some of us were used to RAM devices used in Board Design. These devices use bidirectional data buses. Even the fastest memories, DDRn DRAMs, use bidirectional data buses (‘n’ has changed over the years, from plain DDR to current DDR4).

So, how come internal memories on an FPGA have TWO data buses? Isn’t that a waste of resources? Why don’t FPGAs have internal tri-state buses?

Continue reading “FPGA internal tri-state buses”

VHDL or Verilog?

This question gets asked again and again, by beginners and experienced designers alike.

When I saw it posted on the FPGA group on Reddit, I liked the answer from user fft32, so with his permission, I reproduce it here with some minor changes and additions.

VHDL compared to Verilog

VHDL:

  • A bit verbose, clunky syntax. I never liked that different constructs have different rules for the “end” tag, like “end synth” for architectures, versus “end component mux” for components. I always find myself looking up the syntax of packages and functions.
  • Strongly typed: It’s a bit of a pain to have to make a (0 downto 0) vector to do something like a carry-in, but at the end of the day, it can save you time debugging problems. You don’t scratch your head as to why your 10-bit vector is only 0 to 1, because you assigned a 1-bit value to it (a thing you could do in Verilog, but in VHDL would produce a compile error). By default, in Verilog, undeclared signals default to 1-bit nets. Once I accidentally did this with a clock and it took me a while to figure out why nothing worked.
  • Libraries: This is good and bad for me. It’s great to wrap your code in an organized and reusable manner. However, many “everyday” functions come from libraries rather than built into the language. There are non-standard libraries like std_logic_unsigned/std_logic_signed that are used in a lot of legacy code and old code examples. They’ve since been replaced by numeric_std. The conversion between types needs functions whose format is quite annoying.

Verilog:

  • Writing code seems more streamlined. No component declarations, loose data types (everything is just bits, really).
  • C-like syntax.
  • The resulting code is more compact.
  • Low-level descriptions are closer to actual hardware.
  • Verilog has a poor design of its concurrency resolution scheme. Being an HDL, concurrency is obviously a very important aspect. Here is a write-up concerning this point.

At the end of the day, the two languages are really able to achieve the same designs. I think it’s good to understand code in both languages, but since mixed language support is common, I don’t see an issue sticking with the one that you prefer.

To the comments from fft32, I would add that in my opinion, Verilog with its plain syntax is easier to learn and grasp for the beginner.

Also, from my experience, Verilog tends to be dominant in the ASIC arena, while VHDL is the language of choice for most FPGA designs.

And the winner is?

Well, none of the two, at least as these words are written. In the long run, as you advance in your HDL designer career, you will be probably using both, although also probably using one of them most of the time.

If you are wondering which one you should start with, take the one that you feel more comfortable with. Or, ask colleagues and teachers which one is most needed in the market niche you want to be part of. The important thing is to grasp the structures behind the language, and not the language itself.

To be honest, it seems that both fft32 and I mostly used VHDL, so this comparison could be a little biased. But, after all, both languages are Hardware Description Languages. So what really matters are the flip-flops and gates that give life to your design, and not so much how in what language you describe them.

Whatever you choose, good luck!

Addendum

On May 2017 I put a link about this blog topic on Hacker News. For some reason, the link got a lot of hits and there also was a lively interchange of comments regarding Verilog, VHDL… and the future of HDL languages.

I have summarized some of the comments below:

  1. It seems that Verilog got its syntax from C, and VHDL from Ada. I don’t know Ada so I couldn’t tell, but Verilog looks C’ish to me also.
  2. System Verilog is also a language worth checking since it has powerful verification constructs.
  3. Many people talked about what seems to be the next step, which could leave VHDL and Verilog behind (as C left Assembler behind, might I add). The next step may well be High-Level Synthesis.
  4. Another HDL tool worth checking: MyHDL which reportedly uses the flexibility of Python for HDL editing
  5. And last, for the lighter side of the issue, some time ago there was a competition between VHDL and Verilog… For more details, check here (actually this is very old, and I don’t think its results are conclusive, but I thought it would be fun to mention it).

If you want to check all the comments on Hacker News by yourself, here they are.

Component vs. entity

An Entity defines the interface of a design unit. The elements of an entity are:

  • Name of the entity
  • Generic parameters
  • Ports (connections of the entity)
    • The most popular port types are in, out, and inout.

The architecture specifies the behavior of an entity. An entity can be bonded to several architectures. Each architecture sees all the elements (ports, parameters) of the entity.

component consists of an entity and architecture pair. A component must first be declared. The declaration is a ‘virtual’ action, a declared component is doing nothing until it is instantiated.

Continue reading “Component vs. entity”

Signed, unsigned, std_logic_vector, and integer

VHDL is a strongly typed language. It is also a language with quite a long history. These two facts together make the handling of signed and unsigned numbers quite confusing. Even today I see lots of code examples with bad treatment of signed and unsigned arithmetic.

Part of the history of the VHDL language is the std_logic_arith library. This library is a non-standard library, or maybe I should say a de-facto standard library, created by Synopsis. I recommend not to use it, since there is an IEEE library for arithmetic operations today, ieee.numeric_std.

	-- Definition of unsigned, signed, integer and std_logic_vector signals
	signal u_reg   : unsigned (15 downto 0);
	signal s_value : signed (15 downto 0);
	signal int_var : integer range 0 to 2**15-1;
    signal slv     : std_logic_vector(15 downto 0);

begin 
  -- Conversion functions / typecasting	
  
  -- unsigned/signed to std_logic_vector
  slv <= std_logic_vector(u_reg);
  slv <= std_logic_vector(s_value);
 
  -- std_logic_vector to unsigned/signed
  u_reg   <= unsigned(slv);
  s_value <= signed(slv);
  
  -- unsigned/signed to integer
  int_var <= to_integer(u_reg);
  int_var <= to_integer(s_value);
  
  -- integer to signed/unsigned
  u_reg   <= to_unsigned(int_var, u_reg'length);
  s_value <= to_signed(int_var, s_value'length);
 
  -- std_logic_vector to integer
  int_var <= to_integer(unsigned(slv));   -- std_logic_vector is unsigned
  int_var <= to_integer(signed(slv));     -- std_logic_vector is signed

  -- integer to std_logic_vector
  slv     <= std_logic_vector(to_unsigned(int_var, slv'length)); -- std_logic_vector is unsigned
  slv     <= std_logic_vector(to_signed(int_var, slv'length));   -- std_logic_vector is signed
  

Adding to the confusion is the fact of how operations are made for binary coded numbers. Unsigned numbers represent natural numbers from zero to the maximum value that can be coded in the vector. If we use 8-bit vectors, we will be able to code values between 0-255. To represent signed numbers, one popular format is two’s complement. Using the two’s-complement format we can code numbers from -128 to 127 in an eight-bit vector.

Unless told beforehand, VHDL has to know if a number is signed or unsigned. I will give you what I think are MUSTs and also some recommendations to work with numbers and avoid pitfalls.

  • Use ieee.numeric_std. DO NOT use std_logic_arith.
  • Be very careful when using the signed or unsigned libraries. When you use these libraries, all the std_logic_vector arrays in the file are considered signed or unsigned by default. This can cause very difficult to track bugs if there are mixed types (signed/unsigned) on the same VHDL file.
  • Signals that should be treated as signed or unsigned are EXPLICITLY declared as such in your source file.

Coding and testing a Generic VHDL Downcounter

For synchronous logic, a timer and a counter are almost the same. After all, a timer counts clock units. That is why in many digital applications we see them called timers/counters.

The code below models a generic timer/counter, using unconstrained ports:

Continue reading “Coding and testing a Generic VHDL Downcounter”