2024年3月3日日曜日

raspberry pi : 固定IPアドレスにする (dhcpcd.conf が無い場合)

目的:

nmcli を使用して 固定IPアドレス を設定する。

背景:

Raspberry pi 5 で 固定IPアドレスを設定しようとしたところ、 /etc/dhcpcd.conf が存在しなかった。
OS の バージョンが bookworm になって 設定方法が変わった模様。

手順:

NetworkManager (nmcli) を使用して設定を行う。
設定は
  1. コマンドで設定する。
  2. 設定ファイルを編集して設定する。

のどちらでも可能。
nmcli の コマンド は コマンドが補完できるまで短縮可能 
例 : nmcli connection show   →   nmcli c s

1.コマンドで設定。

  1. 接続名の確認
    nmcli connection show
    で 接続名を確認
    NAME           UUID                                  TYPE      DEVICE 
    有線接続 1     xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  ethernet  eth0   
    preconfigured  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  wifi      wlan0  
    lo             xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  loopback  lo
    
    以降、設定等で 接続名(NAME)を使用するが、接続名 が日本語(2バイトコード) や スペース が含まれている場合は " (ダブルコーテーション) で括って使用する。
    但し、認識できない等の不具合を発生する場合も在りうるため、1バイトコードに変更した方が良い。(手順は こちら )

  2. IPv4 IPアドレス等を設定する
    IPアドレス
    sudo nmcli connection modify [接続名] ipv4.addresses "xxx.xxx.xxx.xxx/24"
    デフォルトゲートウェイ
    sudo nmcli connection modify [接続名] ipv4.gateway "xxx.xxx.xxx.xxx"
    DNS
    sudo nmcli connection modify [接続名] ipv4.dns "xxx.xxx.xxx.xxx"
    (DNS の IPアドレスは スペースで区切って 複数指定可能 )

  3. IPアドレス を 手動設定に変更する。
    sudo nmcli connect modify [接続名]  ipv4.method manual
    この設定は、IPアドレスの設定を行った後に行わないとエラーとなる。

  4. 反映
    sudo nmcli con up eth0

2. 設定ファイルを編集して設定。

設定ファイルは 以下となる。(接続名毎に設定ファイルがある)
/etc/NetworkManager/system-connections/[接続名].nmconnection
  1. 接続名の確認
    nmcli connection show
    で 接続名を確認

  2. 設定ファイルを編集 設定ファイルの IPv4 の部分を書き換える。(br />
    hidden=false
    [ipv4]
    method=auto
    [ipv6]
    hidden=false
    [ipv4]
    address1=[IPアドレス]/24,[ゲートウェイアドレス]
    dns=[DNSアドレス1;DNSアドレス2];
    method=manual

    [ipv6]

  3. 反映
    sudo nmcli connection reload
    sudo nmcli con up preconfigured

* 接続名を変更する

接続名の変更は、古い接続名を削除して新しい接続名を追加することで行う。
接続名が日本語(2バイトコード) の場合、1バイトコードに変える。

  1. 接続名が日本語の接続を切断する
    sudo nmcli connection delete [UUID]
  2. 新しい接続名で接続を追加する
    sudo nmcli connection add type ethernet ifname [デバイス名] con-name [接続名]


2023年11月19日日曜日

raspberry pi : FANをPWM制御する (C言語)

目的:

ラズベリーパイのFAN (PWM制御対応のFAN> を PWM 制御 する。

背景:

ラズベリーパイのケースについているFAN から音が出るようになった。
(5V ファン を 3.3V 駆動 )
この為、PWM制御対応の5V FAN を購入し、説明書通り、/boot/config.txt に
dtoverlay=gpio-fan,gpiopin=18,temp=55000
を追加したところ、 指定温度 (55℃) 以上 で ON, 未満で OFF となり、FAN が 定期的に 全力回転 していた。(PWM制御ではなく、 ON/OFF 制御 )
この為、PWM制御 (回転数制御) できるようにする。

概要

PWM制御については、「C言語で LED 調光 (pigpio を使用した PWM 制御) 」を参照。
pigpiod(デーモン)を使用した hardware_PWM (ユーザ権限で実行可能) を使用し、指定温度範囲で 段階的に FAN回転数 を変える様にする。
尚、コード作成は C言語 で行う。

構成

raspberry pi : raspberry pi 4
FAN : PWM制御端子付き の 5V FAN
使用 GPIO : 18 pin


PWM FAN 制御用コード

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pigpiod_if2.h>

int get_temp(void) {
  static int tmp = 0;
  FILE *fp;
  char rdt[16];

  fp = fopen("/sys/devices/virtual/thermal/thermal_zone0/temp","r") ;
  if (fp != NULL ) {
    fgets(rdt,16,fp) ;
    fclose(fp);
    tmp = atoi(rdt) / 1000 ;
  }

  return tmp ;
}

void usage(void)
{
  printf("Usage: pigpio_pwnfan [option]\n");
  printf("\n");
  printf("  option\n (default)") ;
  printf("    -l n ... Low temperature (50)    'C\n");
  printf("    -h n ... hi  temperature (60)    'C\n");
  printf("    -p n ... PWM output pin  (18)    12/18(ch0) or 13/19(ch1)\n");
  printf("    -f n ... PWM Frequency   (10000) Hz\n");
  printf("\n");
}

int main(int argc, char **argv) {
  int gpio_pin = 18;      // hardware PWM Pin
  int pwm_freq = 10000;   // hardware PWM frequency
  int pwm_duty = 0 ;      // hardware PWM duty
  int tmp_low  = 50;      // cold temperature
  int tmp_hi   = 60;      // hot temperature
  int temp     = 0 ;      // detect twmperature
  int pi       = 0 ;
  int opt      = 0 ;

  // command line option 
  while ((opt = getopt(argc, argv, "l:h:p:f:")) != -1) {
    switch (opt) {
      case 'l':
        tmp_low = atoi(optarg);
        break;
      case 'h':
        tmp_hi  = atoi(optarg);
        break;
      case 'p':
        switch((gpio_pin = atoi(optarg))) {
          case 12:
          case 13:
          case 18:
          case 19:
            break;
          default:
            usage();
            exit(1);
        }
        break;
      case 'f':
        pwm_freq = atoi(optarg);
        break;
      default:
        printf("\n");
        usage();
        exit(1);
    }
  }

  if (tmp_low >= tmp_hi)
  {
    usage();
    exit(1);
  }


  // pigpio start
  pi = pigpio_start(0,0) ;
  if (pi<0) {
    printf ("pigpio start error !!") ;
    exit(1) ;
  }

  // PWM control
  while (1)
  {
    temp = get_temp();
    if (temp <= tmp_low) {
      pwm_duty = 0;
    } else if(temp >= tmp_hi) {
      pwm_duty = 1000000 ;       // 100%
    }else {
      pwm_duty = ((temp - tmp_low) * 1000000) / (tmp_hi - tmp_low) ;
    }

    hardware_PWM(pi,gpio_pin, pwm_freq, pwm_duty) ;

    sleep(10);
  }


  return 0;
}

コード概要

  1. get_temp(void)
    raspberry pi のCPU温度を取得する。
    温度の取得は /sys/devices/virtual/thermal/thermal_zone0/temp を読み込む事で行う。
  2. usage(void)
    オプション不正時の書式の表示を行う。
  3. main(int argc,char **argv) PWM FAN 制御 本体。
    1. command line option 解析部分 getopt を して オプションの解析を行う。
      unistd.h をインクルードする必要がある。
      -l : 下限温度。この温度より下は FAN停止。(省力時 50℃) -h : 上限温度。この温度より上は FAN全速。(省略時 60℃) -p : GPIO PIN番号。12/18(ch0) 又は 13/19(ch1) (省略時 18) -f : PWM 周波数 (省略時 10000 (10KHz) )
  4. pigpio start pigpio_start(0,9) (pigpio の 初期化) を実行。 戻り値が負の場合、異常終了。
  5. PWM control PWM 制御 本体。 設定温度の間、検出温度の応じてデューティを 0~100% の間で変化させる。 無限ループで、 温度の取得, PWM 設定 を行った後、10秒間 スリープする。 ( 10秒間隔で PWM制御 )

コンパイル

gcc -Wall -pthread -o pigpio_pwmfan pigpio_pwmfan.c -lpigpiod_if2 -lrt

実行

pigpiod 開始

sudo systemctl enable pigpiod.service
sudo systemctl start pigpiod.service

実行 (動作確認)

pigpio_pwmfan&
で実行し、FAN がPWM制御されていること(全速でないこと)を確認する。

停止

作成した FAN制御プログラムは サービスとして実行するため、動作確認で実行したプロセスを以下で終了させる。
ps
で pigpio_pwmfan の PIDを確認し、
kill [PID]
で pigpio_pwmfan を終了させる。

サービスへの登録

再起動時等、自動で開始するようにサービスに登録する。

ユニット定義ファイルの作成

/etc/systemd/system に ユニット定義ファイルを作成する。

ユニット定義ファイル例
[Unit]
# サービスの説明。内容は任意
Description=PWM FAN Control
# このUnitより先に起動するべきUnitを設定
After=local-fs.target
  
[Service]
# 実行するコマンドやスクリプトを記述
ExecStart=/usr/local/bin/pigpio_pwmfan
# サービス停止時の Kill する単位を設定
KillMode=process
# プロセスの起動方法を指定
Type=simple
# サービス停止時の再起動条件 (no は再起動しない)
Restart=always
 
[Install]
# 該当ユニットへの弱い依存関係を設定
WantedBy=multi-user.target

FAN制御プログラムの サービス登録、実行

sudo systemctl enable pigpiod.service
sudo systemctl start pigpiod.service






2023年11月6日月曜日

raspberry pi : C言語で LED 調光 (pigpio を使用した PWM 制御)

目的:

WiringPi は 非推奨になったとのことの為、pigpio を使用して PWM 制御を 行う。

概要:

pigpio による ハードウェアPWM を使用する場合、以下の2種類がある。
  1. gpioHardwarePWM を使用
    この場合、
    1. pigpiod (デーモン) を使用しない。( 動作していてはいけない )
    2. 実行は sudo を付けて行う必要がある。(管理者権限が必要)
  2. hardware_PWM を使用
    この場合、
    1. 実行 は sudo を 付けて実行する必要がある。
    2. 管理者権限は不要。
以下、この2種類について、記す。
( 参考 : The pigpio library )

gpioHardwarePWM による PWN 制御:

書式

gpioHardwarePWM(gpio番号, PWM周波数, PWMデューティ)
PWM周波数は 0 ~ 125000000  ( 0 ~ 125MHz)
PWMデューティ は 0 ~ 1000000 ( 0 ~ 100% )

注意事項等

インクルードファイル : pigpio.h
最初に、初期化 として gpioInitialise() を実行する必要がある。

サンプルコード

#include <pigpio.h>

#define GPIO_PWM1 18
#define GPIO_PWM2 19

#define PMW_FREQ    10000

int main(void)
{
    int ret = gpioInitialise();
    if (ret < 0)
    {
        return ret;
    }
    else
    {
        gpioHardwarePWM(GPIO_PWM1, PMW_FREQ, 100000);
        gpioHardwarePWM(GPIO_PWM2, PMW_FREQ, 700000);

        gpioSleep(PI_TIME_RELATIVE,5,0) ;

        gpioHardwarePWM(GPIO_PWM1, PMW_FREQ, 700000);
        gpioHardwarePWM(GPIO_PWM2, PMW_FREQ, 100000);

        gpioSleep(PI_TIME_RELATIVE,5,0) ;

        gpioHardwarePWM(GPIO_PWM1, PMW_FREQ, 0);
        gpioHardwarePWM(GPIO_PWM2, PMW_FREQ, 0);

        gpioTerminate();
    }

    return ret;
}

コンパイル

gcc -Wall -pthread -o pigpio_pwm pigpio_pwm.c -lpigpio -lrt
pigpio.h をインクルードしているため、 -lpigpio が必要。

実行

sudo ./pigpio_pwm
で gpio 18, 19 に PWMのパルス信号が 出力される。
サンプルコードでは 最初に出力した 5秒後に Duty を変えて出力。
その 5秒後に 出力を 停止する。

その他

pigpio を使用する場合は、管理者権限で実行する必要がある。( sudo で実行等)
pigpiod のデーモンは不要。( pigpiod が 動いていると実行できない )
通常の gpio へのアクセスは gpioWrite, gpioRead を使用する。

hardware_PWM による PWN 制御

pigpiod の注意事項

hardware_PWM を使用するには pigpiod を走らせる必要があるが、
pigpiod を走らせると、CPU のパワーを消費してしまう。
これは、ソフトウェア PWN の為 とのこと。
ソフトウェア PWM を使用しないのであれば、サンプリング機能を無効にする
オプション(-m) を付加することで、CPU の消費が少なくなる。

サンプリング機能を無効にする方法 ( CPUの使用率を下げる為)

設定は、 /lib/systemd/system/pigpiod.service を編集して行う。
pigpiod.service :
1 [Unit]
2 Description=Daemon required to control GPIO pins via pigpio
3 [Service]
4 ExecStart=/usr/bin/pigpiod -l -m
5 ExecStop=/bin/systemctl kill pigpiod
6 Type=forking
7 [Install]
8 WantedBy=multi-user.target
上記の通り、 ExecStart の ところに -m を追加する。

pigpiod 開始

pigpiod (デーモン) の開始は、
sudo systemctl enable pigpiod.service
sudo systemctl start pigpiod.service
で行う。
尚、pigpiod の停止は、
sudo systemctl disable pigpiod.service
sudo systemctl stop pigpiod.service
で行う。

書式

hardware_PWM(pi, gpio番号, PWM周波数, PWMデューティ)
pi は pigpio_start の戻り値
PWM周波数は 0 ~ 125000000  ( 0 ~ 125MHz)
PWMデューティ は 0 ~ 1000000 ( 0 ~ 100% )

注意事項等

インクルードファイル : pigpiod_if2.h
最初に、初期化 として pigpio_start(0,0) を実行する必要がある。

サンプルコード

#include <pigpiod_if2.h>

#define GPIO_PWM1 18
#define GPIO_PWM2 19

#define PMW_FREQ    10000

int main(void)
{
    int pi = pigpio_start(0,0) ;
    if (pi < 0)
    {
        return pi;
    }
    else
    {
        hardware_PWM(pi,GPIO_PWM1, PMW_FREQ, 100000);
        hardware_PWM(pi,GPIO_PWM2, PMW_FREQ, 700000);

        time_sleep(5) ;

        hardware_PWM(pi,GPIO_PWM1, PMW_FREQ, 700000);
        hardware_PWM(pi,GPIO_PWM2, PMW_FREQ, 100000);

        time_sleep(5) ;

        hardware_PWM(pi,GPIO_PWM1, PMW_FREQ, 0);
        hardware_PWM(pi,GPIO_PWM2, PMW_FREQ, 0);
    }

    return pi ;
}

コンパイル

gcc -Wall -pthread -o pigpio_pwm pigpio_pwm.c -lpigpiod_if2 -lrt
pigpiod_if2.h をインクルードしているため、 -lpigpiod_if2 が必要。

実行

./pigpio_pwm
で gpio 18, 19 に PWMのパルス信号が 出力される。
サンプルコードでは 最初に出力した 5秒後に Duty を変えて出力。
その 5秒後に 出力を 停止する。

その他 注意事項等

pigpio を使用する場合は、実行時に sudo は不要。
pigpiod のデーモンが必要。
通常の gpio へのアクセスは gpio_write, gpio_read を使用する。

pigpiod_if2.h


2023年8月4日金曜日

WSL : WSL のディスク容量を拡張する

目的:

 WSLに割り当てられているディスク容量を拡張する

概要:

 WSL の空き容量に不安があったため、使用できるディスク容量の拡張を行う。
 WSL は仮想ハードディスク上にインストールされているため、この仮想ハードディスクの容量を増やし、WSLのファイルシステムサイズを拡張する。
 尚、WSLの仮想ハードディスクは ext4 であるが、ext4 の場合、拡張はできるが縮小はできないとのこと。
 容量の拡張は、
仮想ハードディスクの保存パスの探索
仮想ディスク容量の拡張
ファイルシステムのサイズを変更
 の順に行う。

手順:

事前準備

  1. 端末等、WSL が起動していれば 終了させる。
  2. PowerShell を 管理者権限で起動する。 念のため、PowerShell から
    wsl.exe --shutdown
    を実行しておく。

仮想ハードディスクの保存パスの探索

  1. ディストリビューションのパッケージ名を探す。
    PowerShell で "Get-AppxPackage" コマンドでディストリビューションのパッケージ名を探す。(Debian, Ubuntu, openSUSE 等で 探す)
    Get-AppxPackage "*[WSLディストリビューション名の一部]*" | select packagefullname
    例えば debian の場合
    Get-AppxPackage "*Debian*" | select packagefullname
    で パッケージ名が表示される。
  2. ディストリビューションのパスを探す。
    PowerShell で "Get-ChildItem" コマンドでパッケージのフルパスを探す。
    Get-ChildItem $env:LOCALAPPDATA\packages\[パッケージ名の先頭]
    を入力して Tab キー を押下すると パッケージのパスが表示される。
    (そのまま [Enter] を押下するとディレクトリの内容が表示される )

仮想ディスク容量の拡張

PowerShellで、以下の様に仮想ディスク容量の拡張を行う。
  1. diskpart コマンド起動
  2. select vdisk コマンドで 容量を拡張する仮想ディスクを指定する。
    仮想ディスクは ディストリビューションのパスに LocalState\ext4.vhdx を付加したもの。
  3. detail vdisk コマンド で現在の仮想ディスクの情報(サイズ等) を確認する。
  4. EXPAND VDISK MAXIMUN=[仮想ディスクサイズ] で 拡張を行う。
一連のコマンドは、以下の通り。
diskpart
select vdisk file=[パッケージのフルパス]\LocalState\ext4.vhdx
detail vdisk
EXPAND VDISK MAXIMUM=393216
exit

ファイルシステムのサイズを変更

仮想ディスクの容量を拡張した後、ファイルシステムのサイズを拡大する。
  1. WSLのディストリビューション(端末) を起動
  2. 現在のファイルシステムのデバイス名とサイズを確認しておく。
    WSLの端末から
    df -h
    を実行し、マウント位置 が / になっている デバイス名と容量を確認する。

    (この場合、デバイス名 /dev/sdb , 容量 251G)
  3. ファイルシステムサイズを変更
  4. resize2fs コマンドでファイルシステムサイズを変更。
    書式 : sudo resize2fs [デバイス名] [拡張後の容量]
    sudo resize2fs /dev/sdb 384G
  5. 拡張後のサイズを確認する。
  6. df -h
    結果例
    サイズが 377G に拡張されたことを確認できた。 



2023年7月2日日曜日

verilog : SystemVerilog での記述

目的:

SystemVerilog で 追加された 合成可能な論理記述について記す

概要:

追加された項目としては、主に以下の様なものがある。
  1. .<ポート名> や .* による ポート宣言
  2. 数値記述
    1. bit幅の省略
    2. 可変長リテラル
  3. logic 変数
  4. 用途別 always 文
  5. 多次元配列
  6. enum
  7. typedef
  8. 構造体(struct)
  9. その他
  10. 共用体(union)
    interface
    package
    $clog2(), $bits()
    キャスティング

詳細:

  1. .<ポート名> や .* による ポート宣言
  2. モジュール呼び出し時、ポート名とネット名が同じ場合は .<ポート名> で接続できる。
    また。ポート名も .* で 省略できる。

    .<ポート名>での 宣言 (ネット名を省略)
    module1 i_module1 (
      .rst,
      .clk,
      .sig1,
      .sig2,
      .sig3(signal_3)
    ) ;
    sig3以外はネット名を省略。
    .* での 宣言 ( ポート名を省略 )
    module1 i_module1 (
      .*,
      .sig3(signal_3)
    ) ;
    sig3以外は * で省略。
    どちらも、sig3 以外は ネット名 と ポート名が同じ 場合に使用できる。
    但し、.* での接続は 回路記述では 推奨されないらしい。

  3. 数値記述
    1. bit幅の省略
    2. 'd30 の様に bit幅 を省略して記述できる。
      例えば、bit幅を P_BW のようにパラメータとした場合に '1' を設定する場合、
      data <= {{(P_BW-1){1'b0}},1'b1}
      の様にして bit幅を合わせて数値を記述/代入していたが、
      data <= 'd1 ;
      で良いとのこと。
      * Verilog では bit幅を省略すると 32bit とみなされ、合成はできるが spyglass 等のチェックで Warning が発生する。

    3. 可変長リテラル
    4. '0 や '1 で all '0' や all '1' を 表す。
      例えば、bit幅を P_BW とした場合に all '1' を設定する場合、
      data <= '1 ;
      で良い。

  4. logic 変数
  5. reg , wire の代わりに logic で宣言可能。
    (全て logic 宣言で良い。assign文, always文 のどちらにも使用できる。)
    但し、以下のwire の 様な 宣言と同時に代入を行うことはできない。
    wire  signal_1 = signal_2 ; <-- OK
    logic signal_1 = signal_2 ; <-- NG
    尚、icarus, vivado では コンパイル時にはエラーにならないが、シミュレーションでは代入されていない。
    会社で使用している環境ではコンパイル時にエラーになった。

  6. 用途別 always 文
  7. always文 を always_ff, always_comb,  always_latch で使い分けることができるようになった。
    1. always_ff
      always 文 で 順序回路(FF) を作る場合に使用する。
      従来の always での 順序回路記述と同様。
    2. always_comb
      always 文 で 組み合わせ回路 を作る場合に使用する。
      以下の様に、センシビリティリストは不要。
      always_comb
        if  (a)  dt = b ;
        else     dt = c ;
      Verilog の always @(*) と同様。
      case 文, if文 等で、条件を網羅していない場合は、ラッチが生成される。
    3. always_latch
      ラッチ生成用。詳細不明。

  8. 多次元配列
    1. unpacked の 多次元配列
      以下の記述は、Verilog でも 内部信号(メモリ等)には使用できたが、Systemverilog では ポートにも使用可能。
      [7:0] data[0:3] ;
      SystemVerilog では 以下の様に記述することも可能。
      [7:0] data[4] ;
      但し、unpacked の場合、data[0] ~ data[3] は 連続空間ではない為、以下の様に 32bit のデータを代入することはできない。
      wire [7:0] data [0:3] ;
      wire [31:0] data2 ;
      assign data = data2 ;  <--- NG
    2. packed の 多次元配列
      SystemVerilog では 以下の様に記述すると packed となる。
      [3:0][7:0] data :
      この場合、data[3] ~ data[0] は 連続空間となり、以下の様に 32bit幅のデータを assign することが可能。
      wire [31:0] data2 ;
      assign data = data2 ;
    3. 高次元配列
      以下の様な 3次元以上の配列も可能。
      [15:0][11:0][3:0][7:0] data : // 4次元配列の場合

  9. enum
  10. 列挙(enumeration)型。
    値を名前で定義できる。
    例 : ステートマシンの ステート定義
    enum logic [1:0] {STATE_0, STATE_1, STATE_3, STATE_4} state ;
    この場合、記述した名前に左から順に0から値が振られる。
    ( STATE_0=2'd0, STATE_1=2'd1, STATE_3=2'd2, STATE_4=2'd3 )
    値を指定したい場合は、
    enum logic [1:0] {STATE_0='d3, STATE_1='d2, STATE_3='d1, STATE_4='d0} state ;
    の様に指定する。
    同様のことを verilog で行う場合、以下の様に parameter で 値を 名前 に定義する。
    wire [1:0] state ;
    parameter STATE_0 = 2'd0 ;
    parameter STATE_1 = 2'd1 ;
    parameter STATE_2 = 2'd2 ;
    parameter STATE_3 = 2'd3 ;
    尚、enum から logic 等 への 代入はできるが、logic から enum への 代入は できない。( 但し、icarus では 代入できる )

  11. typedef
  12. データのタイプ名を新たに定義することができる。
    例えば、
    typedef enum logic [1:0] {ST_0,ST_1,ST_2,ST_3} t_stat ;
    t_stat stat ;
    t_stat next_stat ;
    の様に使用できる。

  13. 構造体(struct)
  14. 構造体
    以下の様に、複数の信号を 1つの名前に纏めることができる。
    struct {
      logic        we   ;
      logic [ 7:0] adr  ;
      logic [15:0] data ;
    } bus_sig ;
    struct にも packed と unpacked があり、指定しなければ unpacked となる。
    以下の様に packed と した場合、struct に 値を代入できる。
    struct packed {
      logic        we   ;
      logic [ 7:0] adr  ;
      logic [15:0] data ;
    } bus_sig ;

    assign bus_sig = 'h1234567 ;
    この場合、
       bus_sig.we   = 'b1
      bus_sib.adr  = 'h23
      bus_sib_data = 'h4567
    が入る。

  15. その他
  16. その他、
    • 共用体(union)
    • interface
    • package
    • $clog2(), $bits()
    • キャスティング
    等があるが、詳細は未調査。

2023年6月23日金曜日

verilog : Icarus verilog のオプション

目的:

Icarus Verilog での コンパイル時の オプションを 記す。

オプション:

オプションとして以下の様なものがある。
(詳細は、 こちら を参照。)

-o <File名> : 出力ファイル(コンパイルしたファイル)の名前を指定する。
(デフォルト は a.out)

-c <File名> : コマンドファイルを指定する。
(ソースファイル(テストベンチ,rtl等)のリスト等)

-I <Path> : インクルードファイルが存在するディレクトリを指定する。
-g <Flag> : verilog のバージョンを指定する。
バージョンは 1995, 2001, 2005, 2009, 2012 等。
-g 2012 で SystemVerilog に対応。

-s <Top module> : トップモジュールを明示的に指定する。
デフォルトではどのモジュールからも呼び出されていないものがトップと認識される。

-W <警告クラス> : どの警告(ワーニング)を出すかを指定。
-W all ですべてのワーニングがレポートされる。
警告クラスには以下の様なものがある。
anachronisms, implicit, implicit-dimensions
macro-replacement, portbind, select-range
timescale, sensitivity-entire-array

-v : 冗長指定。
著作権情報、進行状況メッセージ、各コンパイル段階のタイミング情報等を出力。

-V : バージョン情報を出力。
-V 時、コンパイルはスキップする。

例:

コンパイル

iverilog -o tst.o -c filelist.txt -g 2001 

ファイルリスト ( filelist.txt )

// test bench
testbench/testbench.sv

// rtl list
rtl/tst_module.v
rtl/tst_submod1.v
rtl/tst_submod2.v

2022年12月13日火曜日

verilog : Vivado (GUI) メモ

目的:

Vivado (GUI) でのシミュレーション 時のメモ を記す。
 ( 随時更新予定 )

TIPS:

  1.  シミュレーション実行手順
    Vivado GUI でのシミュレーション手順」参照

  2. 回路図表示
    左側にある「Flow Navigator」の
    RTL ANALYSYS
     Open Elaborated Design
      Schmatic
    を選択すると、RTL が どのような回路図になるかを確認できる。

  3. RTL を SystemVerilog として 扱う
    Sources ウインドウ の Design Sourdes にある RTL  を右クリック し、
    「Set File Type」を選択する。
    Set Type のウインドウが開くため、 File type を SystemVerilog に変更する。
    再シミュレーションを行うと、SystemVerilog として シミュレーションできる。




2022年11月26日土曜日

verilog : ビットシフト の記述

目的:

ビットシフトの記述の仕方について 記す

記述の仕方:

図のようなビットシフトを行う場合、次の様な記述の仕方がある。
  1. シフト演算子でシフト
    シフト演算子 ( << や >> ) を用いてシフトを行う。
  2. シフトした信号を定義してセレクト
    1bit づつシフトした信号を定義し、シフト量に応じて選択する。

通常は、シフト演算子でビットシフトを行う。
但し、下図の様に シフト量+元データ長 が シフト結果 のデータ長より長い場合、lintチェック等で Warning が 報告される。
はみ出した分は捨てられるのみで、合成は正常にできる為問題は無いが、Warning を減らしたい場合は 2. の記述をする。

また、下図の様に 元データ以外が '0' でない場合も 2. の記述で対応できる。


記述例:

シフトするデータを dat[2:0] (3bit), シフト結果を sft_data[7:0] (8bit),
シフト量を sft[3:0] (4bit) とし、左シフトする場合の記述例を示す。

  1. シフト演算子でシフト
    assign sft_data = dat << sft ;
  2. シフトした信号を定義してセレクト
    // シフトした信号の定義
    wire [7:0] sft_dt[0:8] ;
    assign sft_dt[0] = { 5'd0, dat } ;
    assign sft_dt[1] = { 4'd0, dat, 1'd0 } ;
    assign sft_dt[2] = { 3'd0, dat, 2'd0 } ;
    assign sft_dt[3] = { 2'd0, dat, 3'd0 } ;
    assign sft_dt[4] = { 1'd0, dat, 4'd0 } ;
    assign sft_dt[5] = { dat, 5'd0 } ;
    assign sft_dt[6] = { dat[1:0], 6'd0 } ;
    assign sft_dt[7] = { dat[0], 7'd0 } ;
    assign sft_dt[8] = 8'd0 ;
    // ビットシフト
    assign sft_data = (sft < 8) sft_dt[sft] : sft_dt[8] ;

各データ長をパラメータ化した場合の 2. の記述例を以下に示す。
 ( 1. の場合は パラメータ化しても 変わらない )

// パラメータ定義
parameter P_DT_BW    = 8 ;    // 元データ ビット幅
parameter P_SFTDT_BW = 128 ;  // シフト結果データ ビット幅
parameter P_SFT_BW   = 8 ;    // シフト量 ビット幅 (MAX 256)

// 各データの定義
wire [P_DT_BW-1:0]    dat ;      // 元データ
wire [P_SFTDT_BW-1:0] sft_data ; // シフト後のデータ
wire [P_SFT_BW-1:0]   sft ;      // シフト量

// シフトした信号の定義
wire  [P_SFTDT_BW-1:0]  sft_dt[0:P_SFTDT_BW]     ;
genvar i ;
generate
  for(i=0;i<P_SFTDT_BW-P_DT_BW;i=i+1) begin
    assign sft_dt[i] =
            {{(P_SFTDT_BW-P_DT_BW-i){1'b0}},dat,{(i){1'b0}}}  ;
  end
  for(i=0;i<P_DT_BW;i=i+1) begin
    assign sft_dt[P_SFTDT_BW-P_DT_BW+i] =
            {dat[P_DT_BW-i-1:0],{(P_SFTDT_BW-(P_DT_BW-i)){1'b0}}} ;
  end
  assign sft_dt[P_SFTDT_BW] = {(P_SFTDT_BW){1'b0}} ;
endgenerate
assign sft_data = (sft < P_SFTDT_BW) ? sft_dt[sft] :
                                       sft_dt[P_SFTDT_BW]  ;

元データ以外が base_data の場合 (パラメータ化)
// パラメータ定義
parameter P_DT_BW    = 8 ;    // 元データ ビット幅
parameter P_SFTDT_BW = 128 ;  // シフト結果データ ビット幅
parameter P_SFT_BW   = 8 ;    // シフト量 ビット幅 (MAX 256)

// 各データの定義
wire [P_DT_BW-1:0]    dat ;       // 元データ
wire [P_SFTDT_BW-1:0] sft_data ;  // シフト後のデータ
wire [P_SFTDT_BW-1:0] base_data ; // base_data
wire [P_SFT_BW-1:0]   sft ;       // シフト量

// シフトした信号の定義
wire  [P_SFTDT_BW-1:0]  sft_dt[0:P_SFTDT_BW]     ;
genvar i ;
generate
  assign sft_dt[0] = {base_data[P_SFTDT_BW-1:P_DT_BW], dat}  ;
  for(i=1;i<P_SFTDT_BW-P_DT_BW;i=i+1) begin
    assign sft_dt[i] =
             {base_data[P_SFTDT_BW1:P_DT_BW+i], dat, base_data[i-1:0]} ;
  end
  for(i=0;i<P_DT_BW;i=i+1) begin
    assign sft_dt[P_SFTDT_BW-P_DT_BW+i] =
             {dat[P_DT_BW-i-1:0], base_data[P_SFTDT_BW-P_DT_BW+i-1:0]} ;
  end
  assign sft_dt[P_SFTDT_BW] = base_data ;
endgenerate
assign sft_data = (sft < P_SFTDT_BW) ? sft_dt[sft] :
                                       sft_dt[P_SFTDT_BW]  ;

2022年11月23日水曜日

WSL : Verilator の インストール

目的:

Verilator をインストールする。

Verilator について:

Verilator は Verilog, SystemVerilog のシミュレータ である。
Verilator は 論理回路(論理合成可能なVerilogの記述) を C++ や SystemC 等にコンパイルし、シミュレーションを実行する。
シミュレーション用の記述は C++ や SystemC で 記述する。
また Lint チェックを行うことができる。

今回、Lint チェック を試すために インストールを行う。
 (文法チェック/記述チェック で使用できるか 確認。)

インストール手順:

参考URL : VERIPOOL ホームページ
apt で インストールできるようであるが、バージョンが少し古い為、ソースからビルドを行う事とした。

  1. Verilator をビルドするために必要なパッケージを インストールする。
    $sudo apt-get install git perl python3 make autoconf g++ flex bison ccache
    $sudo apt-get install libgoogle-perftools-dev numactl perl-doc
    $sudo apt-get install libfl2
    $sudo apt-get install libfl-dev
    $sudo apt-get install zlibc zlib1g zlib1g-dev
  2. 適当なディレクトリに移動し、git リポジトリからソースを取得する。
    $git clone https://github.com/verilator/verilator
  3. veerilator ディレクトリに移動する
    $cd verilator
  4. 以下の様に 環境変数を設定しておく。(SYSTEMC インストール済みの場合。設定値は一例。 ~/.bashrc に追加し、source する )
    export SYSTEMC=/usr/local/systemc/2.3.3
    export SYSTEMC_INCLUDE=$SYSTEMC/include
    export SYSTEMC_LIBDIR=$SYSTEMC/lib-linux64
    export SYSTEMC_ARCH=linux64
  5. 構成スクリプトを作成する。
    $autoconf
  6. 設定を行う。
    $./configure
  7. make 実行
    $make -j2
  8. 念のため、チェック実行
    $make test
  9. インストール 実行
    $sudo make install

動作確認 (Lint チェック):

Lint チェックを実行して見る。
Lintチェックは、

$verilator --lint-only -Wall  [RTL ファイル名]
で実行できる。
使用オプションは以下の通り。
--lint-only     Lint, but do not make output
 -Wall          Enable all style warnings

always 文 (FF) で
  data_1 <= #1 data ;
のように 遅延時間を指定していると
%Error-NEEDTIMINGOPT: test.v:64:25: Use --timing or --no-timing to specify how timing controls should be handled
の様なエラーが報告される。
メッセージにあるように
verilator --lint-only -Wall --timing  [RTL ファイル名]
とすると このエラー が報告されなくなる。
--no-timing を付けると、Warning 報告となる。
--timing        Enable timing support
--no-timing     Disable timing support


Lint チェックを実行して見た結果、処理は早く、rtl 記述後にまずは verilator で Lint チェックでデバッグ(記述チェック)するのが良いように思える。
但し、bit幅の不整合などで、実質問題ない記述でもWarning が出る為、煩わしく感じるかもしれない。
とはいえ、問題のある記述の場合もある為、ちゃんと 全数確認する必要がある。


blogger : 文字(段落)を枠で囲む

目的:

blogger で 文字(段落)を枠で囲む。

内容:

記述の途中で
線の幅       : 1px
上側余白     : 5px
右側余白     : 350px
下側余白     : 5px
左側余白     : 50px
線の内側余白 : 5px
の様に、文章を枠で囲む。

方法:

HTMLビュー で線で囲みたい文章の前後を
<div style="border: 1px solid rgb(128, 128, 128); margin-bottom: 5px; margin-left: 50px; margin-right: 350px; margin-top: 5px; padding: 5px;"> (2022/11/26 修正)
<div style="border: 1px solid rgb(128, 128, 128); margin: 5px 350px 5px 50px; padding: 5px;">

</div>
で挟む。margen は 上側,右側,下側,左側の順 *1
上の例 ("内容:"で記載の例) では 各パラメータは

線の幅 : border: 1px 上側余白 : margin-top: 5px 右側余白 : margin-right: 350px 下側余白 : margin-bottom: 5px
左側余白 : margin-left: 50px 線の内側余白 : padding: 5px

とし、更に 文章を<tt> と </tt>で囲っている。(等幅フォント)
尚、この例 ("方法:"で記載の例) では、" 行の途中で文字の先頭を揃える " と組み合わせて記載している。

*1
4方(上下左右) 全て指定する場合、
<div style="border: 1px solid rgb(128, 128, 128); margin-bottom: 5px; margin-left: 50px; margin-right: 350px; margin-top: 5px; padding: 5px;">
の様に書いても良いが、
<div style="border: 1px solid rgb(128, 128, 128); margin-bottom: 5px; margin-left: 50px; margin-right: 350px; margin-top: 5px; margin: 5px 350px 5px 50px; padding: 5px;">
の様に margin 設定が 自動で追加される。
後から margin-right の値等を修正しても margin 設定には反映されず 混乱の元となる。
4方全てでなければ、個別に指定しても問題ない。


2022年11月22日火曜日

WSL : SystemC のインストール

目的:

SystemCの環境をインストールする。

導入契機:

verilator 導入にあたり、シミュレーションには SystemC を使用した方が良いとの記事を見かけた為、インストールしておくこととした。
いづれは、SystemC も使用できるようにしたいと思う。

インストール手順:

  1. Accelleraホームページから"CoreSystemCLanguageandExamples(tar.gz)"をダウンロード ( ダウンロードページ )
     ( systemc-2.3.3.tar.gz をダウンロード した )
  2. ダウンロードしたファイルを適当なディレクトに格納する。
  3. ファイルを解凍する
    tar xvf systemc-2.3.3.tar.gz
  4. 展開された systemc-2.3.3 ディレクトリに移動する
    cd systemc-2.3.3
  5. objdirを作成する
    mkdir objdir
  6. objdirに移動する
    cd objdir
  7. インストール先のディレクトリを作成する。
    ここでは、"/usr/local/systemc/2.3.3" とする。
    sudo mkdir /usr/local/systemc
    sudo mkdir /usr/local/systemc/2.3.3
  8. g++のバージョンを確認
    g++ --version
    (もし、g++が無いようならビルド環境のインストールが必要)
  9. 環境変数CXXにg++を設定する。
    export CXX=g++
  10. インストール先を指定して configure を実行する。
    ../configure --prefix=/usr/local/systemc/2.3.3
  11. make実行
    make
  12. インストール実行
    sudo makeinstall
  13. 念のため、チェック実行
    make check
  14. 環境変数 SYSTEMC_HOME, LD_LIBRARY_PATH にインストール先, ライブラリ所在を設定する。
    ~/.bashrc に次の2行を追加し、source する。
    export SYSTEMC_HOME=/usr/local/systemc/2.3.3
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SYSTEMC_HOME/lib-linux64
    source ~/.bashrc


テスト:

  1. 次の内容のサンプルプログラムを作成する。
    (ファイル名:hello.cpp)
    #include <systemc.h>

    int sc_main(int argc, char *argv[]){
        printf("Hello world\n");
        return 0;
    }
  2. コンパイル/リンクを実行する
    g++ -I. -I$SYSTEMC_HOME/include -L. -L$SYSTEMC_HOME/lib-linux64 -o hello hello.cpp -lsystemc -lm
    → オブジェクト "hello" が生成される。
    尚、各オプションは、以下の通り。
    -I:#includeファイルの検索パスを追加する。
    -c:コンパイルのみ。リンクはしない。
    -L:ライブラリ検索パスを追加する。
    -o:出力ファイルの名前を指定する。
    -L:リンク時に指定したライブラリを検索する。
  3. 以下のようにhelloを実行し、"Hello world" が表示されれば、OK
    ./hello
    (結果)
            SystemC 2.3.3-Accellera --- Nov 20 2022 08:46:27
            Copyright (c) 1996-2018 by all Contributors,
            ALL RIGHTS RESERVED
    Hello world


2022年11月21日月曜日

WSL : Debian の アップグレード

目的:

WSL2 の ディストリビューション debian の アップグレード (debian 9 → debian 11 )

アップグレード理由:

  1. Verilator の コンパイル を行ったところ、エラーが発生。原因を g++ のバージョンが低い為と推定
  2. 久しぶりに  apt update 等を行ったが 何も更新されない。

ことから、debian の アップグレードを試みることとした。

アップグレード手順:

アップグレードは ここ を参考に実施。
  1.  現在のインストールをバックアップ
    PowerShell で バックアップを保存するディレクトリに移動し、
    wsl --export Debian <保存ファイル名>.tar
  2. Devian ターミナルを起動し、update, upgrade を行う。
    sudo apt-get update && sudo apt-get upgrade
  3. /etc/apt/sources.list を編集してリポジトリを更新する。
    内容を以下のように変更。(主に strech → bullseye)
    deb http://deb.debian.org/debian bullseye main
    deb http://deb.debian.org/debian bullseye-updates main
    deb http://security.debian.org/debian-security bullseye-security main
    deb http://ftp.debian.org/debian bullseye-backports main
  4. 更新後のリポジトリで update, upgrade を行う。
    sudo apt-get update && sudo apt-get upgrade
    途中、
    "パッケージの更新中、質問なしにサービスを再起動しますか?  "

    "はい"
    を回答
  5. 「完全アップグレード」を実行
    sudo apt full-upgrade
    不要となるパッケージがあったため、
    sudo apt autoremove
    を実行

以上でアップグレード完了。

備考:

full-upgrade 実行中、
 sgml-base (1.30) のトリガを処理しています ...
libgdk-pixbuf-2.0-0:amd64 (2.42.2+dfsg-1+deb11u1) のトリガを処理しています ...
処理中にエラーが発生しました:
 elpa-magit
E: Sub-process /usr/bin/dpkg returned an error code (1)
の様なエラーが発生。
ここ を参考に
sudo dpkg --configure -a
を実行して、エラー解消した。(と思う)

2022年11月17日木曜日

verilog : セレクタ(マルチプレクサ) の記述 いろいろ

目的

セレクタの記述の仕方について 記す

記述の仕方

  1. 3項演算子で記述
    最もよく使用する記述。
  2. 配列のインデックス(添え字) で選択
    選択数が多い場合は、この方法で記述。
  3. case文 で記述
    function 文 や always 文 内で使用する。
    セレクタを使いまわす場合は function で記述する。
  4. if文 で記述
    function 文 や always 文 内で使用する。
    セレクト条件が複数の信号の組み合わせでも記述できる。
    但し、複雑な条件となると
     可読性か悪くなる
     シミュレーション時に条件成立が判りにくい
    等の問題がある。
    セレクト条件は assign 文で 1信号 にしてから使用した方がよい。
以下に記述例を示す。

記述例

図の様なセレクタを記述する例を示す。
  1. 3項演算子で記述
    assign sel_data  = (sel == 4'd0)  ?  data_0 :
                       (sel == 4'd1)  ?  data_1 :
                       (sel == 4'd2)  ?  data_2 :
                       (sel == 4'd3)  ?  data_3 :
                                          8'd0 ;

  2. 配列のインデックス(添え字) で選択
    reg [7:0] all_data[0:15] ;   //選択対象の 2次元配列データ
    assign sel_data = all_data[sel] ;  //セレクタ
    選択対象が配列になっていない場合、以下のように データを 2次元配列に代入する。
     ( 16 x 8bit の 配列に 4つのデータを代入し、残り 12個を 8'd0 で埋める場合。)
    wire [7:0] all_data[0:15] ;     // 2次元配列データ
    assign all_data[0] = data_0 ;
    assign all_data[1] = data_1 ;
    assign all_data[2] = data_2 ;
    assign all_data[3] = data_3 ;
    genvar i ;
    generate
      for (i=4; i<16; i=i+1) begin
        assign all_data[i] = 8'd0 ;
      end
    endgenerate

  3. case文 で記述
    function 文 で選択の場合
    function [7:0] data_sel (
    input [3:0] select,
    input [7:0] in_data0,
    input [7:0] in_data1,
    input [7:0] in_data2,
    input [7:0] in_data3
    ) ;
      begin
        case (sel)
          4'd0    : sel_data = in_data0 ;
          4'd1    : sel_data = in_data1 ;
          4'd2    : sel_data = in_data2 ;
          4'd3    : sel_data = in_data3 ;
          default : sel_data = 8'd0     ;
        endcase
      end
    endfunction

    assign sel_data = data_sel(.select(sel),.in_data0(data_0),.in_data1(data_1),
                               .in_data2(data_2),.in_data3(data_3)) ;
    always 文 で選択の場合
    always @(*) begin
      case (sel)
        4'd0    : sel_data = data_0 ;
        4'd1    : sel_data = data_1 ;
        4'd2    : sel_data = data_2 ;
        4'd3    : sel_data = data_3 ;
        default : sel_data = 8'd0   ;
      endcase
    end

  4. if文 で記述
    always 文 で選択の場合
    always @(*) begin
      if      (sel == 4'd0)  sel_dt5 = data_0 ;
      else if (sel == 4'd1)  sel_dt5 = data_1 ;
      else if (sel == 4'd2)  sel_dt5 = data_2 ;
      else if (sel == 4'd3)  sel_dt5 = data_3 ;
      else                   sel_dt5 = 8'd0   ;
    end



2022年10月2日日曜日

blogger: ページ内ジャンプ

 目的

blogger の記事でページ内へのジャンプを設定する方法を記す。

設定方法 

  1. ジャンプ先に、id を設定する。( HTML で編集 )
    見出し等の場合の例
    <h3 id="target">
    文字列(div 等)
    <p id="target">
    ( "target" は適当な文字列 )
  2. ジャンプ元にリンクを設定する。
    リンク先は、右ペインの パーマリンク に、次のように id を加えたものを設定。
    https://qazsedcftf.blogspot.com/2022/10/blogger.html#target

テスト記述 

以下にページ内ジャンプのサンプルを記述する。
( ジャンプすることが判るように、ジャンプ先は、下の方に設定。

設定方法 へジャンプ
設定方法 の 2 へ ジャンプ

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

テストジャンプ先1




テストジャンプ先2






2022年7月2日土曜日

Excel : Excel ファイルの 個人情報を削除する

 

目的:

Excelファイル内 に保存されている 作成者 等の 個人情報を削除する。

内容: 

Excelファイル内 には 保存されている 作成者名、更新者名 等の 個人情報が保存されている。
この個人情報をファイルから削除する手順を示す。


方法:

  1. 「ファイル」タブをクリックする。
  2.  左ペインの[情報]をクリックする。
  3. [問題のチェック]ボタン→ [ドキュメント検査]をクリックする。
  4. ドキュメントのプロパティと個人情報 に チェックが入っていることを確認して[検査]をクリックする。
  5. ドキュメントのプロパティと個人情報 の [すべて削除]をクリックする。
  6. [閉じる]をクリックする

再度、検査まで実施し、個人情報がないことを確認する。


Excel : 行番号のつけ方 いろいろ

目的:

Excel で 行番号を振るときの 書き方について記しておく。

内容: 

行番号を振るとき、以下の様な場合の書き方を記す。
 ( 下へ行くほど、式が複雑になる )
・ 単純に数値を記入する。   → 行の移動等で 全行付けなおし。
・ 数式でインクリメントする。 → 行の移動等で 編集行とその後ろの行を付けなおし。
・ 行に応じた行番号にする。  → 移動等では修正不要。
・ データのある行のみ行番号を振る。
・ データのある行のみ行番号を振り、データを移動しても番号が狂わないようにする。
( サンプル Excel )

方法:

( 以降、セル B3 に 先頭行 の 行番号 '1' を 設定 して 行番号をつけた場合 )
  1. 単純に数値を記入する。(+1づつの数値を振る場合)
    1. 先頭行(セル B3) に '1' を記入
    2. 記入したセルを選択し、右下を掴んで CTRL を押しながら下へドラッグする。
      この方法の場合、行の移動/挿入/削除を行うと 全行やり直す必要がある。

  2. 数式でインクリメントする。(セル毎に +1 して 連続した行番号を付ける。)
    1. 先頭行に '1' を記入 ( セル B3 に '1' を記入したとする。)
    2. 下のセル (B4) に 以下の式を記入する。 (上のセル に +1 した値になる)
      =B3+1
    3. セル B4 を選択し、右下を掴んで 下にドラッグする。
  3. この方法の場合、行の移動/挿入/削除を行うと 移動/挿入/削除した行と次の行の行番号を修正する必要がある。

  4. 行に応じた行番号にする。(ROW 関数を使用して連続した行番号をつける。)
    1. 先頭行に '1' を記入 ( セル B3 に '1' を記入したとする。)
    2. 下のセル (B4) に 以下の式を記入する。 ( 上のセル に +1 した値になる ) =B$3+(ROW(B4)-ROW(B$3))
    3. セル B4 を選択し、右下を掴んで 下にドラッグする。
  5. この方法の場合、行の移動/削除を行っても行番号は狂わない。
    行の挿入を行った場合、別の行の行番号のセルを挿入した行にコピーする。

  6. データのある行のみに行番号を付ける。
    ( C列に データがあり、B列に データのある行のみに行番号を付ける場合 )
    1. 先頭行に '1' を記入
      ( セル C3にデータがあり、セル B3 に '1' を記入したとする。)
    2. 下のセル (B4) に "" を記入する。
      ( データ行毎に 上のセル に +1 した値になる )
  7. =IF(C4="","",C$3+COUNTA(C$3:C4))-1
    この方法の場合、行の移動/挿入/削除を行っても行番号は狂わないが、データのみを移動/挿入/削除すると 行番号が狂う。

  8. データのある行のみに行番号を付け、
    データ移動しても行番号が狂わない様にする。
      ( C列に データがあり、B列に データのある行のみに行番号を付ける場合 )
    1. 先頭行に '1' を記入
      ( セル C3にデータがあり、セル B3 に '1' を記入したとする。)
    2. 下のセル (B4) に "" を記入する。
      ( データ行毎に 上のセル に +1 した値になる )        =IF(INDEX(C:C,ROW(B4))="","",C$3+COUNTA(C$3:INDEX(C:C,ROW(B4)))-1)
  9. この方法の場合、データのみを移動/挿入/削除しても行番号は狂わない。
    但し、先頭行は移動/削除 不可。 

サンプル :

    サンプルの xlsx ファイルは  こちら



    2021年11月4日木曜日

    windows : ストアアプリ(itunes等)のショートカット作成

     目的:

    ランチャー登録等の為、ストアアプリ(itunes)のショートカットを作成する。

    方法:

    「スタート」から 目的のアプリをドラッグし、デスクトップ や エクスプローラ にドロップする。
    これで、ショートカットが作成される。
     

    背景:

    ストアアプリの実行ファイルは C:\ProgramvFiles に存在しない。
    また、スタートメニューの右クリックにもショートカット作成ができなかった。

    が、スタートメニューからドラッグアンドドロップで作成できると判った。

     


    2021年11月2日火曜日

    blogger : 箇条書きの点の色を変える

     目的:

    blogger で 箇条書きを行った時の点の色を変える。

    内容:

    • 項目1
    • 項目2
      • 項目2-1
      • 項目2-2
        • 項目2-2-1
    • 項目3
    の様に、箇条書きのネスト等で点の色(黒丸/白丸) が変わる。
    この為、点の色を手動で変える。

    方法:

    HTMLビュー で 箇条書きの <ul> を以下のように変更する。
    • 黒丸にする場合
      <ul style="list-style-type: disc;">
    • 白丸にする場合
      <ul style="list-style-type: circle;">


    WSL : WSL2 を使用する 2

    目的:

    Windows10 で 新たに WSL2 を使用できるようにする

    前提条件:

    Windows 10 バージョン 2004 以降 (ビルド 19041 以降) で初めて WSLを入れる場合。
    自PC は 20H1 で実施。
    ディストリビューションは debian をインストール。

    インストール手順:

    1. PowerShwll または コマンドプロンプト を管理者権限で立ち上げ、以下を実行。
      wsl --install -d Debian
      • wsl --install のみだと、Ubuntu が インストールされる。
      • 利用可能なディストリビューションは、
        wsl --list --online
         または
        wsl -l -o
         で表示できる
    2. PCを再起動する。
      再起動すると、ディストリビューションのインストールが始まる。
    3. ユーザ名とパスワードの設定
      ディストリビューションのインストールが終わると、ユーザ名とパスワードの入力が要求されるため、入力する。
    以上で、WSL2 のインストールは完了。

    WSL2 注意事項:

    1. DISLPAY の設定は 以下の様に行う。
      ( export DISPLAY=:0.0 では NG )
      export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0

    2. cifs-utils をインストール
      NAS(SMB1.0) を drvfs でマウントできない。このため、cifs-utils をインストールし、cifs でマウントする。
      sudo apt install cifs-utils

    3. vim が vim-tiny になっている。
      Vim インストール と同様に入れ替え

    4. gcc, make が入っていない。
      以下にて開発環境をインストールする。
      sudo apt install build-essential


    2021年10月25日月曜日

    verilog : 多ビット信号の配列(二次元配列)と入出力ポート

    目的:

    入出力ポートには2次元配列を使用できない為、2次元配列を1次元配列にアサインする。

    記述例:

    内部信号
      reg  [P_BW-1:0]  r_rise_pos[0:6] ;
    を 1次元の配列
      wire [P_BW*7-1:0] w_rise_pos ;
    に アサイン する場合の記述例を以下に示す。

    例1 :

    assign  w_rise_pos = {r_rise_pos[6], r_rise_pos[5],r_rise_pos[4],r_rise_pos[3],
                          r_rise_pos[2], r_rise_pos[1],r_rise_pos[0] } ;

    例2 :

    generate
      for (i=0; i<7; i=i+1)
        begin : asin_1d
          assign w_rise_pos[(i+1)*P_BW-1:i*P_BW] = r_rise_pos[i] ;
        end
    endgenerate

    回路例:

    この回路例は、レジスタブロック(pgen_reg)とパルス生成ブロック(pgen_plsgen)で構成。
    7組の 立ち上げタイミング(r_rise_pos)と立ち下げタイミング(r_fall_pos)レジスタを持ち、スタートビット(r_cntstart) に '1' をライトする事で、設定したタイミングで ON/OFF する7つのパルスを出力する。
    立ち上げ/たち下げタイミングを 2次元配列とし、ブロック間 を1次元配列として接続している。

    RTL (Verilog)

    レジスタブロック : 2次元配列→1次元配列 のアサインに 上述の 例1 と 例2 を使用。

    // -----------------------------------------------------
    //   2d-array Sample module 
    //
    //   Module Name : pgen_reg
    //   Version     : 0.00
    // -----------------------------------------------------
     
    module pgen_reg #(                      // Module name : test
      parameter P_BW = 8                    // parameter list
    ) (                                     //
      clr,                                  // port list
      clk,
      adr,
      we,
      data,
      rd_data,
      cntstart,
      cntmax,
      rise_pos,
      fall_pos
    ) ;
     
    // ====== port declaration ================
    input                     clr      ;
    input                     clk      ;
    input            [3:0]    adr      ;
    input                     we       ;
    input       [P_BW-1:0]    data     ;
    output      [P_BW-1:0]    rd_data  ;
    output                    cntstart ;
    output      [P_BW-1:0]    cntmax   ;
    output reg  [7*P_BW-1:0]  rise_pos ;
    output reg  [7*P_BW-1:0]  fall_pos ;
     
    // ====== parameter declaration ===========
    parameter   DLY = 1 ;
     
    // ====== internal signal declaration =====
    wire        [15:0]  sel        ;
    wire        [15:0]  reg_wen    ;
    wire  [7*P_BW-1:0]  w_rise_pos ;
    wire  [7*P_BW-1:0]  w_fall_pos ;
    
    reg              r_cntstart ;
    reg  [P_BW-1:0]  r_cntmax     ; 
    reg  [P_BW-1:0]  r_rise_pos[0:6] ;
    reg  [P_BW-1:0]  r_fall_pos[0:6] ;
    
    // variable for generate ----------
    genvar i ;
    
    // ====== logical description =============
    
    // address decode -------------------------
    assign sel = 16'd1 << adr ;
    
    // write enable ---------------------------
    assign reg_wen = sel & {16{we}} ;
    
    // register -------------------------------
    
    //   cntstart reg -----------------------
    always @(posedge clk or posedge clr)
      if (clr) 
        r_cntstart  <= #DLY  1'b0 ;
      else if (reg_wen[0])
        r_cntstart  <= #DLY  data[0] ;
    
    //   cntmax reg -------------------------
    always @(posedge clk or posedge clr)
      if (clr) 
        r_cntmax    <= #DLY  {P_BW{1'b0}} ;
      else if (reg_wen[1])
        r_cntmax    <= #DLY  data ;
    
    //   rise_pos, fall_pos reg -------------
    generate
      for (i=0; i<7; i=i+1) 
        begin : pos_reg
          always @(posedge clk or posedge clr)
            if (clr)
              r_rise_pos[i]  <= #DLY  {P_BW{1'b0}} ;
            else if (reg_wen[i*2+2])
              r_rise_pos[i]  <= #DLY  data ;
    
          always @(posedge clk or posedge clr)
            if (clr) begin
              r_fall_pos[i]  <= #DLY  {P_BW{1'b0}} ;
              end
            else if (reg_wen[i*2+3])
              r_fall_pos[i]  <= #DLY  data ;
        end
    endgenerate
    
    // read data select -----------------------
    assign rd_data = (sel[0])  ?  {{(P_BW-1){1'b0}},r_cntstart} :
                     (sel[1])  ?  r_cntmax :
                     (sel[2])  ?  r_rise_pos[0] :
                     (sel[3])  ?  r_fall_pos[0] :
                     (sel[4])  ?  r_rise_pos[1] :
                     (sel[5])  ?  r_fall_pos[1] :
                     (sel[6])  ?  r_rise_pos[2] :
                     (sel[7])  ?  r_fall_pos[2] :
                     (sel[8])  ?  r_rise_pos[3] :
                     (sel[9])  ?  r_fall_pos[3] :
                     (sel[10]) ?  r_rise_pos[4] :
                     (sel[11]) ?  r_fall_pos[4] :
                     (sel[12]) ?  r_rise_pos[5] :
                     (sel[13]) ?  r_fall_pos[5] :
                     (sel[14]) ?  r_rise_pos[6] :
                     (sel[15]) ?  r_fall_pos[6] : {P_BW{1'b1}} ;
    
    // 2d_array -> 1d_array --------------------
    // EX.1 ------------
    assign  w_rise_pos =   { r_rise_pos[6], 
                             r_rise_pos[5],
                             r_rise_pos[4],
                             r_rise_pos[3],
                             r_rise_pos[2],
                             r_rise_pos[1],
                             r_rise_pos[0] } ;
    // EX.2 ------------
    generate
      for (i=0; i<7; i=i+1)
        begin : asin_1d
          assign w_fall_pos[(i+1)*P_BW-1:i*P_BW] = r_fall_pos[i] ;
        end
    endgenerate
    
    
    // output signal ---------------------------
    assign cntstart  = r_cntstart ; 
    assign cntmax    = r_cntmax ;
    
    always @(posedge clk or posedge clr)
      if (clr)
        rise_pos <= #DLY  {(7*P_BW){1'b0}} ;
      else
        rise_pos <= #DLY  w_rise_pos  ;
    
    always @(posedge clk or posedge clr)
      if (clr)
        fall_pos <= #DLY {(7*P_BW){1'b0}} ;
      else
        fall_pos <= #DLY  w_fall_pos ;
    
    endmodule
    

    パルス生成ブロック : 1次元配列→2次元配列 のアサインに 上述の 例2 と同様の記述を使用。

    // -----------------------------------------------------
    //   2d-array Sample module 
    //
    //   Module Name : pgen_plsgen
    //   Version     : 0.00
    // -----------------------------------------------------
     
    module pgen_plsgen #(              // Module name : test_plsgen
      parameter P_BW = 8               // parameter list
    ) (                                //
      clr,                             // port list
      clk,
      cntstart,
      cntmax,
      rise_pos,
      fall_pos,
      pls_0,
      pls_1,
      pls_2,
      pls_3,
      pls_4,
      pls_5,
      pls_6
    ) ;
     
    // ====== port declaration ================
    input                clr ;
    input                clk ;
    input                cntstart ;
    input    [P_BW-1:0]  cntmax   ;
    input  [7*P_BW-1:0]  rise_pos ;
    input  [7*P_BW-1:0]  fall_pos ;
    output               pls_0    ;
    output               pls_1    ;
    output               pls_2    ;
    output               pls_3    ;
    output               pls_4    ;
    output               pls_5    ;
    output               pls_6    ;
     
    // ====== parameter declaration ===========
    parameter   DLY = 1 ;
     
    // ====== internal signal declaration =====
    wire             w_start_pls  ;
    wire  [P_BW-1:0] w_rise_pos[0:6] ;
    wire  [P_BW-1:0] w_fall_pos[0:6] ;
    wire             w_pls[0:6]  ;
    wire             w_valid ;
    
    reg              r_start_dl ;
    reg  [P_BW-1:0]  r_count ;
    reg              r_pls[0:6]  ;
    
    // variable for generate ----------
    genvar i ;
    
    // ====== logical description =============
    
    // input array -> 2d array assign ---------
    generate
      for (i=0; i<7; i=i+1) 
        begin : asin_2d
          assign w_rise_pos[i] = rise_pos[(i+1)*P_BW-1:i*P_BW] ;
          assign w_fall_pos[i] = fall_pos[(i+1)*P_BW-1:i*P_BW] ;
        end
    endgenerate
    
    // generate start pulse -------------------
    always @(posedge clk or posedge clr)
      if (clr)
        r_start_dl  <= #DLY  1'b0 ;
      else
        r_start_dl  <= #DLY  cntstart ;
    
    assign w_start_pls = cntstart & ~r_start_dl ;
    
    // pulse counter  -------------------------
    always @(posedge clk or posedge clr)
      if (clr)
        r_count  <= #DLY  {P_BW{1'b0}};
      else if (w_start_pls)
        r_count  <= #DLY  {{(P_BW-1){1'b0}},1'b1} ;
      else if ((r_count > 0) && (r_count < cntmax) )
        r_count  <= #DLY  r_count + 1 ;
      else if (r_count == cntmax)
        r_count  <= #DLY  {P_BW{1'b0}} ;
    
    assign r_valid = r_count != 0 ;
    
    // pulse generate -------------------------
    generate
      for (i=0; i<7; i=i+1) 
        begin : pos_reg
          assign w_pls[i] = (w_rise_pos[i] <= r_count) && (r_count < w_fall_pos[i]) && r_valid ;
    
          always @(posedge clk or posedge clr)
            if (clr)
              r_pls[i]  <= #DLY  {P_BW{1'b0}} ;
            else
              r_pls[i]  <= #DLY  w_pls[i] ;
        end
    endgenerate
    
    // output signal ---------------------------
    assign pls_0 = r_pls[0]   ; 
    assign pls_1 = r_pls[1]   ; 
    assign pls_2 = r_pls[2]   ; 
    assign pls_3 = r_pls[3]   ; 
    assign pls_4 = r_pls[4]   ; 
    assign pls_5 = r_pls[5]   ; 
    assign pls_6 = r_pls[6]   ; 
     
    endmodule
    

    トップブロック : レジスタブロックとパルス生成ブロックの上位ブロック

    // -----------------------------------------------------
    //   2d-array Sample module 
    //
    //   Module Name : pgen
    //   Version     : 0.00
    // -----------------------------------------------------
     
    module pgen(
      clr,                                  // port list
      clk,
      adr,
      we,
      data,
      rd_data,
      pls_0,
      pls_1,
      pls_2,
      pls_3,
      pls_4,
      pls_5,
      pls_6
    ) ;
    
    // ====== port declaration ================
    input                clr ;
    input                clk ;
    input         [3:0]  adr ;
    input                we  ;
    input    [     7:0]  data     ;
    output   [     7:0]  rd_data  ;
    output               pls_0    ;
    output               pls_1    ;
    output               pls_2    ;
    output               pls_3    ;
    output               pls_4    ;
    output               pls_5    ;
    output               pls_6    ;
     
    // ====== internal signal declaration =====
    wire               cntstart ;
    wire   [     7:0]  cntmax   ;
    wire [7*8   -1:0]  rise_pos ;
    wire [7*8   -1:0]  fall_pos ;
     
    // ====== logical description =============
    
    pgen_reg #(            
      .P_BW  (8)  
    )i_test_reg(                    
      .clr        ( clr          ),                 
      .clk        ( clk          ),
      .adr        ( adr          ),
      .we         ( we           ),
      .data       ( data         ),
      .rd_data    ( rd_data      ),
      .cntstart   ( cntstart     ),
      .cntmax     ( cntmax       ),
      .rise_pos   ( rise_pos     ),
      .fall_pos   ( fall_pos     )
    ) ;
     
    pgen_plsgen #(
      .P_BW (8)
    )i_test_plsgen(                  
      .clr          ( clr      ),               
      .clk          ( clk      ),
      .cntstart     ( cntstart ),
      .cntmax       ( cntmax   ),
      .rise_pos     ( rise_pos ),
      .fall_pos     ( fall_pos ),
      .pls_0        ( pls_0    ),
      .pls_1        ( pls_1    ),
      .pls_2        ( pls_2    ),
      .pls_3        ( pls_3    ),
      .pls_4        ( pls_4    ),
      .pls_5        ( pls_5    ),
      .pls_6        ( pls_6    )
    ) ;
    
    endmodule
    

    シミュレーション用のテストベンチ

    // ----------------------------------------------------------
    //   test bench
    //
    //     for pgen.v
    // ----------------------------------------------------------
    
    `timescale 1ns / 1ps
    
    module testbench ;
    
    // testbench logic -------------------
    logic         clr;
    logic         clk;
    logic  [ 3:0] adr     ;
    logic         we      ;
    logic  [ 7:0] data    ;
    logic  [ 7:0] rd_data ;
    logic         pls_0   ;
    logic         pls_1   ;
    logic         pls_2   ;
    logic         pls_3   ;
    logic         pls_4   ;
    logic         pls_5   ;
    logic         pls_6   ;
    
    // parameter -------------------------
    parameter  MAX_SIM_TIME = 20000 ;
    
    // target module ---------------------
    pgen i_pgen (
      .clr           ( clr        ),
      .clk           ( clk        ),
      .adr           ( adr        ),
      .we            ( we         ),
      .data          ( data       ),
      .rd_data       ( rd_data    ),
      .pls_0         ( pls_0      ),
      .pls_1         ( pls_1      ),
      .pls_2         ( pls_2      ),
      .pls_3         ( pls_3      ),
      .pls_4         ( pls_4      ),
      .pls_5         ( pls_5      ),
      .pls_6         ( pls_6      )
    ) ;
    
    // clock, reset generate -------------
    initial begin
      clk = 0 ;
      clr = 1 ;
      #10 clr = 0 ;
      forever begin
        #10 clk = ~clk ;
      end
    end
    
    // scenario --------------------------
    initial begin
      $dumpfile("wave.vcd");
      $dumpvars(0,testbench) ;
    
      adr         =  4'h0   ;
      we          =  1'b0   ;
      data        =  8'h0   ;
    
      #MAX_SIM_TIME
      $display(" SIM TIME OUT !!") ;
      $finish ;
    
      end
    
    // include test patteern  ------------
    
    initial begin
    
      $display (" ") ;
      #200
    
      @(posedge clk) #1
      adr    = 4'h2   ;     // rise_pos 0
      data   = 8'h10  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'h3   ;     // fall_pos 0
      data   = 8'h14  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
    
      @(posedge clk) #1
      adr    = 4'h4   ;     // rise_pos 1
      data   = 8'h20  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'h5   ;     // fall_pos 1
      data   = 8'h28  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
    
      @(posedge clk) #1
      adr    = 4'h6   ;     // rise_pos 2
      data   = 8'h30  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'h7   ;     // fall_pos 2
      data   = 8'h3f  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
    
      @(posedge clk) #1
      adr    = 4'h8   ;     // rise_pos 3
      data   = 8'h12  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'h9   ;     // fall_pos 3
      data   = 8'h38  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
    
      @(posedge clk) #1
      adr    = 4'ha   ;     // rise_pos 4
      data   = 8'h3e  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'hb   ;     // fall_pos 4
      data   = 8'h3f  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
    
      @(posedge clk) #1
      adr    = 4'hc   ;     // rise_pos 5
      data   = 8'h0f  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'hd   ;     // fall_pos 5
      data   = 8'h10  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
    
      @(posedge clk) #1
      adr    = 4'he   ;     // rise_pos 6
      data   = 8'h20  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'hf   ;     // fall_pos 7
      data   = 8'h21  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
    
      @(posedge clk) #1
      adr    = 4'h1   ;     // count max 
      data   = 8'h50  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'h0   ;     // count start on
      data   = 8'h01  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
      @(posedge clk) #1
      @(posedge clk) #1
      adr    = 4'h0   ;     // count start off
      data   = 8'h00  ;
      we     = 1'b1   ;
      @(posedge clk) #1
      we     = 1'b0   ;
    
      repeat(100) @(posedge clk)  ;
    
      $display ("test_END");
    
      $finish ;
    end
    
    // include assertion bind list -------
    //`include "bind.list"
    //`include "bind_sva.sv"
    //`include "sva_1.sv"
    
    endmodule
    

    シミュレーション結果を以下に示す。
    コマンドラインからの VCD出力では 2次元配列の信号が表示されなかった為、vivado GUI でのシミュレーション波形を表示。pls0 のみ レジスタブロックとパルス生成ブロックの2次元配列を表示。(他は パルス生成ブロックのみ)