{"id":16293,"date":"2021-06-28T14:18:02","date_gmt":"2021-06-28T18:18:02","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/?p=16293"},"modified":"2026-03-27T08:49:55","modified_gmt":"2026-03-27T12:49:55","slug":"runtime-checks-with-the-cast-method","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2021\/06\/28\/runtime-checks-with-the-cast-method\/","title":{"rendered":"Runtime checks with the $cast() method"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Verilog was always known for its lack of type checking, treating everything as just bits strung together into vectors and arrays. \u201cCompile it and find the problems at run-time.\u201d SystemVerilog introduced new types that require more discipline. If you are new to SystemVerilog, the $cast() method can be mysterious as it checks <span style=\"text-decoration: underline;\">values at runtime<\/span>, not <span style=\"text-decoration: underline;\">types at compile <\/span>time.<\/p>\n\n\n\n<p>This is the third post in a series on OOP and UVM. Here is the previous <a href=\"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2021\/06\/21\/verification-class-categories\/\">post<\/a> on Verification Class Categories.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Enumerated Type<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"856\" height=\"308\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/06\/3_1_traffic_light.png\" alt=\"Traffic light: red, yellow, green\" class=\"wp-image-16295\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/06\/3_1_traffic_light.png 856w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/06\/3_1_traffic_light-600x216.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/06\/3_1_traffic_light-768x276.png 768w\" sizes=\"auto, (max-width: 856px) 100vw, 856px\" \/><figcaption>Traffic light:  green, yellow, red<\/figcaption><\/figure>\n\n\n\n<p>An enumerated variable creates a new type that has a limited set of values, specified by named constants. That sounds boring \u2013 how can it help you? If you are modeling a traffic light, you could create an enumerated type for the three states. Make it one-hot so you can connect this type to a port that drives the three bulbs.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">typedef enum bit[2:0] {GREEN=3\u2019b001, YELLOW=3\u2019b010, RED=3b100} traffic_t;<\/pre>\n\n\n\n<p>Now your code has the abstract names GREEN, YELLOW, and RED instead of the magic numbers 3\u2019b001, 3\u2019b010, 3\u2019b100. Enumerated variables are strongly typed which means you can only assign an enum variable from a value of the same type. On the right side of the assignments of <strong>light<\/strong> and <strong>next_light <\/strong>are constants or variables of the <strong>traffic_t <\/strong>type. Here is a simple state machine with assignments.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">traffic_t light, next_light;\n\nalways_ff @(posedge clk or negedge reset_n) begin\n  if (! reset_n) \n    light = RED;                    \/\/ Reset to RED\n  else begin\n    case (light)                    \/\/ Specify the order of the light values\n      RED:     next_light = GREEN;\n      YELLOW:  next_light = RED;\n      GREEN:   next_light = YELLOW;\n      default: $error(\"Illegal light value %b\", light);\n    endcase\n    light &lt;= next_light;\n  end\nend<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Injecting Values<\/h2>\n\n\n\n<p>What if you have a 3-bit vector, <strong>v3<\/strong>, that you need to assign to the <strong>traffic_t <\/strong>enum called <strong>light<\/strong>? SystemVerilog won\u2019t let you directly assign it as that could put <strong>light <\/strong>in an unknown state such as 0, or 3\u2019b111. This type checking is done at compile time, so the following code won&#8217;t compile. Try it on your favorite simulator.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">traffic_t light;\nbit [2:0] v3 = 3'b010; \/\/ One-hot value, not traffic_t type\ninitial\n  light = v3;          \/\/ Gets compile error<\/pre>\n\n\n\n<p>You need a way to check that the value of <strong>v3 <\/strong>is one of the legal values for <strong>light<\/strong>, &#8216;b001 for GREEN, &#8216;b010 for YELLOW, and &#8216;b100 for RED. The SystemVerilog $cast() method performs this check for you. Here you are calling it like a task.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">initial\n  $cast(light, v3); \/\/ Check value of v3 at run time: compatible with traffic_t?<\/pre>\n\n\n\n<p>The order of the arguments is the same as the assignment: <em>destination <\/em>= <em>source<\/em>;<\/p>\n\n\n\n<p>The problem with this call is that if <strong>v3<\/strong> has a bad value, the simulator prints an cryptic error. Instead, call $cast() like a function and check its return value so you can print your own message.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">if (! $cast(light, v3))\n  $error(\"v3 value %b out of bounds for traffic_t\", v3);<\/pre>\n\n\n\n<p>Remember, $cast() checks the value on the right side, not the variable&#8217;s type. This can only be done at runtime. The following code has two identical calls to $cast(), yet they produce different results.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">v3 = YELLOW;      \/\/ Legal as enum values are a subset of bit[2:0]: 'b000-'b111\n$cast(light, v3); \/\/ Success, light = YELLOW\nv3++;             \/\/ v3 now is 'b011\n$cast(light, v3); \/\/ Run-time error:3\u2019b011 is not a legal value<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Venn Time<\/h2>\n\n\n\n<p>Look at a Venn diagram of the possible values. The variable v3 is 3 bits so it can hold &#8216;b000 &#8211; &#8216;b111, all the values shown below. The <strong>light <\/strong>variable can only hold &#8216;b001, &#8216;b010, or &#8216;b100, which are the inner box. So <strong>v3 <\/strong>holds a wider range of values than <strong>light<\/strong>, and $cast() makes sure that the current value of <strong>v3<\/strong> is inside the smaller set.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"515\" height=\"223\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/07\/3_2_Venn_3.png\" alt=\"\" class=\"wp-image-16318\"\/><figcaption>Venn diagram of v3 and light values<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>When you need to assign between two variables of different types, and the source might have a value incompatible with the destination, use $cast() to check the value. The check happens at runtime. If you want to give a helpful message, call $cast() as a function.<\/p>\n\n\n\n<p>Wait \u2013 this series is supposed to be on OOP and this post has no class. What gives? Next week I\u2019ll show the next concept, and all will be revealed. Thank you for your patience!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Verilog was always known for its lack of type checking, treating everything as just bits strung together into vectors&#8230;<\/p>\n","protected":false},"author":72251,"featured_media":16295,"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":[1,982,10],"tags":[300,951,950,952,461,462,953,751,775],"industry":[],"product":[],"coauthors":[942],"class_list":["post-16293","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","category-systemverilog","category-tips-tricks","tag-cast","tag-base-class","tag-class-variable","tag-derived-class","tag-enum","tag-enum-label","tag-extended-class","tag-systemverilog","tag-typedef"],"featured_image_url":"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/54\/2021\/06\/3_1_traffic_light.png","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16293","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\/72251"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/comments?post=16293"}],"version-history":[{"count":3,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16293\/revisions"}],"predecessor-version":[{"id":16354,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/16293\/revisions\/16354"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media\/16295"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=16293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=16293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=16293"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=16293"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=16293"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=16293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}