$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Self-defined math definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math symbol commands \newcommand{\intd}{\,{\rm d}} % Symbol 'd' used in integration, such as 'dx' \newcommand{\diff}{{\rm d}} % Symbol 'd' used in differentiation ... $$

【FPGA学习】- 存储器设计

只读存储器

  只读存储器:Read-Only Memory(ROM),是一种极为重要的时序逻辑存储电路。逻辑功能是在地址信号的选择下,从指定的存储单元中读出相应的数据。特点是ROM只能进行数据的读取,而不能修改或者写入新的数据。

  16×8位的只读存储器设计如下。输入信号为地址选择信号addr,使能端en;输出信号为数据输出端data。

  ROM设计如下。

module rom(en, addr, data);
    input en;
    input [3:0] addr;
    output reg [7:0] data;
    //中间变量,传值给data
    reg [7:0] data1[15:0];

    always @(*) begin
        data1[0] = 8'b1010_1001; 
        data1[1] = 8'b1111_1101; 
        data1[2] = 8'b1110_1001; 
        data1[3] = 8'b1101_1100; 
        data1[4] = 8'b1011_0010; 
        data1[5] = 8'b1100_1001; 
        data1[6] = 8'b1100_0101; 
        data1[7] = 8'b0000_0100; 
        data1[8] = 8'b1110_1100; 
        data1[9] = 8'b1100_1001; 
        data1[10] = 8'b1010_0111; 
        data1[11] = 8'b0011_0100; 
        data1[12] = 8'b1100_0001;
        data1[13] = 8'b1001_1111;
         data1[14] = 8'b1010_0101;
         data1[15] = 8'b0101_1100;  

        if(en)
            data[7:0] = data1[addr];
        else
            data[7:0] = 8'bzzzz_zzzz;
    end
endmodule

  testbench。

`timescale 1ms/1ms
module rom_testbench;
    reg en;
    reg [3:0] addr;
    wire [7:0] data;
    
    rom r1(en, addr, data);

    initial begin
        en = 0;
       #2   en = 1; addr = 4'd0;
       #2   en = 1; addr = 4'd1;
       #2   en = 1; addr = 4'd2;
       #2   en = 1; addr = 4'd3;
       #2   en = 1; addr = 4'd4;
       #2   en = 1; addr = 4'd5;
       #2   en = 1; addr = 4'd6;
       #2   en = 1; addr = 4'd7;
       #2   en = 0; addr = 4'd8;
       #2   en = 1; addr = 4'd9;
       #2   en = 0; addr = 4'd10;
       #2   en = 0; addr = 4'd11;
       #2   en = 1; addr = 4'd12;
       #5   $stop;
    end

    initial begin
        $monitor($time,"\ten = %b, addr = %d, data = %b\t",en, addr, data);
    end
endmodule

  仿真结果。当使能端为1时,data输出数据;否则,data端为高阻态。

 

 

随机存储器

  随机存储器:Random Access Memory(RAM),逻辑功能是在地址信号的选取下,对指定的存储单元的数据进行读或写操作,所以随机存储器常用于动态数据的存储。

  32×8位的的RAM设计如下图。输入信号为地址选择信号addr,写信号wr,读信号rd,片选信号cs,数据写入端datain;输出信号为dataout。

  设计如下

module ram(addr, wr, rd, cs, datain, dataout);
    input wr, rd, cs;
    input [4:0] addr;
    input [7:0] datain;
    output reg [7:0] dataout;
    reg [7:0] data_space[31:0];
    //写操作
    always @(*) begin
        if(cs == 0) begin
            if(wr)
                data_space[addr] = datain;
            else
                dataout = 1'bz;
        end
        else
            dataout = 1'bz;
    end
    //读操作
    always @(*) begin
        if(cs == 0) begin
            if(rd)
                dataout = data_space[addr];
            else
                dataout = 1'bz;
        end
        else
            dataout = 1'bz;
    end
endmodule

  testbench。

`timescale 1ms/1ms
module ram_testbench;
    reg wr, rd, cs;
    reg [4:0] addr;
    reg [7:0] datain;
    wire [7:0] dataout;

    ram r1(addr, wr, rd, cs, datain, dataout);

    initial begin
            cs = 1'b1;
       #2   cs = 1'b0; addr = 5'd0; rd = 1'b0; wr = 1'b1; datain = 8'd15;
       #2   cs = 1'b0; addr = 5'd1; rd = 1'b0; wr = 1'b1; datain = 8'd10;
       #2   cs = 1'b0; addr = 5'd2; rd = 1'b0; wr = 1'b1; datain = 8'd32;
       #2   cs = 1'b0; addr = 5'd3; rd = 1'b0; wr = 1'b1; datain = 8'd97;
       #2   cs = 1'b1;
       #2   cs = 1'b0; addr = 5'd2; rd = 1'b1; wr = 1'b0;
       #2   cs = 1'b0; addr = 5'd3; rd = 1'b1; wr = 1'b0; 
       #2   cs = 1'b0; addr = 5'd1; rd = 1'b1; wr = 1'b0;
       #5   $stop;
    end
    
    initial begin
        $monitor($time, "\twr = %d, rd = %d, addr = %d, dataout = %d\t", wr, rd, addr, dataout);
    end
endmodule

  测试结果。写信号有效时,可以写入数据;读信号有效时,可以读出数据;当片选信号无效时,输出为高阻态。

 

 

堆栈

  堆栈:堆栈是一种执行先入后出的存储器。数据逐个存入的过程叫做压栈(push),数据逐个取出的过程称为出栈(pop)。最开始放入数据的单元称为栈底,最后存入数据的单元称为栈顶。

  8B的堆栈设计如下图。输入信号为清零信号clr,时钟信号clk,压栈信号push,出栈信号pop,输入端din;输出信号为栈空信empty,栈满信号full和输出端dout。

  设计如下。

module stack(
    input clr,
    input push,
    input pop,
    input clk,
    input [7:0] din,
    output empty,
    output full,
    output [7:0] dout
);

    reg empty, full;
    reg [7:0] dout;
    reg[7:0] stack[8:0];
    reg[3:0] cnt;

    always @(posedge clk) begin
        if(clr) begin            //clear
            dout <= 0;
            full <= 0;
            cnt <= 0;
        end
        else if(push && (!pop) && (cnt != 'b1000)) begin    //push
            empty <= 0;
            stack[cnt] <= din;
            cnt <= cnt + 1;
        end
        else if(pop && (!push) && (cnt != 'b0)) begin        //pop
            full <= 0;
            cnt <= cnt - 1;
            dout <= stack[cnt];
        end
        else if(cnt == 'b0) begin
            empty <= 1;
            dout <= 'b0;
        end
        else if(cnt == 'b1000) 
            full <= 1;
    end
endmodule

FIFO

   FIFO:先入先出存储器。是一种单向的数据传输的物理器件,只允许数据从输入端流向输出端。特点在于不需要地址线,而只需要数据线与读/写控制线。

  8B的FIFO如下。输入信号为时钟信号clk,清零端clr,写信号wr,读信号rd,数据写入端din;输出信号为数据读出端dout[7:0],存储器空信号empty,存储器满信号full。

 

posted @ 2023-03-20 12:07  素衣叹风尘  阅读(129)  评论(0)    收藏  举报