远程FPGA虚拟实验平台用SystemVerilog HDL实现存储器
原理
实验材料
就是两个存储器,直接用。
实验内容·用ROM实现七段译码器
学习实验材料里的ROM,并用ROM的形式来写七段译码器ROM_SevenSegDecode,即令ROM的输入为四位数据,输出为八位的用来表示数码管的一串数字。
实验内容·用RAM实现寄存器堆
学习实验材料里的RAM,并用RAM的形式来写寄存器RegisterFile,即令RAM的输入为iWA, iRA1, iRA2, iWD而输出为oRD1, oRD2,再用数码管在virtualboard里显示。
源代码
实验材料·ROM
该实验材料基本照搬到实验内容,所以实验材料就不写了。
实验材料·RAM
VrtualBoard
/** The input port is replaced with an internal signal **/
wire reset = PB[0];
wire clk = PB[1];
wire [15:0] write_data = S[15:0];//一个输入端口,16位数据位
wire [15:0] address = S[31:16];//16位地址位
wire write_enable = S[32];//使能
logic [15:0] read_data;//一个输出端口
/************* The logic of this experiment *************/
RAM #(.ADDRWIDTH(8), .DATAWIDTH(16)) mem(.iClk(clk), .iWR(write_enable),
.iAddress(address), .iWriteData(write_data), .oReadData(read_data));
/****** Internal signal assignment to output port *******/
assign HD[0] = read_data[3:0];
assign HD[1] = read_data[7:4];
assign HD[2] = read_data[11:8];
assign HD[3] = read_data[15:12];
assign HD[4] = address[3:0];
assign HD[5] = address[6:4];
// assign HD[6] = address[:];
// assign HD[7] = address[:];
assign L[0] = write_enable;//反正老师没有给实验面板,只能自己幻想一下大概是一堆七段数码管叭
RAM
module RAM
#( parameter ADDRWIDTH = 6,
parameter DATAWIDTH = 32)
(
input wire iClk, iWR,
input wire [ADDRWIDTH-1:0] iAddress,//6位地址
input wire [DATAWIDTH-1:0] iWriteData,//32位输出数据
output wire [DATAWIDTH-1:0] oReadData//32位输出数据
);
localparam MEMDEPTH = 1<<ADDRWIDTH; //存储器的字数,为把1左移ADDRWIDTH位,也即b'100000,10位数64
logic [DATAWIDTH-1:0] mem[0:MEMDEPTH-1];//数组容量64位,每个可以存8位的二进制,一个数组即一个寄存器
logic [ADDRWIDTH-1:0] read_addr;//用来锁存读地址
always_ff @(posedge iClk)
begin
read_addr <= iAddress; //读地址锁存,编译器使用FPGA的RAM块生成存储器
if (iWR)
mem[iAddress] <= iWriteData;//往寄存器写入地址
end
assign oReadData = mem[read_addr]; //从寄存器读地址
/* initial 为了调试方便可给存储器赋初值,调试成功后将其删除。
$readmemh("init_data.txt",mem); // 存储器内容定义在文件中。 */
endmodule
实验内容·用ROM实现七段译码器
VrtualBoard
`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
);
/** The input port is replaced with an internal signal **/
wire [3:0] hexData = S[11:8];
/************* The logic of this experiment *************/
wire [7:0] segData;
ROM_SevenSegDecode ssdecode_inst(.iAddress(hexData), .oData(segData));//输入地址,输出数据
/****** Internal signal assignment to output port *******/
assign SD1 = segData;
改了模块名,其他照搬。
ROM_SevenSegDecode
module ROM_SevenSegDecode
#( parameter ADDRWIDTH = 4,
parameter DATAWIDTH = 8)
(
input logic [ADDRWIDTH-1:0] iAddress,//输入的地址
output logic [DATAWIDTH-1:0] oData//输出的数据,8位可以得出是直接写成七段译码器的那个数字
);
localparam MEMDEPTH = 1<<ADDRWIDTH;//存储器的字数,为把1左移ADDRWIDTH位,也即b'100000,10位数64
logic [DATAWIDTH-1:0] mem[0:MEMDEPTH-1];//数组容量64位,每个可以存8位的二进制,一个数组即一个寄存器
assign oData = mem[iAddress];
initial begin//初始化存储器用来测试数据,实验中也需要这个来完成七段译码器
//$readmemb("init_mem.txt",mem); //$readmemh是函数,如果文件中的数据是十六进制,用 $readmemh
// 也可以采用如下代码代替上面的readmemb,在实验内容里就是要用这种了,用mem数组来赋值
mem[16'h0000] = 8'b11000000;
mem[16'h0001] = 8'b11111001;
mem[16'h0002] = 8'b10100100;
mem[16'h0003] = 8'b10110000;
mem[16'h0004] = 8'b10011001;
mem[16'h0005] = 8'b10010010;
mem[16'h0006] = 8'b10000010;
mem[16'h0007] = 8'b11111000;
mem[16'h0008] = 8'b10000000;
mem[16'h0009] = 8'b10010000;
mem[16'h000A] = 8'b10001000;
mem[16'h000B] = 8'b10000011;
mem[16'h000C] = 8'b11000110;
mem[16'h000D] = 8'b10100001;
mem[16'h000E] = 8'b10000110;
mem[16'h000F] = 8'b10001110;
end
endmodule
实验内容·用RAM实现寄存器堆
VirtualBoard
`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
);
/********* Seven-segment decoder instantiation **********/
parameter ADDRWIDTH = 2;
parameter DATAWIDTH = 4;
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 [DATAWIDTH-1:0] write_data = S[11:8];
wire [ADDRWIDTH-1:0] address = S[5:4];
wire write_enable = S[6];
wire [ADDRWIDTH-1:0] read_address1 = S[1:0];
wire [ADDRWIDTH-1:0] read_address2 = S[3:2];
wire [DATAWIDTH-1:0] read_data1, read_data2;
/************* The logic of this experiment *************/
RegisterFile #(.ADDRWIDTH(ADDRWIDTH), .DATAWIDTH(DATAWIDTH)) mem(.Clk(clk), .iWE(write_enable),
.iWA(address), .iRA1(read_address1), .iRA2(read_address2), .iWD(write_data), .oRD1(read_data1), .oRD2(read_data2));//按照慕课里写的模块来写
/****** Internal signal assignment to output port *******/
assign HD[4] = read_data1;
assign HD[5] = read_data2;
endmodule
RAM(Register)
module RegisterFile
#( parameter ADDRWIDTH = 5,
parameter DATAWIDTH = 32)
(
input logic Clk,
input logic iWE,
input logic [ADDRWIDTH-1:0] iWA, iRA1, iRA2,
input logic [DATAWIDTH-1:0] iWD,
output logic [DATAWIDTH-1:0] oRD1, oRD2
);
localparam MEMDEPTH = 1<<ADDRWIDTH; //存储器的字数
logic [DATAWIDTH-1:0] mem[0:MEMDEPTH-1];
logic [ADDRWIDTH-1:0] read_addr1, read_addr2;
always_ff @(posedge Clk)
begin
read_addr1 <= iRA1; //读地址锁存,编译器使用FPGA的RAM块生成存储器
read_addr2 <= iRA2;
if (iWE && iWA!=0)//寄存器0不能写入数据
mem[iWA] <= iWD;
end
assign oRD1 = mem[iRA1]; //输出
assign oRD2 = mem[iRA2];
initial begin//初始化寄存器0为0
mem[5'b0] = 32'b0;
end
endmodule
测试/保存/提交
七段译码器的jvp去之前的实验里抓过来,这次实验数据回放记得直接提交,啥也别干就好,说实话前面的每一次也都是这样拿满分,离谱,这次终于在慕课提到了。