南大数字逻辑与计算机组成课程实验三加法器与ALU 思路与代码参考

top.v

module top(
  input [3:0] A,
  input [3:0] B,
  input [2:0] ALUctr,
  output reg [3:0] ALUout,
  output reg [3:0] temp,
  output reg less,
  output reg of,zf,cf
);
reg [3:0] xb;
always@(*)begin
  ALUout = 4'b0;temp = 4'b0; less = 1'b0; of = 0; zf = 0; cf = 0; xb = 4'd0; // 初始化
  casez(ALUctr)
    3'b00z:begin // add or sub
      xb = B ^ { {4{ALUctr[0]}} };  // 根据最后一位确定加减法 加:000 减:001 减法则取反
      {cf,ALUout} = xb + A + {3'b0,ALUctr[0]};
	    of = (A[3] == xb[3]) && (ALUout[3] != A[3]);
	    zf = ~(|ALUout);
    end
    3'b011:begin // and
      ALUout = A & B;
    end
    3'b100:begin // or
      ALUout = A | B;
    end
    3'b101:begin // xor
      ALUout = A ^ B;
    end
    3'b110:begin // cmp
      xb = B ^ 4'b1111;  // 用减法进行比较大小
      {cf,temp} = xb + A + 4'b1;
      of = (A[3] == xb[3]) && (temp[3] != A[3]);
	    zf = ~(|temp);
      less = temp[3] ~^ of;
      if(less == 0) ALUout = 4'b1;
      else ALUout = 4'b0;
    end
    3'b111:begin // equl
      xb = B ^ 4'b1111;
      {cf,temp} = xb + A + 4'b1;
      of = (A[3] == xb[3]) && (temp[3] != A[3]);
	    zf = ~(|temp);
      if(zf == 1) ALUout = 4'b1;
      else ALUout = 4'b0;
    end
    default:ALUout = 4'b0; // avoid latch
  endcase
end
endmodule

为什么不用方法二进行减法overflow计算

assign t_add_Cin =( {n{Cin}}^B )+ Cin;  //  在这里请注意^运算和+运算的顺序
assign { Carry, Result } = A + t_add_Cin;
assign Overflow = (A[n-1] == t_add_Cin[n-1]) && (Result [n-1] != A[n-1]);

参考A=0111 B=1000时的情况,方法二不能正确判断overflow

sim_main.cpp

sim_main.cpp的说明可见文章

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<nvboard.h>

#include"Vtop.h"
#include"verilated.h"
#include"verilated_vcd_c.h"

void nvboard_bind_all_pins(Vtop* top);

int main(int argc, char** argv) {
    VerilatedContext* contextp = new VerilatedContext;
    contextp->traceEverOn(true);
    contextp->commandArgs(argc, argv);

    Vtop* top = new Vtop{contextp};

    nvboard_bind_all_pins(top);
    nvboard_init();
    VerilatedVcdC* m_trace = new VerilatedVcdC;
    top->trace(m_trace, 99);
    m_trace->open("wave.vcd");
    
    while (!contextp->gotFinish()) {
	nvboard_update();
        contextp->timeInc(1);
        //----测试----
        top->A = 0b0001;
        top->B = 0b0001;
        top->ALUctr = 0b000;
        //----测试---- 此处为测试:1 + 1
        top->eval();
        m_trace->dump(contextp->time());
    }
    m_trace->close();
    delete top;
    delete contextp;
    return 0;
}

Makefile

参考NVBoard的Makefile
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

$(BIN): $(VSRCS) $(CSRCS) $(NVBOARD_ARCHIVE)
	@rm -rf $(OBJ_DIR) wave.vcd
	$(VERILATOR) $(VERILATOR_CFLAGS) \
		--top-module $(TOPNAME) $^ \
		$(addprefix -CFLAGS , $(CXXFLAGS)) $(addprefix -LDFLAGS , $(LDFLAGS)) \
		--Mdir $(OBJ_DIR) --exe -o $(abspath $(BIN))

all: default

run: $(BIN)
	./build/top +trace
	gtkwave wave.vcd

clean:
	rm -rf $(BUILD_DIR) wave.vcd

.PHONY: default all clean run

接入NVBoard

可以用NVBoard进行数据输入和输出,在top.nxdc文件中进行引脚绑定。

top=top
A (SW3,SW2,SW1,SW0)
B (SW7,SW6,SW5,SW4)
ALUctr (SW10,SW9,SW8)
ALUout (SW15,SW14,SW13,SW12)

演示一下1+1
nv
SW每一位代表二进制中的每一位,图为0001(A)+0001(B) = 0010(ALUout)

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值