南大数字逻辑与计算机组成课程实验六移位寄存器和桶形移位器 思路与代码参考

桶形移位器

module barrel_shifter(shamt,din,LR,AL,dout);
input [2:0] shamt;
input [7:0] din;
input LR;  // left:LR = 1, rgiht:LR = 0
input AL;  // athi:AL = 1, logical:AL = 0
output reg [7:0] dout;

always @(*) begin
    if(LR == 1)begin  // left shift
        dout = shamt[2] ? {din[3:0], 4'b0} : din;
        dout = shamt[1] ? {dout[5:0], 2'b0} : dout;
        dout = shamt[0] ? {dout[6:0], 1'b0} : dout;
    end

    else begin  // right shift
        if(AL == 1)begin  
            dout = shamt[2] ? {{ 4{din[7]}}, din[7:4]} : din;
            dout = shamt[1] ? {{ 2{dout[7]}}, dout[7:2]} : dout;
            dout = shamt[0] ? {{ 1{dout[7]}}, dout[7:1]} : dout;
        end
        else begin
            dout = shamt[2] ? {4'b0, din[7:4]} : din;
            dout = shamt[1] ? {2'b0, dout[7:2]} : dout;
            dout = shamt[0] ? {1'b0, dout[7:1]} : dout;      
        end
    end
end

endmodule

主要思想是根据shamt的值来确定移位,第一级利用shamt[0]来控制是否需要移动一位,第二级在第一级的移动结果上用shamt[1]来控制是否要移动两位,第三级在第二级的基础上再对应判断是否要移动四位。例如shamt为111,即移动1位+移动2位+移动4位=移动7位。

随机数发生器

top.v

module top (
  input clk,
  input rst,
  output reg [7:0] num,
  output reg [3:0] num0,
  output reg [3:0] num1,
  output reg [6:0] seg0,
  output reg [6:0] seg1
);
reg x;
always@(posedge clk)begin
  if(rst) begin num = 8'b00000001;end 
  else begin
    x = num[4] ^ num[3] ^ num[2] ^ num[0]; // 串行阻塞赋值
    num = {x,num[7:1]}; 
  end
end
assign num0 = num[3:0];
assign num1 = num[7:4];

seg my_seg(
  .clk(clk),
  .rst(rst),
  .num0(num0),
  .num1(num1),
  .seg0(seg0),
  .seg1(seg1)
);
endmodule

由于x要先于下一条语句算出 所以使用串行阻塞赋值。
=为阻塞赋值 有先后顺序。 <=为非阻塞赋值,所有语句一起执行。
begin ··· end为串行语句, fork ··· join为并行语句。

seg.v

module seg (
    input clk,
    input rst,
    input [3:0] num0,
    input [3:0] num1,
    output reg [6:0] seg0,
    output reg [6:0] seg1
);
wire [6:0] segs [15:0];
assign segs[0]  = 7'b0000001; // nvboard 0为发光 1为熄灭
assign segs[1]  = 7'b1001111;
assign segs[2]  = 7'b0010010;
assign segs[3]  = 7'b0000110;
assign segs[4]  = 7'b1001100;
assign segs[5]  = 7'b0100100;
assign segs[6]  = 7'b0100000;
assign segs[7]  = 7'b0001111;
assign segs[8]  = 7'b0000000;
assign segs[9]  = 7'b0001100;
assign segs[10] = 7'b0001000;
assign segs[11] = 7'b1100000;
assign segs[12] = 7'b0110001;
assign segs[13] = 7'b1000010;
assign segs[14] = 7'b0110000;
assign segs[15] = 7'b0111000;
always@(posedge clk)begin
    case (num0)
        4'd0 :seg0 = segs[0];
        4'd1 :seg0 = segs[1];
        4'd2 :seg0 = segs[2];
        4'd3 :seg0 = segs[3];
        4'd4 :seg0 = segs[4];
        4'd5 :seg0 = segs[5];
        4'd6 :seg0 = segs[6];
        4'd7 :seg0 = segs[7];
        4'd8 :seg0 = segs[8];
        4'd9 :seg0 = segs[9];
        4'd10:seg0 = segs[10];
        4'd11:seg0 = segs[11];
        4'd12:seg0 = segs[12];
        4'd13:seg0 = segs[13];
        4'd14:seg0 = segs[14];
        4'd15:seg0 = segs[15];
        default: seg0 = segs[0];
    endcase
        case (num1)
        4'd0 :seg1 = segs[0];
        4'd1 :seg1 = segs[1];
        4'd2 :seg1 = segs[2];
        4'd3 :seg1 = segs[3];
        4'd4 :seg1 = segs[4];
        4'd5 :seg1 = segs[5];
        4'd6 :seg1 = segs[6];
        4'd7 :seg1 = segs[7];
        4'd8 :seg1 = segs[8];
        4'd9 :seg1 = segs[9];
        4'd10:seg0 = segs[10];
        4'd11:seg0 = segs[11];
        4'd12:seg0 = segs[12];
        4'd13:seg0 = segs[13];
        4'd14:seg0 = segs[14];
        4'd15:seg0 = segs[15];
        default: seg1 = segs[0];
    endcase
end
endmodule

sim_mian.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");
    
    top->clk = 0;
    top->rst = 1;
    while (!contextp->gotFinish()) {
        contextp->timeInc(1);
        nvboard_update();
        //top->clk = !top->clk; // 用按钮控制clk 所以不需要在这里更新clk
        top->eval();
        m_trace->dump(contextp->time());
    }
    m_trace->close();
    delete top;
    delete contextp;
    return 0;
}    

top.nxdc

top=top

clk SW1
rst SW0
seg0 (SEG0A, SEG0B, SEG0C, SEG0D, SEG0E, SEG0F, SEG0G)
seg1 (SEG1A, SEG1B, SEG1C, SEG1D, SEG1E, SEG1F, SEG1G)

注意首先要在rst=1下用按钮给几个时钟上升沿用于初始化
wave

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值