1.搭建verilator仿真环境
1.1安装verilator
参考Unbuntu22.04安装Verilator --5.008_help2man-CSDN博客
1.2双控开关
1.2.1 搭建工程框架
constr存top.nxdc约束文件,crsc存main.cpp文件,vsrc存各种.v文件。
1.2.2 编写top.v文件
module top(
input a,
input b,
output f
);
assign f = a ^ b;
endmodule
1.2.3 编写main.cpp文件
#include <nvboard.h>
#include <Vtop.h>
static TOP_NAME dut;
void nvboard_bind_all_pins(TOP_NAME* top);
nvboard_bind_all_pins(&dut);
nvboard_init();
int main() {
while(1) {
nvboard_update();
dut.eval(); /
}
}
1.2.4 编写top.nxdc文件
top=top
a SW0
b SW1
f LD0
需要运行
python3 $"NVBOARD_HOME"/scripts/auto_pin_bind.py nxdc约束文件路径 auto_bind.cpp输出路径
来生成C++文件
1.2.5 编写Makefile文件
TOPNAME = top
NXDC_FILES = constr/top.nxdc
INC_PATH ?=
VERILATOR = verilator
VERILATOR_CFLAGS += -MMD --build --trace -cc \
-O3 --x-assign fast --x-initial fast --noassert
BUILD_DIR = ./build
OBJ_DIR = $(BUILD_DIR)/obj_dir
BIN = $(BUILD_DIR)/$(TOPNAME)
default: $(BIN)
$(shell mkdir -p $(BUILD_DIR))
# constraint file
SRC_AUTO_BIND = $(abspath $(BUILD_DIR)/auto_bind.cpp)
$(SRC_AUTO_BIND): $(NXDC_FILES)
python3 $(NVBOARD_HOME)/scripts/auto_pin_bind.py $^ $@
# project source
VSRCS = $(shell find $(abspath ./vsrc) -name "*.v")
CSRCS = $(shell find $(abspath ./csrc) -name "*.c" -or -name "*.cc" -or -name "*.cpp")
CSRCS += $(SRC_AUTO_BIND)
# rules for NVBoard
include $(NVBOARD_HOME)/scripts/nvboard.mk
# rules for verilator
INCFLAGS = $(addprefix -I, $(INC_PATH))
CXXFLAGS += $(INCFLAGS) -DTOP_NAME="\"V$(TOPNAME)\""
LDFLAGS += -lSDL2 -lSDL2_image
sim: $(VSRCS) $(CSRCS) $(NVBOARD_ARCHIVE)
$(call git_commit, "sim RTL") # DO NOT REMOVE THIS LINE!!!
@rm -rf $(OBJ_DIR)
$(VERILATOR) $(VERILATOR_CFLAGS) \
--top-module $(TOPNAME) $^ \
$(addprefix -CFLAGS , $(CXXFLAGS)) $(addprefix -LDFLAGS , $(LDFLAGS)) \
--Mdir $(OBJ_DIR) --exe -o $(abspath $(BIN))
all:default
@echo "Write this Makefile by your self."
clean:rm -rf $(BUILD_DIR)
include ../Makefile
.PHONY: default all clean runun
2.数字电路基础实验
2.1.实验一:选择器
top.v
module top(a, y, f);
input [7:0] a;
input [1:0] y;
output [1:0] f;
/* verilator lint_off WIDTHTRUNC */
MuxKeyWithDefault #(4, 2, 2) i0 (f, y, 2'b00, {
2'b00, a[1:0],
2'b01, a[3:2],
2'b10, a[5:4],
2'b11, a[7:6]
});
/* verilator lint_off WIDTHTRUNC */
endmodule
module MuxKeyInternal #(NR_KEY = 2, KEY_LEN = 1, DATA_LEN = 1, HAS_DEFAULT = 0) (
output reg [DATA_LEN-1:0] out,
input [KEY_LEN-1:0] key,
input [DATA_LEN-1:0] default_out,
input [NR_KEY*(KEY_LEN + DATA_LEN)-1:0] lut
);
localparam PAIR_LEN = KEY_LEN + DATA_LEN;
wire [PAIR_LEN-1:0] pair_list [NR_KEY-1:0];
wire [KEY_LEN-1:0] key_list [NR_KEY-1:0];
wire [DATA_LEN-1:0] data_list [NR_KEY-1:0];
generate
for (genvar n = 0; n < NR_KEY; n = n + 1) begin
assign pair_list[n] = lut[PAIR_LEN*(n+1)-1 : PAIR_LEN*n];
assign data_list[n] = pair_list[n][DATA_LEN-1:0];
assign key_list[n] = pair_list[n][PAIR_LEN-1:DATA_LEN];
end
endgenerate
reg [DATA_LEN-1 : 0] lut_out;
reg hit;
integer i;
always @(*) begin
lut_out = 0;
hit = 0;
for (i = 0; i < NR_KEY; i = i + 1) begin
lut_out = lut_out | ({DATA_LEN{key == key_list[i]}} & data_list[i]);
hit = hit | (key == key_list[i]);
end
if (!HAS_DEFAULT) out = lut_out;
else out = (hit ? lut_out : default_out);
end
endmodule
module MuxKey #(NR_KEY = 2, KEY_LEN = 1, DATA_LEN = 1) (
output [DATA_LEN-1:0] out,
input [KEY_LEN-1:0] key,
input [NR_KEY*(KEY_LEN + DATA_LEN)-1:0] lut
);
MuxKeyInternal #(NR_KEY, KEY_LEN, DATA_LEN, 0) i0 (out, key, {DATA_LEN{1'b0}}, lut);
endmodule
module MuxKeyWithDefault #(NR_KEY = 2, KEY_LEN = 1, DATA_LEN = 1) (
output [DATA_LEN-1:0] out,
input [KEY_LEN-1:0] key,
input [DATA_LEN-1:0] default_out,
input [NR_KEY*(KEY_LEN + DATA_LEN)-1:0] lut
);
MuxKeyInternal #(NR_KEY, KEY_LEN, DATA_LEN, 1) i0 (out, key, default_out, lut);
endmodule
top.nxdc
top=top
a (SW9, SW8, SW7, SW6, SW5, SW4, SW3, SW2)
y (SW1, SW0)
f (LD1, LD0)
main.cpp
#include <nvboard.h>
#include <Vtop.h>
static TOP_NAME dut;
void nvboard_bind_all_pins(Vtop* top);
int main() {
nvboard_bind_all_pins(&dut);
nvboard_init();
while(1) {
nvboard_update();
dut.eval();
}
}
2.2.实验二:译码器和编码器
encode83.v
module encode83(
input [7:0]x,
input en,
output reg [2:0]y,
output reg l);
/* verilator lint_off CASEOVERLAP */
always @(x or en) begin
if(en) begin
casez(x)
8'bzzzz_zzz1:begin y = 3'b000; l = 1;end
8'bzzzz_zz1z:begin y = 3'b001; l = 1;end
8'bzzzz_z1zz:begin y = 3'b010; l = 1;end
8'bzzzz_1zzz:begin y = 3'b011; l = 1;end
8'bzzz1_zzzz:begin y = 3'b100; l = 1;end
8'bzz1z_zzzz:begin y = 3'b101; l = 1;end
8'bz1zz_zzzz:begin y = 3'b110; l = 1;end
8'b1zzz_zzzz:begin y = 3'b111; l = 1;end
default:begin y = 3'b000; l = 0; end
endcase
end
end
/* verilator lint_on CASEOVERLAP */
endmodule
bcd7seg.v
module bcd7seg(
input [3:0] b,
output reg [6:0] h
);
always @(b) begin
case(b)
4'b000 : h = 7'b1000000;
4'b001 : h = 7'b1111001;
4'b010 : h = 7'b0100100;
4'b011 : h = 7'b0110000;
4'b100 : h = 7'b0011001;
4'b101 : h = 7'b0010010;
4'b110 : h = 7'b0000010;
4'b111 : h = 7'b1111000;
default : h = 0;
endcase
end
endmodule
top.v
module top(
input [7:0]x,
input en,
output [2:0]y,
output l,
output [6:0] h
);
encode83 i0(.x(x), .en(en), .y(y), .l(l));
/* verilator lint_off WIDTHEXPAND */
bcd7seg i1(.b(y), .h(h));
/* verilator lint_on WIDTHEXPAND */
endmodule
top.nxdc
top=top
x (SW7, SW6, SW5, SW4, SW3, SW2, SW1, SW0)
en (SW8)
y (LD2, LD1, LD0)
l (LD4)
h (SEG0G, SEG0F, SEG0E, SEG0D, SEG0C, SEG0B, SEG0A)