ハードウェア実験 SystemVerilogのコード断片

メモ書き程度。

ファイル読み込み関数

input.txt, output.txtの、相対パスの起点は、デフォルトでは[project_name].sim/sim_1/behav/'です。


`timescale 1 ns / 100 ps

module marisa ();
   // variables
   string input_name = "input.txt";
   string output_name = "output.txt";
   logic [31:0] in_descriptor, out_descriptor, code, data, plus_one_data;

   initial begin
      // open input & output file
      // this shoud be a blocking assignment
      in_descriptor  = $fopen(input_name, "r");
      out_descriptor = $fopen(output_name, "w+");
      if ($signed(in_descriptor) == $signed(32'd0))
        $display("Could not open file: %s", input_name);
      else if ($signed(out_descriptor) == $signed(32'd0))
         $display("Could not open file: %s", output_name);
      else begin
         // read and write loop
         while ((code = $fscanf(in_descriptor, "%h", data)) != 31'd0) begin
            // `plus_one_data' is updated 10s after updating `data'
            // this should be a blocking assignment, too
            plus_one_data = #10 data + 1'b1;
            $fdisplay(out_descriptor, ">: %h, %d", plus_one_data, code);
         end
         $display("end of file");
      end

      // DO NOT forget this
      $fclose(in_descriptor);
      $fclose(out_descriptor);
   end
endmodule
        

クロック生成器モジュール

initialforever文を使うベーシックなタイプ。

わざわざモジュールにする必要はないが、一応...


`timescale 1 ns / 100 ps

module aya (output logic clk);
   initial clk <= 1'b0;
   initial forever #5 clk <= ~clk;
endmodule
        

モジュールの使い方

ポートとシグナルを繋ぐ。インスタンス名、ポート名、信号名の場所が勘違いしやすい?


`timescale 1 ns / 100 ps

module momiji ();
   logic clock_signal;
   // module_type instance_name port_connection
   // explicit connection
   // connect clock_signal(variable) to clk(port)

   aya clock_instance (.clk(clock_signal));
endmodule
        

SystemVerilog版Hello, World

...ようこそ。


`timescale 1 ns / 100 ps

module reimu ();
   logic [31:0] this_year = 32'd2016;
   // initial block
   // executed at the time ZERO
   initial $display("Hello, HW Jikken %d!", this_year);
endmodule
        

Find First One

最初の1bit目をみつけるモジュール。DEPTH=5の場合、5段のシフターと、カウンターの組み合わせのデイジーチェーン(数珠つなぎ)になります。for文を使う際には、どのような段数の回路になるのかイメージしましょう。


`timescale 1 ns / 100 ps

// find first one
module sakuya
  #(DEPTH = 5)
   (input logic [2**DEPTH-1:0] target, output logic [DEPTH:0] count);

   logic [2**DEPTH-1:0] shiftreg = 0;
   logic [2**DEPTH-1:0] mask;

   always_comb begin
      count = 0;
      shiftreg = target;
      mask = ~0;
      for (int i = DEPTH - 1; i >= 0; i--) begin
         mask = mask << (2**i);
         if (!(shiftreg & mask)) begin
            count = (2**i) + count;
            shiftreg = shiftreg << (2**i);
         end
      end
   end // always_comb

endmodule
        

バレルシフター

右シフター、アンダーフローつきです。for文を使わずに行うと、こういう感じになります。


`timescale 1 ns / 100 ps

// Simple Barrel Shifter (with underflow flag)
module meiling (input logic [31:0] value,
                input logic [4:0]   shift,
                output logic [31:0] shifted_value,
                output logic        underflow);

   logic [31:0]                     shifted1, shifted2, shifted3, shifted4;
   logic [15:0]                     under1;
   logic [7:0]                      under2;
   logic [3:0]                      under3;
   logic [1:0]                      under4;
   logic                            under5;

   assign shifted1 = (shift & 5'h10) ? {16'h0000, value[31:16]} : value;
   assign shifted2 = (shift & 5'h08) ? {8'h00, shifted1[31:8]} : shifted1;
   assign shifted3 = (shift & 5'h04) ? {4'h0, shifted2[31:4]} : shifted2;
   assign shifted4 = (shift & 5'h02) ? {2'h0, shifted3[31:2]} : shifted3;
   assign shifted_value = (shift & 5'h01) ? {1'h0, shifted4[31:1]} : shifted4;

   assign under1 = (shift & 5'h10) ? 16'hffff & value[15:0] : 'h0;
   assign under2 = (shift & 5'h08) ? 8'hff & shifted1[7:0] : 'h0;
   assign under3 = (shift & 5'h04) ? 4'hf & shifted2[3:0] : 'h0;
   assign under4 = (shift & 5'h02) ? 2'h3 & shifted3[1:0] : 'h0;
   assign under5 = (shift & 5'h01) ? 1'h1 & shifted4[0] : 'h0;

   assign underflow = (|under1) | (|under2) | (|under3) | (|under4) | under5;

endmodule