2対4デコーダとエンコーダ回路のVerilog設計手法

2対4デコーダの論理構成

2ビットの選択信号に基づき、4本の出力線の中から1本のみをアクティブレベルに切り替える組合せ回路です。制御信号が非アクティブの場合は全出力がリセットされます。

module dec_2to4 (
    input  wire       enable_ctrl,
    input  wire [1:0] addr_sel,
    output reg  [3:0] led_drv
);
    always @(*) begin
        if (enable_ctrl) begin
            case (addr_sel)
                2'b00: led_drv = 4'b0001;
                2'b01: led_drv = 4'b0010;
                2'b10: led_drv = 4'b0100;
                2'b11: led_drv = 4'b1000;
                default: led_drv = 4'b0000;
            endcase
        end else begin
            led_drv = 4'b0000;
        end
    end
endmodule

4対2エンコーダの実装

4本の入力信号のうち、ハイ状態にあるビットのインデックスを2ビットのバイナリ値に変換します。複数の入力が同時にハイとなる場合は、定義された優先順位または排他制御が想定されます。

module enc_4to2 (
    input  wire       enable_ctrl,
    input  wire [3:0] btn_req,
    output reg  [1:0] bin_code
);
    always @(*) begin
        if (enable_ctrl) begin
            if (btn_req == 4'b0001)      bin_code = 2'b00;
            else if (btn_req == 4'b0010) bin_code = 2'b01;
            else if (btn_req == 4'b0100) bin_code = 2'b10;
            else if (btn_req == 4'b1000) bin_code = 2'b11;
            else                         bin_code = 2'b00;
        end else begin
            bin_code = 2'b00;
        end
    end
endmodule

優先度エンコーダ(4入力および8入力)

複数の入力が同時にアサートされた場合、最上位ビット(MSB側)の信号を優先して符号化します。有効な入力の存在を検知するためのバリデーション信号も併設します。

4入力優先エンコーダ

module prio_enc_4to2 (
    input  wire       enable_ctrl,
    input  wire [3:0] data_in,
    output reg  [1:0] out_val
);
    integer k;
    always @(*) begin
        out_val = 2'b00;
        if (enable_ctrl) begin
            for (k = 0; k <= 3; k = k + 1) begin
                if (data_in[k]) begin
                    out_val = k[1:0];
                end
            end
        end
    end
endmodule

8入力優先エンコーダと7セグメント表示連動

8ビット入力を受け付け、3ビットコードに変換すると同時に、結果を7セグメントLEDドライバに渡して可視化します。

module prio_enc_8to3 (
    input  wire       enable_ctrl,
    input  wire [7:0] data_bus,
    output reg  [2:0] code_out,
    output wire       valid_flag
);
    assign valid_flag = enable_ctrl && (|data_bus);
    
    always @(*) begin
        if (enable_ctrl) begin
            casez (data_bus)
                8'b1???????: code_out = 3'b111;
                8'b01??????: code_out = 3'b110;
                8'b001?????: code_out = 3'b101;
                8'b0001????: code_out = 3'b100;
                8'b00001???: code_out = 3'b011;
                8'b000001??: code_out = 3'b010;
                8'b0000001?: code_out = 3'b001;
                8'b00000001: code_out = 3'b000;
                default:     code_out = 3'b000;
            endcase
        end else begin
            code_out = 3'b000;
        end
    end
endmodule

module seg_driver (
    input  wire [2:0] hex_in,
    output wire [7:0] seg_lines
);
    reg [7:0] pattern;
    always @(*) begin
        case (hex_in)
            3'b000: pattern = 8'b11111101;
            3'b001: pattern = 8'b01100000;
            3'b010: pattern = 8'b11011010;
            3'b011: pattern = 8'b11110010;
            3'b100: pattern = 8'b01100110;
            3'b101: pattern = 8'b10110110;
            3'b110: pattern = 8'b10111110;
            3'b111: pattern = 8'b11100000;
            default: pattern = 8'b11111111;
        endcase
    end
    assign seg_lines = ~pattern; // 共カソード/アノード反転対応
endmodule

module top_system (
    input  wire [7:0] sw_in,
    input  wire       enable_sw,
    output wire [2:0] led_code,
    output wire       led_valid,
    output wire [7:0] seg_disp
);
    prio_enc_8to3 u_enc (
        .enable_ctrl(enable_sw),
        .data_bus(sw_in),
        .code_out(led_code),
        .valid_flag(led_valid)
    );
    seg_driver u_seg (
        .hex_in(led_code),
        .seg_lines(seg_disp)
    );
endmodule

検証環境の構築とハードウェア連携

C++シミュレーションテストベンチ

VerilatorおよびNVBoard双方で利用可能な検証スキャフォールディングです。波形取得とクロック単位の評価を分離し、テストベクタの投入を簡素化します。

#include "verilated.h"
#include "verilated_vcd_c.h"
#include "Vtop_system.h"

static VerilatedContext* ctx_handle = nullptr;
static VerilatedVcdC* trace_ptr = nullptr;
static Vtop_system* dut_ptr = nullptr;

void setup_context() {
    ctx_handle = new VerilatedContext;
    trace_ptr  = new VerilatedVcdC;
    dut_ptr    = new Vtop_system;
    
    ctx_handle->traceEverOn(true);
    dut_ptr->trace(trace_ptr, 0);
    trace_ptr->open("waveform.vcd");
}

void apply_input_and_step(const uint8_t en, const uint32_t data) {
    dut_ptr->enable_sw = en;
    dut_ptr->sw_in     = data;
    dut_ptr->eval();
    ctx_handle->timeInc(1);
    trace_ptr->dump(ctx_handle->time());
}

void teardown_context() {
    apply_input_and_step(0, 0);
    trace_ptr->close();
    delete dut_ptr;
    delete trace_ptr;
    delete ctx_handle;
}

int main(int argc, char** argv) {
    setup_context();
    
    // 検証ベクタ投入
    apply_input_and_step(0b0, 0x00);
    apply_input_and_step(0b1, 0x03);
    apply_input_and_step(0b1, 0x06);
    apply_input_and_step(0b1, 0x04);
    apply_input_and_step(0b1, 0x08);
    apply_input_and_step(0b1, 0x10);
    apply_input_and_step(0b1, 0x40);
    apply_input_and_step(0b1, 0x80);
    
    teardown_context();
    return 0;
}

NVBoard連携用エントリーポイント

ハードウェアボード上でリアルタイムに入出力を反映させるためのバインディングループです。

#include <nvboard.h>
#include "Vtop_system.h"

static Vtop_system board_dut;

void nvboard_bind_all_pins(Vtop_system* top);

void clock_tick() {
    board_dut.eval();
}

int main() {
    nvboard_bind_all_pins(&board_dut);
    nvboard_init();
    
    while (true) {
        nvboard_update();
        clock_tick();
    }
    return 0;
}

ピンアサイン定義(.nxdc)

top=top_system

sw_in (SW7, SW6, SW5, SW4, SW3, SW2, SW1, SW0)
enable_sw (SW8)

led_code (LD2, LD1, LD0)
led_valid (LD4)
seg_disp (SEG0A, SEG0B, SEG0C, SEG0D, SEG0E, SEG0F, SEG0G, DEC0P)

ビルドおよび実行ワークフロー

# 1. VerilatorによるC++コード生成とコンパイル
verilator -Wall --trace -cc top_system.v seg_driver.v --exe sim_main.cpp

# 2. Makefileを用いた実行ファイル生成
make -C obj_dir -f Vtop_system.mk

# 3. シミュレーション実行とVCD波形生成
./obj_dir/Vtop_system

# 4. GTKWaveによる波形可視化
gtkwave waveform.vcd

# 5. NVBoard環境でのハードウェアビルド
make
cd build
./top_system

タグ: Verilog fpga-design verilator nvboard digital-circuit

7月12日 23:31 投稿