How to Write Safe Verilog: Become a PL Troll
danluu.com
danluu.com
I wonder what this has to say about type systems in general. Projects like Clojure's core.typed let you add static typing as a library where you feel like you need it, but then you don't get the benefit of statically checking everyone's code, all of the time. Perhaps a company policy on what functions need to be typed would do the trick, but at that point the compiler might as well enforce it for you.
Sorry for the stalking but you must realize you posted in a site called "hacker news"
Basically, you have to write everything in goto statements, no while's or for's. You also have to check that size always match, otherwise you will have errors. You also have to check that you do not accidentally drive one input from two outputs, otherwise you will also get errors.
As you discover errors through very slow simulation (small circuit takes about 4 days of simulation for measly 2 seconds and it stays about 60% of time idle, e.g., not doing much), you really need to face any possible errors ASAP.
Another option is code generation from some high level model, but then you can miss something important like critical path delay or latency (in clock ticks) and you have to bring that information into the model. While this can be done in Clojure or Python or something alike, it is not a panacea, not even close to that.
I wasn't very impressed precisely because it does not have flexible types and typechecking.
First, if you're going to have a statically typed language with no type declarations, how else are you going to do type checking? Sure, it's generally agreed that Hungarian warts are unnecessary in this day of tools (editors, IDEs, what have you) that will tell you what type a variable is in an instant, but if you're playing some silly game of "let's set arbitrary constraints to see how convoluted we can get", then you very well might come up with required Hungarian warts.
Second, if hardware programming is a place where static type checking would be a boon, could it not be said that any language which doesn't have it built in is less than ideal for the task? It's been a while since I've programmed in Verilog, but surely there must be other off the shelf tools (both OSS and otherwise) that would be better suited. Even if you stick with Verilog and go the route that the article describes, that's not trolling, that's just practicality.
This article is interesting in and of itself, and I'm glad to see it hit the front page, but the author could have left off the quote and not claimed to be a PL troll.
It's not "hardware programming". It's hardware design. It's no different from connecting raw gates and chips on a breadboard. This is a very important distinction that is often glossed-over in HN conversations.
Verilog is a tool with which you explicitly or by inference DESCRIBE hardware. You are not programming hardware. That's software.
At some level this concept of static types is nonsensical. You have registers made up of flip-flops that move data around from circuit block to circuit block. That's it. Data types, in many ways, are software constructs, they don't really exist in hardware.
One would not look at a breadboard full of chips or an old-school PCB with latch and flip-flop chips and discuss static data types. Maybe you'll talk about fixed with data busses that implement this or that encoding, but that's about it.
One could argue that a specialized floating point processor has a data type. That's one way to interpret it. Another way is to say that it has a, say, 64 bit architecture that, by convention, is interpreted in order to be able to represent floating point numbers within certain constraints. If by that we mean "static data type" then, well, I suppose I can go with that.
Yes, it is a bunch of flip-flops and gates, but in the end the interface with "empty" signal is different from interface without it. The same is for error signal.
To connect those sinks and sources properly you have to match types. E.g., you have to deal with the absence of "empty" on one end.
Otherwise you will surely make some obvious mistake.
And, finally, Avalon streaming interface is a tuple: type ASI a = (SOP, EOP, a) data SOP = NoSOP | SOP -- SOP and EOP equivalent to boolean data EOP = NoEOP | EOP
And parameter "a" can be anything - raw value without empty or error, tuple of value and empty, tuple of value and error, triple of value, empty and error. They all are different. Even if their connection is no-op, like inventing "always good" value for error field, this no-op should be specified.
Otherwise, you make discovery of the error very distant.
Source: being a PL troll :)
EDA tools vary in license costs, from a few thousand
dollars per machine license per year, to half a million
per core license per year. Timing tools aren’t all the way
at the top end, but they’re not cheap.
I have never in my life touched software this expensive. It's interesting to me how this warps workflows - e.g. automated testing tools can only test one build every two days, not because running in parallel is computationally expensive, but because licensing is too expensive in cash terms. Given the zero marginal costs (to software vendors) of existing customers running extra copies, this sounds completely insane to me.The world you're referring to is not 'virtual', it is solidly grounded in capital goods for production. At the costs of a typical spin the use of the software is a very very small fraction, and that fraction is gladly paid because it avoids unnecessary spins (think of a spin as an 'edit-compile-test' cycle, only with a price tag of a few hundred K on the low end to a few million and up on the high end).
The software you're talking about has 1000's of manyears and sometimes 10's of thousands or even higher numbers of manyears involved in writing, testing, debugging. The present day value of that investment is so large that it serves as a defensible moat against any upstart company entering the market with a competing product, and if they do they will likely end up pricing it the same or higher (once they have the bugs worked out...).
Open source works well for fields where there are 100's of thousands of potential users for something that you can build in a reasonable amount of time and which does not require extensive domain knowledge spread out over lots of individuals.
For software like this, specialized, very expensive to develop and with a limited audience licenses are still the way it is done and as far as I can see it's the only model that makes sense. The alternative, bespoke software would be far more expensive still, the licenses are at least affordable to those who need them.
Yes, this is better than requiring each hardware company develop their own. But maybe there are other solutions that still result in the tools being available, both to those who can currently afford it and to those who can't? A shorter copyright term seems like one step in that direction. Nationalize one of the firms and open source it, leading to both a lower priced alternative and greater price competition for the remaining?
I guess it's a question of what the goal is. I'd put global accessibility to the developed technology up very high, and presume that dropping the cost and barriers to entry for both the hardware and software firms would help this.
The narrower the field and harder the science, the fewer (and more expensive) candidates will be sufficiently competent to implement the software and the lesser audience for the software-publisher to recoup their RnD investment with, so prices tends to go up.
Once you need software to support engineering-disciplines not software, they know you will be able to pay the bill and find the software worthwhile compared to doing the same work manually with expensive engineers.
What's more of a challenge is trying to use techniques like continuous integration when your compile time is a week!
And your simulation time is another week.
And interpreting the results could be another week.
I've worked on designs where you can only do one iteration per day to on iteration per week. It really slows down development to a crawl.
You learn very quickly to segment designs and validate everything as far as humanly possible before even dreaming of simulating/compiling larger functional blocks.
These are ways in which modern hardware design is vastly different and vastly more expensive than any comparable software development workflow.
The cost of hardware tools is pretty much insignificant when you consider the entire process. Buying a $50,000 signal analyzer might save you weeks or months of development and debug time. You can't launch into these kinds of startups with a $15K investment over a summer.
I worked in an EDA startup for a decade before we were bought by Cadence. Getting people to evaluate our tool generally took a few months of a technical presales person's time. We only ever acquired a few dozen customers: there aren't all that many ASIC companies. Most required at least one custom feature. Therefore there's an elaborate commercial negotiation to take as much money as possible from the customer in order to amortize the R&D.
Given manufacturing fixed costs of $250k, spending $250k on software to get it right starts to look reasonable.
How else are you supposed to get I/O from one module to another, say a 32bit data bus? Also, what's the definition of high speed here?
"unless you like random errors"
And very hard to diagnose errors until you realize that you messed up your clock domains.
Perhaps the most important thing you can get away with? Errors. Reprogramming an FPGA takes three minutes; manufacturing a new ASIC takes three months and three million dollars (or something along those lines). So dot your i's and cross your t's, baby.
I believe the answer in this case is you latch the signal, and use a local copy. Sort of like how it is good practice to use local variables when coding.
what's the definition of high speed
Last I heard, 100MHz+
So the latch is local to both, and therefore not using a signal from another module?
sub proc {
my $latch = @_[0];
}
We capture the input signal in $latch for local use in the procI can see the sourcing issue when trying to fan out too much from a single module, but I don't see any issue doing a high speed interconnect between them as long as you're intelligent about where the modules are going to be placed in regards to chip I/O. i.e. don't have a high speed serdes unit on one bank try and directly talk to a bank on the other side of a chip.
It is a placement/distance problem. Sometimes one module needs to talk to a module on the other side of the chip, and there's no two ways about it. In that case, when you clock it fast enough, you need to break the path across cycles.
edit: It looks like BUF is indeed the Xilinx primitive for a buffer, so no. Definitely not what I meant.
Half-cocked Example:
module test ( a, clk );
input a; input clk;
wire a; wire clk;
reg flop;
always @ (posedge clk)
begin
flop = a;
end
(... useful things ...)
endmoduleFor ASIC work there are a couple of tools used these days: http://www.cadence.com/products/mfg/tempus/pages/default.asp...
http://www.synopsys.com/Tools/Implementation/SignOff/Pages/P...
Electronic Design Automation is a tough market to crack - for most startups the exit strategy is to be bought by one of the 2 (or 3) big players without being sued by them first!
Somewhere here I saw a comment saying that you must time your design taking in account the logic delay or will get weird errors, but that's impossible. The tool chain (both quartus and Xilinx ISE) will report the max clock speed with a big bold red font if you try to go faster.
There's a step in every design flow called DRC (Design rule-checker), basically a bunch of warnings if you do dumb things with anything including the high-speed transcievers. You must pay attention to the warnings.
Neverd did any ASIC but I know they have about 10X the testing and simulation that FPGA have. I would believe you don't get random errors if you follow the standard design flow and tests.
In ASIC, or FPGA? With FPGA, you're probably right. With ASIC, it will depend on your goals. For example, I'm not aware of an industry standard methodology for accounting for the timing impact of localized supply droop. I believe that's something you have to cook up yourself.
My spouse designs CPUs for a major CPU manufacturer (you've used them). She is responsible for physical design for one tile (there are many tiles, each of which has other physical designers). Her single tile, by itself, is substantially larger than almost all ASIC designs in the world today. At that scale, most of the standard FPGA design tools don't even work. Designing in that space is substantially different than FPGA or even ASIC design.
Concepts such as modules don't translate directly into the software world. A module is a grouping of circuit elements. The criterial for grouping them can be varied. One typically creates modules for functional blocks that are easy to plug into the overall circuit. And, much like a subroutine, the other motivation is when one must use the circuitry multiple times. The difference is that a subroutine is called and exited. A module instantiation creates real and permanent circuitry on the chip (ignoring FPGA reconfiguration techniques).
I've been working with HDL's for quite some time. Frankly, every attempt I've seen to get away from hardware development and making it look like software development is crippled in some way or another. I equate this to the idea of, for example, tools that allow you to write mobile apps using something other than the native language and framework of the platform. It works. Until it doesn't.
As far as the article is concerned, no issues with any of it. It's an interesting approach. That said, I've never used anything similar to this and can't remember the last time I had such problems. This isn't criticism. Just one data point.
This is hardly official and not a perfect analogy but github is to software devs as opencores.org is to FPGA devs. Thats why when you go to github and search for Verilog and only get 259 hits for stuff written in Verilog you're going to the wrong place.
The other FAQ is verilog looks like C because C looks like the incredibly orthogonal PDP-11 addressing modes chart. So pretty much if you can imagine it as an addressing mode, the PDP-11 could do it, so thats explains the weird compatibility between something that looks like C and something that can define the hardware of a CPU. Its not a perfect analogy but it kind of describes why the HDL look very C like rather than Ruby like, for example. If you could build it out of basic logic gates in 1970 using TTL chips, its probably supported by the old PDP-11 and therefore in C.
Finally you need a FAQ for old timers that home-scale FPGA / CPLD stuff has collapsed in price over the last decade or two. Yes, in 1990 you needed four figures to do anything so no one did anything at home. Now you need at minimum a $50 board and a (multi-gig) free download. Its maybe 3dB more expensive than fooling around with arduino stuff. The small scale stuff doesn't scale well to larger stuff; I think its "weird" when a simple gray code decoder or quadrature decoder takes a minute to synth, so yes doing a complete CPU does take a long time to synth even on fairly high end hardware. Back to the old days of batch computing, sorta.
The minute you get into the hundreds of MHz and into GHz and thousand pin devices you've entered a domain that is far away from what casual hackers can handle.
Yet, I do agree with you. Today, free compilers from Xilinx and Altera support devices that ten years ago required their multi-thousand dollar suites. Free or low-cost PCB design tools are out there. All of this of course, comes with compromises. Free simulation tools don't compare to paid tools. Free and low cost EDA software packages don't have all the tools you really need to efficiently manage high speed design of complex boards with larger devices. Signal integrity alone has dedicated (and very expensive) tools that you almost can't do without in certain domains.
None of this is to say that it is impossible for someone to play with the technology but it certainly ain't like playing with software.
Also, I really don't understand what the author meant by "PL troll". Writing static code checkers is trolling nowadays?
Not sure if I agree here, at least in these absolute terms. Sometimes you cannot afford to unnecessarily capture every I/O signal, and it is indeed not always necessary.
I am not sure if a static checker meant 'lint' but Verilog writer can be better being good at static check and static checker at next end.