When I was an undergraduate a lot of my classmates hated HDLs (we were learning VHDL). They often claimed they were electronic engineers and not programmers, they hated writing programs and wanted to work with circuits and electronics. It probably did not help that the professors loved to give academic problems rather than real-world issues. I think more would have enjoyed learning HDLs and RTL if they had been interfacing FPGAs with other components or designing digital filters rather than implementing LZH compression algorithms in hardware and software. However, I also think they failed to see the true power of HDLs and hardware synthesis.
What my fellow classmates did not realize is that even though they were writing RTL in a programming language-like syntax, they were actually designing circuits. I suspect the compilers and the for-loops may have thrown them off, but they were really modeling hardware. One doesn’t just begin writing RTL (without years of experience at least), one has a high -level circuit in mind that should be modeled with the RTL. Take the following Verilog RTL, for example, with a for-loop:
module bitmask(
input clock,
input [7:0] in_data,
input [3:0] index,
output [7:0] sum
);
reg [7:0] buffer;
reg [7:0] mask;
assign sum = buffer;
always @(posedge clock)
buffer <= mask & in_data;
integer i;
always @(*)
for(i=7; i>=0; i=i-1)
mask[i] = (i>= index) ? 1'b0 : 1'b1;
endmodule
For those that don’t read Verilog or just refuse to try, this module applies an adjustable mask to an input and stores the result in a register. The mask is created by specify from where the mask should begin. The result of a simulation is shown below. Note that in the output below, ptr maps to index and data maps to in_data
GtkWave display of the value-change dump (generated by GNU Icarus Verilog)
The incoming data is 0x55h, and the mask ptr is set to 4. In terms of big endianness, this means that the lower byte of the mask should be all ones and the upper byte should be all zeros. The result when the register clocks the masked data on the clock’s positive edge is 0x05h. We then change the input data to 0xDEh, and the mask ptr is set to 5. Now the mask consists of the top three bits being zeros, and the lower five bits being ones. On the positive clock edge, the result in the register is 0x1Eh.
This is a very primitive example, but I wanted to show how some simple RTL modeling can be so powerful. I synthesized this module using Synopsys Design Compiler one of my university’s lab machines. The synthesized circuit is shown below. I was synthesizing with an ASIC standard cell library, so if you did this for an FPGA you might get somewhat different output.
Unfortunately, Synopsys did not print the port names when the schematic was exported to postscript, but I think you can get the idea. The squares on the right are the flip-flops that correspong to register buffer. The ports of the left represent the inputs, and the logic gates between the inputs and flip-flops are the combination logic required to produce the mask.
The true power of synthesis is that it allows designers to increase their productivity in great strides. While it may take only a few minutes to model a circuit with RTL and do a quick simulation for verification, imagine having to do karnaugh-map optimizations and truth-tables to come up with the optimized circuit that Synopsys produced?