{"id":15848,"date":"2021-02-16T16:38:42","date_gmt":"2021-02-16T21:38:42","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/?p=15848"},"modified":"2026-03-27T08:46:40","modified_gmt":"2026-03-27T12:46:40","slug":"systemverilog-syntax","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2021\/02\/16\/systemverilog-syntax\/","title":{"rendered":"The Semantics of SystemVerilog Syntax"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large is-resized\"><a href=\"https:\/\/ieeexplore.ieee.org\/document\/8299595\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/07\/SystemVerilog-.png\" alt=\"SystemVerilog\" class=\"wp-image-14674\" width=\"185\" height=\"122\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/07\/SystemVerilog-.png 1024w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/07\/SystemVerilog--600x396.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/07\/SystemVerilog--768x506.png 768w\" sizes=\"auto, (max-width: 185px) 100vw, 185px\" \/><\/a><\/figure><\/div>\n\n\n\n<p class=\"has-text-align-left\">Trying to grasp any programming language from scratch can be a difficult task, especially when you start by reading the Language Reference Manual (LRM). The<a href=\"https:\/\/ieeexplore.ieee.org\/document\/8299595%5DIEEE\" target=\"_blank\" rel=\"noopener\"> <\/a><a href=\"https:\/\/ieeexplore.ieee.org\/document\/8299595\" target=\"_blank\" rel=\"noopener\">SystemVerilog<\/a><a href=\"https:\/\/ieeexplore.ieee.org\/document\/8299595%5DIEEE\" target=\"_blank\" rel=\"noopener\"> LRM <\/a>is 1315 pages. For comparison, the <a href=\"https:\/\/www.iso.org\/standard\/74528.html\" target=\"_blank\" rel=\"noopener\">C(2018) LRM<\/a> is 520 and the <a href=\"https:\/\/www.iso.org\/standard\/79358.html\" target=\"_blank\" rel=\"noopener\">C++(2020) LRM<\/a> is 1853 pages.&nbsp; LRMs are not written to teach one how to learn a language; they are mainly worded for people writing tools to be compliant with the standard. Although there are a number of additional resources for learning SystemVerilog, this post tackles one key aspect of the SystemVerilog usually left out: the BNF.<\/p>\n\n\n\n<h2 class=\"has-cyan-bluish-gray-color has-text-color wp-block-heading\">Backus-Naur Form<\/h2>\n\n\n\n<p>Syntax is a set of formal grammar rules, expressed in metalanguage called <a href=\"https:\/\/en.wikipedia.org\/wiki\/Backus\u2013Naur_form\" target=\"_blank\" rel=\"noopener\">Backus-Naur Form<\/a> (BNF), listed in Annex A of the SystemVerilog LRM. Since the creation of ALGOL, considered the ancestor of most modern programming languages, the BNF is used by compilers of many tool chains to determine what each token in the source code represents (i.e., keyword, identifier, operator, string, comment). And all the possible legal groupings of tokens are given names called \u201cproductions\u201d.<\/p>\n\n\n\n<p>Semantics is everything that happens after the source code is parsed. Does the compiler understand how to implement what it just parsed? Does what you have written violate some use pattern deemed too unsafe to implement? You can have illegal code with legal syntax, but you cannot have legal code without legal syntax. Syntax allows you to write <code>!A<\/code>, but semantics will not allow it if <code>A<\/code> is a real number.<br>Say we see the piece of code below, assuming A, B, and C have already been declared as integral variables:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>A &lt;= B &lt;= C;<\/code><\/pre>\n\n\n\n<p>There could be different ways of interpreting this code depending on the context of the location of this code. As a <em>statement<\/em> it would be interpreted as \u201ca non-blocking assignment to A with the expression B less than or equal to C\u201d. As a constraint expression, this would be interpreted as \u201cthe result of A less than or equal to B must be less than or equal to C\u201d. If we saw that same piece of code with more context:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>always @(posedge clk) begin\n    A &lt;= B &lt;= C; \nend<\/code><\/pre>\n\n\n\n<p>the BNF rules, by position of all the tokens, determines that the first <strong>&lt;=<\/strong> is a&nbsp;<em>non-blocking<\/em> <em>assignment <\/em>operator, and the second <strong>&lt;=<\/strong> is a&nbsp;<em>less-than or equal to&nbsp;<\/em>operator. If we assume the <code>always<\/code> is in the proper location within a module, we can start looking for a matching production in the BNF.<\/p>\n\n\n\n<pre class=\"wp-block-verse\"><em>always_construct ::= always_keyword statement\nalways_keyword ::= <\/em><span class=\"has-inline-color has-vivid-red-color\">always<\/span> | <span class=\"has-inline-color has-vivid-red-color\">always_comb<\/span> | <span class=\"has-inline-color has-vivid-red-color\">always_latch<\/span> | <span class=\"has-inline-color has-vivid-red-color\">always_ff<\/span><em>\nstatement ::= [ block_identifier <\/em><span class=\"has-inline-color has-vivid-red-color\">:<\/span><em> ] { attribute_instance } statement_item\nstatement_item ::=\nblocking_assignment ;\n      | nonblocking_assignment ;\n      | procedural_continuous_assignment ;\n      | inc_or_dec_expression ;\n      | procedural_timing_control_statement\n      | seq_block\n      |\u2026 [14 more productions]<\/em><\/pre>\n\n\n\n<p>The<em> always_construct <\/em>production lets the parser know that SystemVerilog allows an <em>always_keywor<\/em>d production followed by a single <em>statement<\/em> production. The <em>always_keyword<\/em> production lists four possible keywords that could start an <em>always_construct<\/em>. Then the parser looks through the 20 possible productions for a statement_item and finds a match with <code><span class=\"has-inline-color has-vivid-red-color\">@<\/span>(posedge)<\/code> as a procedural timing control statement<\/p>\n\n\n\n<pre class=\"wp-block-verse\"><em>procedural_timing_control_statement ::=\nprocedural_timing_control statement_or_null<\/em><\/pre>\n\n\n\n<p>If you follow <em>statement_or_null <\/em>production, you notice that it recurses back to a <em>statement<\/em>. That is what allows you to write a series of timing controls before any procedural statement. Then the parser comes to the <code><span class=\"has-inline-color has-vivid-red-color\">begin<\/span><\/code> keyword, which is a sequential block statement.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-verse\"><em>seq_block ::= \/\/ from A.6.3\n<\/em><span class=\"has-inline-color has-vivid-red-color\">begin<\/span><em> [ <\/em><span class=\"has-inline-color has-vivid-red-color\">: <\/span><em>block_identifier ] { block_item_declaration } { statement_or_null }\n<\/em><span class=\"has-inline-color has-vivid-red-color\">end<\/span><em> [ <\/em><span class=\"has-inline-color has-vivid-red-color\">:<\/span><em> block_identifier ]<\/em><\/pre>\n\n\n\n<p>From this we see a <code>begin\/end<\/code> block can take an optional <em>block_identifier<\/em>, 0 or more <em>{block_item_declaration}<\/em>, followed by 1 or more<em> { statement_or_null }<\/em>. By the way, this BNF rule dictates that declarations must come before any procedural statements. You cannot have declarations in the middle of a set of procedural statements.\u00a0<\/p>\n\n\n\n<p>Finally, we get down to the parsing of the variable <code>A<\/code>, which matches 3 of the 20 available productions for a statement: a <em>blocking_assignment<\/em>, <em>nonblocking_assignment<\/em>, or an inc_<em>or_dec_expression<\/em>. The next token <code>&lt;=<\/code> only matches one production:<\/p>\n\n\n\n<pre class=\"wp-block-verse\"><em>nonblocking_assignment ::=\nvariable_lvalue <\/em><span class=\"has-inline-color has-vivid-red-color\">&lt;= <\/span><em>[ delay_or_event_control ] expression<\/em><\/pre>\n\n\n\n<h2 class=\"has-cyan-bluish-gray-color has-text-color wp-block-heading\">Compiler Errors<\/h2>\n\n\n\n<p>Syntax errors occur when the compiler can&#8217;t find a match in the BNF for what you wrote in your source code. If you wrote <code>A =&gt; B<\/code>, there is no rule in the BNF determining what that is supposed to represent. And it makes it extremely difficult to parse any code after the first syntax error because it has to throw out all the tokens it could not match. The token that follows it could be part of the statement that had the error or could be the start of a new statement.&nbsp;<\/p>\n\n\n\n<p>Semantic errors come at a later stage when the compiler knows what you wrote, but other rules in the LRM prevent it from being legal. For example, if it turned out that <code>B<\/code> and <code>C<\/code> were class variables, that would be a semantic error and would be reported much later in compilation. Because of parameterization, sometimes the error cannot be generated until the final elaboration of the design.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignright size-large is-resized\"><a href=\"https:\/\/2021.dvcon.org\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/2021.dvcon.org\/sites\/dvcon21\/files\/images\/logos\/dvcon2021_us_logo-01.svg\" alt=\"\" width=\"192\" height=\"126\"\/><\/a><\/figure><\/div>\n\n\n\n<h2 class=\"has-cyan-bluish-gray-color has-text-color wp-block-heading\">DVCon<\/h2>\n\n\n\n<p>That&#8217;s it for just one small aspect of working with SystemVerilog. Hope to meet you on-line at DVCon 2021 when I&#8217;ll be chairing a number of sessions and presenting my paper on &#8220;The Life of SystemVerilog Variables&#8221;.<\/p>\n\n\n\n<h2 class=\"has-cyan-bluish-gray-color has-text-color wp-block-heading\">Exercise<\/h2>\n\n\n\n<p>Here is an exercise for you to work on yourself:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>module top;\n  \n  logic A;\n  logic &#91;7:0] B=3;\n  \n  initial begin\n    A = |~B;   \/\/ illegal\n    A = |(~B); \/\/ legal with parenthesis\n    #B;        \/\/ legal\n    #B++;      \/\/ illegal\n    #(B++);    \/\/ legal with parenthesis\n  end\nendmodule\n<\/code><\/pre>\n\n\n\n<p>Question: Why are the above statements illegal without parentheses made legal by adding ()\u2019s.<\/p>\n\n\n\n<p>Hint: Start with <em>expression<\/em> and <em>delay_control<\/em> in the BNF.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Trying to grasp any programming language from scratch can be a difficult task, especially when you start by reading the&#8230;<\/p>\n","protected":false},"author":71689,"featured_media":14674,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spanish_translation":"","french_translation":"","german_translation":"","italian_translation":"","polish_translation":"","japanese_translation":"","chinese_translation":"","footnotes":""},"categories":[5,7,1],"tags":[442,533,540,690,751,819,831],"industry":[],"product":[205],"coauthors":[],"class_list":["post-15848","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-events","category-learning-resources","category-news","tag-dvcon","tag-ieee-1800","tag-ieee-sa","tag-rtl","tag-systemverilog","tag-verification","tag-verilog","product-questa"],"featured_image_url":"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2020\/07\/SystemVerilog-.png","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/15848","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/users\/71689"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/comments?post=15848"}],"version-history":[{"count":5,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/15848\/revisions"}],"predecessor-version":[{"id":15928,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/15848\/revisions\/15928"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media\/14674"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=15848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=15848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=15848"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=15848"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=15848"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=15848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}