VL23 ROM的简单实现

一、要求

描述:实现一个深度为8,位宽为4bit的ROM,数据初始化为0,2,4,6,8,10,12,14。可以通过输入地址addr,输出相应的数据data。
输入描述:clk:系统时钟      rst_n:异步复位信号,低电平有效                                                                     addr:8bit位宽的无符号数,输入到ROM的地址
输出描述:data:4bit位宽的无符号数,从ROM中读出的数据                                                           

二、分析

1、要实现ROM,首先要声明数据的存储空间,例如:[3:0] rom [7:0];
(   每个数据具有多少位,位宽   。 一共需要多少个数据,深度 。  )
2、变量名称rom之前的[3:0]表示每个数据具有多少位,指位宽;
3、变量名称rom之后的[7:0]表示需要多少个数据,指深度,注意这里深度为8,应该是使用[7:0],而不是[2:0]。
4、声明存储变量之后,需要对rom进行初始化,写入数据,然后将输入地址作为rom的索引值,将索引值对应的数据输出。

三、代码

`timescale 1ns/1ns
module rom(
    input clk,
    input rst_n,
    input [2:0]addr,  //虽然题目说addr是8条线,但其实3条线已经够用
    output [3:0]data
);
    reg [3:0] myROM [7:0];
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            myROM[0] <= 0;
            myROM[1] <= 2;
            myROM[2] <= 4;
            myROM[3] <= 6;
            myROM[4] <= 8;
            myROM[5] <= 10;
            myROM[6] <= 12;
            myROM[7] <= 14;
        end
        else begin
            myROM[0] <= myROM[0];
            myROM[1] <= myROM[1];
            myROM[2] <= myROM[2];
            myROM[3] <= myROM[3];
            myROM[4] <= myROM[4];
            myROM[5] <= myROM[5];
            myROM[6] <= myROM[6];
            myROM[7] <= myROM[7];
        end
    end
    assign data = myROM[addr];
endmodule

四、问题和思考

1、关于 reg [3:0] myROM [7:0]; 和  input [2:0]addr, 的问题

①深度为8,指的是有8个寄存器,所以声明ROM时,必须是[7:0],表示有8个寄存器。                     8个寄存器可以存8个数据,地址线只要3根便可以对应这8个数据,所以input [2:0]addr            ②input [7:0]addr综合出来的电路,尽管电路输入端显示的是addr[7:0],但是,多路选择器的控制端仍然只用到addr[2:0],显示S[2:0],所以多出来的地址线没有用!

2、data = myROM[addr]; 这条语句应该放进always时序语句还是放在assign组合语句?下面的代码是把它放进always块,会多出一个寄存器。

这两种写法的区别:第①种:如果要求输入的地址addr一变,则输出的数据data立刻变,说明和时序无关,那么便是组合逻辑,则放在always语句外面,用assign语句。2、如果要求输入的地址addr一变,输出的数据data在clk时钟上升沿到时,才进行变化,则放在always时序语句里面。(也就是说,我用地址addr取的数据data我不立马使用,我可以延迟它的输出,让它打一拍再输出)。

要求中给出的波形图中圈出来的部分可知,data是随着addr的变化立刻变化的,即使不在clk的上升沿,即这条语句不受时序控制。所以我们语句应该是,assign data = myROM[addr]; 使用第一种写法。

`timescale 1ns/1ns
module ROM(
    input clk,
    input rst_n,
    input [2:0]addr,
    output [3:0]data
);
    reg [3:0] myROM [7:0];
    reg [3:0] data_r;
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            myROM[0] <= 0;
            myROM[1] <= 2;
            myROM[2] <= 4;
            myROM[3] <= 6;
            myROM[4] <= 8;
            myROM[5] <= 10;
            myROM[6] <= 12;
            myROM[7] <= 14;
            data_r   <= 0;
        end
        else
            data_r   <= myROM[addr];
    end
    assign data = data_r;
endmodule

五、数电知识

1、怎么看ROM电路?可以去B站搜索更详细的讲解视频

        先明白三点:1、二极管输出端如果为1,则说明二极管不导通,它的输入端电平看情况,                                         可能为1也可能为0                                                                                                                         2、二极管输出端如果为0,则说明二极管导通,那么它的输入端电平一定为0                                   3、如果没有二极管,则四条字线W0 W1 W2 W3全导通,且沿线都为高电平。

        假设地址位是A1为0 A0为1  。

        ①接着在地址译码器看字线W0 W1 W2 W3的值。二极管1和二极管2导通,则它们的输入端均为0,沿着字线W2 W3 ,发现二极管6和二极管8的输入端均为0,所以二极管6和二极管8不导通,那么字线W2 W3端口处的电平是二极管1和二极管2的输入端电平,即0    (W2=0 W3=0)

二极管3不导通,二极管7导通,则字线W0的端口处电平为二极管7的输入端电平,即0  (W0=0)

二极管4和二极管5均不导通,则W1端口处的电平为1(悬空)

        总结,对于地址译码器部分,只有当一条位线上的二极管全都不导通,则该位线的端口处才是高电平。其他情况的位线端口都是低电平!

        ②接着在存储矩阵看位线d3 d2 d1 d0的值

二极管只有在输入端为1时,才有可能导通,如果输入端为0,那二极管必然不导通。

由于字线W0 W2 W3均是低电平,则导致与字线W0 W2 W3相接的二极管输入均为0,二极管不导通。

只有W1字线的二极管可能导通,由于它们的输出端均接地,所以W1相接的二极管全导通。

所以 d3=1 d2=0 d1=1 d0=1   1011

        总结,对于存储矩阵,只有高电平位线上的二极管导通,由于它们接地,所以全导通!

        ③最后看输出缓冲器。它由三态门控制,当控制信号有效时,才会把d3d2d1d0输出,才会有D3D2D1D0这些数据。

2、地址译码器、存储矩阵、输出缓冲器

地址译码器其实就是把地址输入的组合拆开,分别由这几种地址组合去选取存储矩阵里的数据。

存储矩阵里面的数据是固化的,也就是它里面的数据出厂就已经确定了。

n条地址线,一共有2的n次方种组合,可以取2的n次方个数据,而数据的值是多少由厂家固定。

六、最后从电路的角度理解设计的要求

  reg [3:0] myROM [7:0];   数据初始化为 0 2 4 6 8 10 12 14

  这句话声明了一个ROM,意思是,ROM的存储矩阵的  每个数据有4bit位宽  有8个这样的数据

  其中[3:0] 以及 0 2 4 6 8 10 12 14 这些是数据信息,都是厂家固化的在电路的数据信息。

  其中[7:0] 表示 存储矩阵的字线和位线都是8条,则对于的地址线是3条,

  所以input [2:0]addr  (虽然题目说地址线addr是8根,但是实际电路3根就够了)

七、其他一些代码和电路

`timescale 1ns/1ns
module rom(
    input clk,
    input rst_n,
    input [7:0]addr,
    
    output [3:0]data
);

reg [3:0] data_out;
always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        data_out <= 4'b0000;
    else 
        case (addr)
            8'b0000_0000:data_out <= 4'b0000;
            8'b0000_0001:data_out <= 4'b0010;
            8'b0000_0010:data_out <= 4'b0100;
            8'b0000_0011:data_out <= 4'b0110;
            8'b0000_0100:data_out <= 4'b1000;
            8'b0000_0101:data_out <= 4'b1010;
            8'b0000_0110:data_out <= 4'b1100;
            8'b0000_0111:data_out <= 4'b1110;
        endcase         
end

assign data = data_out;
endmodule

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值