シフトレジスタとバレルシフタの実装

論理シフトと算術シフトの8ビットレジスタ

module shift_unit_8bit (
    input clock,            
    input reset,            
    input [2:0] operation,  
    input [7:0] parallel_input, 
    input serial_data,      
    input shift_direction,  
    output reg [7:0] parallel_output
);

    reg [7:0] storage_reg;
    
    always @(posedge clock or posedge reset) begin
        if (reset) begin
            storage_reg <= 8'd0;
        end else begin
            case(operation)
                3'b000: storage_reg <= 8'd0;
                3'b001: storage_reg <= parallel_input;
                3'b010: storage_reg <= {shift_direction, storage_reg[7:1]};
                3'b011: storage_reg <= {storage_reg[6:0], shift_direction};
                3'b100: storage_reg <= {storage_reg[7], storage_reg[7:1]};
                3'b101: storage_reg <= {storage_reg[6:0], serial_data};
                3'b110: storage_reg <= {storage_reg[0], storage_reg[7:1]};
                3'b111: storage_reg <= {storage_reg[6:0], storage_reg[7]};
                default: storage_reg <= storage_reg;
            endcase
        end
    end
    
    always @(*) begin
        parallel_output = storage_reg;
    end

endmodule

RV32I命令セット対応の32ビットシフタ

module barrel_shifter_32 (
    input [31:0] input_data,
    input [4:0]  shift_amount,
    input [1:0]  operation_type,
    output [31:0] result
);
    reg [31:0] shifted_result;
    
    always @(*) begin
        case(operation_type)
            2'b00: shifted_result = input_data << shift_amount;
            2'b01: shifted_result = input_data >> shift_amount;
            2'b10: shifted_result = $signed(input_data) >>> shift_amount;
            default: shifted_result = input_data;
        endcase
    end
    
    assign result = shifted_result;
endmodule

線形フィードバックシフトレジスタによる乱数生成

プロジェクト構成

.
├── constr
│   └── top.nxdc
├── csrc
│   └── simulation_test.cpp
├── Makefile
├── vsrc
│   └── top_module.v
├── top_module.v
├── vlt_trace.vcd
├── simulation_test.cpp
├── obj_dir
└── waveform.vcd

ピン配置ファイル (constr/top.nxdc)

top=top

button BTNL

rst_n BTNC

leds (LD7, LD6, LD5, LD4, LD3, LD2, LD1, LD0)
hex0 (SEG0A, SEG0B, SEG0C, SEG0D, SEG0E, SEG0F, SEG0G, DEC0P)
hex1 (SEG1A, SEG1B, SEG1C, SEG1D, SEG1E, SEG1F, SEG1G, DEC1P)

テストベンチ (csrc/simulation_test.cpp)

#include<nvboard.h>
#include<Vtop_module.h>

static TOP_NAME device;
 
void nvboard_bind_all_pins(TOP_NAME* top);
 
static void cycle(){
    device.eval();
}
  
int main(){
    nvboard_bind_all_pins(&device);
    nvboard_init();
    
    while(1){
        nvboard_update();
        cycle();
    }
}

シミュレーションコード (simulation_test.cpp)

#include "verilated.h"
#include "verilated_vcd_c.h"
#include "obj_dir/Vtop_module.h"

VerilatedContext* ctx = NULL;
VerilatedVcdC* vcd = NULL;

#define SIMULATION_TIME 20
int current_time = 0;

static Vtop_module* dut;

void execute_cycle(){
  dut->eval();
  ctx->timeInc(1);
  vcd->dump(ctx->time());
}

void initialize_simulation(){
  ctx = new VerilatedContext;
  vcd = new VerilatedVcdC;
  dut = new Vtop_module;
  ctx->traceEverOn(true);
  dut->trace(vcd, 0);
  vcd->open("waveform.vcd");
}

void finalize_simulation(){
  execute_cycle();
  vcd->close();
}

int main() {
  initialize_simulation();

  while (current_time < SIMULATION_TIME) {
      dut->button ^=1;
      execute_cycle();
      current_time ++;
  } 
  
  finalize_simulation();
}

トップモジュール (vsrc/top_module.v)

module top_module (
    input push_button,
    input reset_n,
    output [7:0] display_low,
    output [7:0] display_high,
    output [7:0] led_status
);

    reg [7:0] lfsr_reg = 8'b00000001;
    
    wire feedback_bit = lfsr_reg[4] ^ lfsr_reg[3] ^ lfsr_reg[2] ^ lfsr_reg[0];
    
    always @(negedge push_button or posedge reset_n) begin
        if (reset_n) 
            lfsr_reg <= 8'b00000001;
        else begin
            lfsr_reg <= {feedback_bit, lfsr_reg[7:1]};
            if (lfsr_reg == 8'b0) 
                lfsr_reg <= 8'b00000001;
        end
    end
    
    seg7_decoder digit_0 (.binary(lfsr_reg[3:0]), .segments(display_low));
    seg7_decoder digit_1 (.binary(lfsr_reg[7:4]), .segments(display_high));
    
    assign led_status = lfsr_reg;

endmodule

module seg7_decoder (
    input [3:0] binary,
    output reg [7:0] segments
);

always @(*) begin
    case(binary)
        4'h0: segments = 8'b00000011;
        4'h1: segments = 8'b10011111;
        4'h2: segments = 8'b00100101;
        4'h3: segments = 8'b00001101;
        4'h4: segments = 8'b10011001;
        4'h5: segments = 8'b01001001;
        4'h6: segments = 8'b01000001;
        4'h7: segments = 8'b00011111;
        4'h8: segments = 8'b00000001;
        4'h9: segments = 8'b00001001;
        4'hA: segments = 8'b00010001;
        4'hB: segments = 8'b11000001;
        4'hC: segments = 8'b01100011;
        4'hD: segments = 8'b10000101;
        4'hE: segments = 8'b01100001;
        4'hF: segments = 8'b01110001;
        default: segments = 8'b11111111;
    endcase
end

endmodule

簡略化されたトップモジュール (top_module.v)

module top_module (
    input push_button,
    output [7:0] led_status
);

    reg [7:0] lfsr_reg = 8'b00000001;
    
    wire feedback_bit = lfsr_reg[4] ^ lfsr_reg[3] ^ lfsr_reg[2] ^ lfsr_reg[0];
    
    always @(negedge push_button) begin
        lfsr_reg <= {feedback_bit, lfsr_reg[7:1]};
        if (lfsr_reg == 8'b0) 
            lfsr_reg <= 8'b00000001;
    end
    
    assign led_status = lfsr_reg;

endmodule

シミュレーション手順

(1) コンパイル
verilator -Wall --trace -cc top_module.v --exe simulation_test.cpp

(2) 実行ファイル生成
make -C obj_dir -f Vtop_module.mk Vtop_module

(3) 波形データ生成
./obj_dir/Vtop_module

(4) 波形表示
gtkwave waveform.vcd

NVBoard接続手順

make
cd build
./top_module

タグ: Verilog SystemVerilog FPGA DigitalDesign ShiftRegister

6月1日 02:58 投稿