{"id":89,"date":"2014-10-20T20:29:11","date_gmt":"2014-10-21T04:29:11","guid":{"rendered":"http:\/\/www.beyond-circuits.com\/wordpress\/?p=89"},"modified":"2021-01-18T14:42:01","modified_gmt":"2021-01-18T22:42:01","slug":"a-verilog-preprocessor","status":"publish","type":"post","link":"https:\/\/www.beyond-circuits.com\/wordpress\/2014\/10\/a-verilog-preprocessor\/","title":{"rendered":"A Verilog Preprocessor"},"content":{"rendered":"<h2>A long time ago&#8230;<\/h2>\n<p>When I used to work at Silicon Engineering in the nineties, I wrote a Verilog preprocessor using Perl. Verilog &#8217;95 is pretty limited in what it can do, so we used this preprocessor on our projects to enhance our Verilog code. Back in the Verilog &#8217;95 days, we used to write every RTL file as a preprocessor file and used GNU Make to convert it into pure Verilog. What with Verilog 2005 and System Verilog, these days I only use this preprocessor when necessary. But that&#8217;s still pretty often.<\/p>\n<h2>The trick<\/h2>\n<p>The cool thing about this preprocessor is that it does very little of the work on its own. It can be used in place of the standard Verilog preprocessor\u2013 which is well and good if you need that type of thing, but it&#8217;s still pretty limited. After all, you already have something that does that. This preprocessor&#8217;s neat trick is that you can embed Perl code inside your Verilog code. What the preprocessor does, essentially, is it converts the input code into a perl program which, when run, prints the input code. Now, by itself that is kind of boring. However the preprocessor allows you to use special comments to drop out of this mode and embed Perl code.<\/p>\n<h2>A simple example<\/h2>\n<p>One simple example of what you can do is to build a table to use in your Verilog module. In my CORDIC module, I needed a table of arctan values. This table is static and doesn&#8217;t ever need to change. All I needed was one entry in the table for each pipeline stage in the CORDIC. The table takes the pipeline stage number as input and returns a 64-bit value as the result. I implemented this as a function which is basically just a big case statement. You can see the special comment is wrapped in a \/*@ and @*\/ pair. I chose these because they are real Verilog comments so they won&#8217;t mess up editors that know how to edit Verilog (like Emacs). Once you drop into Perl mode, anything that your Perl code writes to standard output will appear in the preprocessor output. Here is the input to the\u00a0preprocessor:<\/p>\n<pre><code>   function [63:0] k_table;\n      input [5:0] index;\n      begin\n\t case(index)\n\/*@\n  $k = 1;\n  for my $i (0..63)\n    {\n      $k *= cos(atan2(1,2**$i));\n      printf \"%8d: k_table = 64'd%s; \/\/ %.20e\\n\",$i,int($k*2**64+.5),$k;\n    }\n @*\/\n\t   default: k_table = 0;\n\t endcase\n      end\n   endfunction\n<\/code><\/pre>\n<h2>Interpolation<\/h2>\n<p>Code enclosed within the \/*@ and @*\/ pairs, or prefixed with the \/\/@ comment, is just copied into the output Perl program. Other lines are just printed by the Perl program, which means\u00a0you can use Perl string interpolation on those lines. Here&#8217;s a rather contrived example:<\/p>\n<pre><code>\/\/@ my $reset_style = \" or negedge clk\";\nalways @(posedge clk $reset_style)\n  q &lt;= d;\n<\/code><\/pre>\n<p>In this example, the Perl <code>reset_style<\/code> variable is used in the verilog code without needing to drop into the more cumbersome comment syntax. This can help make your code a lot more readable. I have a library that I commonly use which defines a bunch of variables. These variables match the Verilog system tasks and functions that begin with a dollar sign ($). This way, you can say <code>$display<\/code>\u00a0and the preprocessor will expand the Perl variable <code>display<\/code>\u00a0(which, by the way, conveniently has the value <em>$display<\/em>.)<\/p>\n<h2>Other Possibilities<\/h2>\n<p>I also write a lot of structured documentation for my designs using XML. By using the XML::LibXML library I can read the XML documentation from my Verilog code and parse that for information that drives the RTL code generation. So I can document registers, instruction sets, interrupts, or other types of information, and then that do generate my verily code.<\/p>\n<h2>Useful Links<\/h2>\n<ul>\n<li>vpp.pl\u00a0<a title=\"vpp.pl\" href=\"https:\/\/www.beyond-circuits.com\/wordpress\/vpp-pl-man-page\/\">man page<\/a> and <a href=\"https:\/\/www.beyond-circuits.com\/repos\/common\/trunk\/bin\/vpp.pl\">perl code<\/a>.<\/li>\n<li>Vpp.pm <a title=\"Vpp.pm\" href=\"https:\/\/www.beyond-circuits.com\/wordpress\/vpp-pm\/\">man page<\/a> and <a href=\"https:\/\/www.beyond-circuits.com\/repos\/common\/trunk\/lib\/Vpp.pm\">perl library<\/a>.<\/li>\n<\/ul>\n<p>Look for more posts using this technique soon.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A long time ago&#8230; When I used to work at Silicon Engineering in the nineties, I wrote a Verilog preprocessor using Perl. Verilog &#8217;95 is pretty limited in what it can do, so we used this preprocessor on our projects &hellip; <a href=\"https:\/\/www.beyond-circuits.com\/wordpress\/2014\/10\/a-verilog-preprocessor\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,4],"tags":[],"class_list":["post-89","post","type-post","status-publish","format-standard","hentry","category-tools","category-verilog"],"_links":{"self":[{"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/posts\/89","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/comments?post=89"}],"version-history":[{"count":11,"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/posts\/89\/revisions"}],"predecessor-version":[{"id":1346,"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/posts\/89\/revisions\/1346"}],"wp:attachment":[{"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/media?parent=89"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/categories?post=89"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.beyond-circuits.com\/wordpress\/wp-json\/wp\/v2\/tags?post=89"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}