論理シフトと算術シフトの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