【xilink nexsy3】【verilog】存储器RAM

 

一、    实验目的

1.学习如何使用ISE的IP核

2.学习使用Xilinx FPGA内的RAM资源

a)例化一个简单双端口的RAM(32bitx64)

b)使用coe文件对RAM进行初始化

二、    实验要求

1.综合利用三次实验的结果,完成以下功能:

a)从ram中0地址和1地址读取两个数, 分别赋给reg0和reg1

b)利用第二次实验的结果(ALU+Regfile)进行斐波拉契运算,运算结果保存在对应的寄存器

c)运算结果同时保存在对应的ram地址中,即ram[0]<----->reg0,ram[1]<----->reg1,

ram[2]<----->reg2,……

2.实现一个control模块,完成整个运算的控制。

3.实现一个顶层模块Top

a)调用Ram

b)调用RegFile

c)调用ALU完成运算

d)调用control模块,完成运算控制

三、    实验内容

1.生成IP核

模块参数如下:

2.主要代码分析

module top(

input clk,

output[31:0] writein,

output[31:0] readout1,

output[31:0] readout2

    );

 

reg[5:0] readaddr=5'd0;

wire[31:0] readout;

wire[5:0] addrb;

wire[5:0] addra;

wire writeenable;

wire[31:0] doutb;

//例化模块如下,其中ram和regfile使用同一个使能writeenable、同一个写入地址//addra和同一个写入内容writein,ram的两个端口使能保持为1

ram ra(clk,1'b1,writeenable,addra,writein,clk,1'b1,addrb,doutb);

regfilere(clk,1'b1,readaddr,readout,addra,writein,writeenable);

alu al(readout1,readout2,5'd1,writein);

controlcon(clk,doutb,writeenable,readout1,readout2,addra,addrb);

 

endmodule

 

********************************************************************************************

module control(

input clk,

input [31:0] doutb,

output reg writeenable,

output reg[31:0] readout1,

output reg[31:0] readout2,

output reg[5:0]  addra,

output reg[5:0]  addrb

         );

 

reg[2:0] count = 3'd0;

reg flag = 1'b0;

 

always@(negedgeclk)                            //control部分,利用标记数count来

   //进行步骤的循环,每次循环里面有

   //四个步骤,分别在下降沿执行,修改

   //在上升沿的执行的regfile的参数

 

begin

              if(flag== 1'b0)                                               //如果flag=0,先进行初始化,即先

                     begin                               //将ram【0】、ram【1】里的内容都

                            if(count==3'd0)                  //复制存储到regfile中

                                   begin

                                          addrb<= 1'b0;

                                          count<= count+1'b1;

                                          writeenable<=1'b0;

                                   end

                            else if(count==3'd1)

                                   begin

                                          count <= count + 1'b1;

                                          readout1 <= doutb;

                                          readout2 <= 1'b0;

                                          addra <= addrb;

                                          addrb <= addrb + 1'b1;

                                          writeenable <=1'b1;

                                   end

                            else if(count==3'd2)

                                   begin

                                          count <= count + 1'b1;

                                          readout1 <= doutb;

                                          readout2 <= 1'b0;

                                          addra <= addrb-1'b1;

                                          addrb <= addrb + 1'b1;

                                          writeenable <=1'b1;

                                   end

                            else if(count==3'd3)                //初始化复制完成,flag赋值为1

                                   begin                        //count等数值归零

                                          count<= 1'b0;

                                          addrb <= 1'b0;

                                          flag <= 1'b1;

                                   end

                     end

              else

              begin

              if(count==3'd0)

                     begin

                            count <= count + 1'b1;

                            writeenable <=1'b0;

                     end

              elseif(count==3'd1)                                       //修改操作数2读取地址

                     begin

                            count <= count + 1'b1;

                            readout1 <= doutb;

                            addrb <= addrb + 1'b1;

                            writeenable <=1'b0;

                     end

              elseif(count==3'd2)

                     begin

                            count <= count + 1'b1;

                            readout2 <= doutb;

                            writeenable <=1'b0;

                     end

else if(count==3'd3)                      //修改写入addra地址和write使能

                     begin

                            writeenable <=1'b1;

                            addra <= addrb + 1'b1;

                            count <= 3'd0;

                     end

              end       

end

endmodule

 

******************************************************************************************

Alu和regfile模块见前两次实验报告,此处略去

3.coe文件编写

如图:

 

4.仿真

 

(可以发现下降沿修改时,结果即时发生变化,但是在上升沿写入寄存器的结果是斐波那契数列的正确结果,4,6,10,16,26,42,68,110,178……每次写入是正确的,可知读取的也是正确的。

打开观察ram中的内容可以验证正确。)

四、    实验分析和总结

本实验regfile、alu均调用之前实验的编写结果,关键在于control部分的逻辑要清晰。

在对regfile和ALU进行control时,考虑到regfile模块是时钟上升沿敏感的,所以在下降沿对实例化的参数进行修改,这样充分利用了每个时钟周期,而且不会导致冲突。

Ram可以当作一个普通模块调用,有相应的输出输出接口,可以在generate的时候设置ram的相关参数,例如ram的深度宽度,端口的宽度等等。Ram初始化要使用coe文件。


猜你喜欢

转载自blog.csdn.net/saber_jk/article/details/80923302