远程FPGA虚拟实验平台用SystemVerilog HDL实现寄存器组和堆

原理

单端口寄存器组

单端口寄存器组在实验平台的图如下:单端口寄存器顶层图
由图可知,单端口寄存器组的单端口指的是写入和读取的地址用的是来自一个端口的信号,在Load=1时,可以通过D,Index和时钟信号写入寄存器的值,同时,由于只有一个端口,四选一多路器读取的值是和写入的值同步的。

三端口寄存器堆

三端口寄存器堆的原理如下:
三端口寄存器堆顶层图
由图可知,三端口寄存器组较单端口寄存器堆多了一个多路选择器和输出。同时多了两个输入地址的端口RA1和RA2,用以控制两个多路选择器读哪个寄存器的值,这使得它可以在写入1个寄存器的同时读出2个不同寄存器的值。

源代码

单端口寄存器组

VirtalBoard模块

实验面板:

`default_nettype none 
module VirtualBoard (
    input  logic  CLOCK,      // 10 MHz Input Clock 
    input  logic [19:0] PB,   // 20 Push Buttons, logical 1 when pressed
    input  logic [35:0] S,    // 36 Switches
    output logic [35:0] L,    // 36 LEDs, drive logical 1 to light up
    output logic  [7:0] SD7,  // 8 common anode Seven-segment Display
    output logic  [7:0] SD6,
    output logic  [7:0] SD5,
    output logic  [7:0] SD4,
    output logic  [7:0] SD3,
    output logic  [7:0] SD2,
    output logic  [7:0] SD1,
    output logic  [7:0] SD0
);

一堆七段译码器的实例化:

logic [3:0] HD[7:0];  // 8 hexadecimal display 
SevenSegDecode ssdecode_inst7(.iData(HD[7]), .oSeg(SD7));
SevenSegDecode ssdecode_inst6(.iData(HD[6]), .oSeg(SD6));
SevenSegDecode ssdecode_inst5(.iData(HD[5]), .oSeg(SD5));
SevenSegDecode ssdecode_inst4(.iData(HD[4]), .oSeg(SD4));
SevenSegDecode ssdecode_inst3(.iData(HD[3]), .oSeg(SD3));
SevenSegDecode ssdecode_inst2(.iData(HD[2]), .oSeg(SD2));
SevenSegDecode ssdecode_inst1(.iData(HD[1]), .oSeg(SD1));
SevenSegDecode ssdecode_inst0(.iData(HD[0]), .oSeg(SD0));

单端口需要的线路:

/** The input port is replaced with an internal signal **/
wire clk    = PB[1];//时钟信号
wire [3:0] Data  = S[3:0];//数据
wire [1:0] Index = S[5:4];//地址
wire Load = S[6];//使能信号

实验逻辑部分:

localparam N = 4;//参数化设计
// 2-4 decode 二四译码器
logic load3, load2, load1, load0;
always_comb begin
    if (Load)
        case (Index)//用四种状态控制四个寄存器的使能信号load
            2'b00: {load3, load2, load1, load0} = 4'b0001;
            2'b01: {load3, load2, load1, load0} = 4'b0010;
			2'b10: {load3, load2, load1, load0} = 4'b0100;
			2'b11: {load3, load2, load1, load0} = 4'b1000;
            default: {load3, load2, load1, load0} = 4'bx;
        endcase
    else
        {load3, load2, load1, load0} = 4'b0000;
end

// register instantiation 译码器的实例化
logic [N-1:0] R0_Q, R1_Q, R2_Q, R3_Q;
DataReg #(N) R0(.oQ(R0_Q), .iD(Data), .Clk(clk), .Load(load0), .Reset(1'b0));//由于本实验没有用到复位信号,所以reset恒为0,在待会的三端口寄存器堆里可以将第一个寄存器的信号设置为1使它无法存值
DataReg #(N) R1(.oQ(R1_Q), .iD(Data), .Clk(clk), .Load(load1), .Reset(1'b0));
DataReg #(N) R2(.oQ(R2_Q), .iD(Data), .Clk(clk), .Load(load2), .Reset(1'b0));
DataReg #(N) R3(.oQ(R3_Q), .iD(Data), .Clk(clk), .Load(load3), .Reset(1'b0));

// 4-1 MUX 四选一多路器
logic  [N-1:0] GRS_Q;//总线的输出
always_comb begin
	case (Index)//根据地址信号选择输出哪个寄存器的值
		2'b00: GRS_Q = R0_Q;
		2'b01: GRS_Q = R1_Q;
		2'b10: GRS_Q = R2_Q;
		2'b11: GRS_Q = R3_Q;
	endcase
end
/****** Internal signal assignment to output port *******/
assign HD[0] = R0_Q;//把一堆信号和面板的灯什么的连上
assign HD[1] = R1_Q;
assign HD[2] = R2_Q;
assign HD[3] = R3_Q;
assign HD[4] = GRS_Q;
assign L[0] = load0;
assign L[1] = load1;
assign L[2] = load2;
assign L[3] = load3;

endmodule//->用来把面板模块写完

SevenSegDecode模块

沿用七段译码器实验的就好了。

module SevenSegDecode(
	input logic [3:0]iData,
	output logic [7:0]oSeg
);
always_comb
	case(iData)
		4'b0000: oSeg = 8'b11000000;
		4'b0001: oSeg = 8'b11111001;
		4'b0010: oSeg = 8'b10100100;
		4'b0011: oSeg = 8'b10110000;
		4'b0100: oSeg = 8'b10011001;
		4'b0101: oSeg = 8'b10010010;
		4'b0110: oSeg = 8'b10000010;
		4'b0111: oSeg = 8'b11111000;
		4'b1000: oSeg = 8'b10000000;
		4'b1001: oSeg = 8'b10010000;
		4'b1010: oSeg = 8'b10001000;
		4'b1011: oSeg = 8'b10000011;
		4'b1100: oSeg = 8'b11000110;
		4'b1101: oSeg = 8'b10100001;
		4'b1110: oSeg = 8'b10000110;
		4'b1111: oSeg = 8'b10001110;
		default: oSeg = 8'b11111111;
	endcase
endmodule

DataReg模块

根据实验要求,下载DataReg.v文件,然后建议把它放到工程文件夹内的resource文件夹中,然后把文件加入工程,如图所示:
在这里插入图片描述
在这里插入图片描述
接下来就可以编译啦。
DataReg文件内容如下:

module DataReg
#(parameter N = 4)
(   output reg [N-1:0] oQ,
    input wire [N-1:0] iD,
    input wire Clk,
    input wire Load,
    input wire Reset
);
always @(posedge Clk or posedge Reset)
begin
  if (Reset)
		oQ <= 0;	
  else if (Load)
		oQ <= iD;
end
endmodule

三端口寄存器堆

VirtalBoard模块

在单端口寄存器组的基础上修改一下,就可以得到三端口寄存器堆,修改内容如下:
需要用到的线:

/** The input port is replaced with an internal signal **/
wire clk    = PB[1];
wire [3:0] Data  = S[11:8];
wire [1:0] WIndex = S[5:4];//这个是写入的地址
wire [1:0] RIndex1 = S[1:0];//加了读取的地址
wire [1:0] RIndex2 = S[3:2];
wire Load = S[6];

实验逻辑部分:

localparam N = 4;
// 2-4 decode
logic load3, load2, load1, load0;
always_comb begin
    if (Load)
        case (WIndex)//改了名字来的
            2'b00: {load3, load2, load1, load0} = 4'b0001;
            2'b01: {load3, load2, load1, load0} = 4'b0010;
			2'b10: {load3, load2, load1, load0} = 4'b0100;
			2'b11: {load3, load2, load1, load0} = 4'b1000;
            default: {load3, load2, load1, load0} = 4'bx;
        endcase
    else
        {load3, load2, load1, load0} = 4'b0000;
end
// register instantiation
logic [N-1:0] R0_Q, R1_Q, R2_Q, R3_Q;
DataReg #(N) R0(.oQ(R0_Q), .iD(Data), .Clk(clk), .Load(load0), .Reset(1'b1));//这个reset改了
DataReg #(N) R1(.oQ(R1_Q), .iD(Data), .Clk(clk), .Load(load1), .Reset(1'b0));
DataReg #(N) R2(.oQ(R2_Q), .iD(Data), .Clk(clk), .Load(load2), .Reset(1'b0));
DataReg #(N) R3(.oQ(R3_Q), .iD(Data), .Clk(clk), .Load(load3), .Reset(1'b0));

// 4-1 MUX 现在有两个多路器
logic  [N-1:0] GRS_Q1, GRS_Q2;
always_comb begin
	case (RIndex1)
		2'b00: GRS_Q1 = R0_Q;
		2'b01: GRS_Q1 = R1_Q;
		2'b10: GRS_Q1 = R2_Q;
		2'b11: GRS_Q1 = R3_Q;
	endcase
	case (RIndex2)
		2'b00: GRS_Q2 = R0_Q;
		2'b01: GRS_Q2 = R1_Q;
		2'b10: GRS_Q2 = R2_Q;
		2'b11: GRS_Q2 = R3_Q;
	endcase
end

DataReg模块

与单端口的一样,但如果在VirtualBoard的实例化DataReg中没有将它的复位信号赋为1’b1,那么可以在DataReg进行修改,如:(不建议这样做,花里胡哨的,就是写一写)

always @(posedge Clk or posedge Reset)
begin
		oQ <= 0;
end
endmodule

测试/保存/提交

测试一下没问题之后就可以提交了,需要注意的是本次实验平台上的数据回放有点问题,把代码放上去之后不能做记录。如果记录了,单端口寄存器组就会变成20分,三端口寄存器堆就会变成66.7分,搞不明白,等老师说吧。(更新一下,新的改分好像是好了)

  • 16
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值