zoukankan      html  css  js  c++  java
  • 用嵌入式块RAM IP核配置一个双口RAM

    本次设计源码地址:http://download.csdn.net/detail/noticeable/9914173

    实验现象:通过串口将数据发送到FPGA 中,通过quartus II 提供的in system memory content editor 工具查看RAM中接收到的数据,当需要是,按下按键KEY0,将FPGA 的RAM 中存储的数据通过串口发送出去。

    知识点:

        (1)存储器IP核的使用(2)in system memory content editor 内存查看工具的使用

     系统结构框图如下,如何绘制在http://www.cnblogs.com/noticeable/p/7248404.html可以进行查看

    设计过程:复制之前写的uart工程,打开,添加menmoryIP核

     

    然后直接next,直到finish,此时就可以将IP核添加完毕了。

    直接将IP核生成的文件设置为顶层文件,编写testbench文件对其进行仿真

    `timescale 1ns/1ns
    `define clock_period 20
    
    module dua_ram_tb;
                                            reg clock;
                                            reg [7:0]data;
                                            reg [7:0]rdaddress;
                                            reg [7:0]wraddress;
                                            reg wren;
                                            wire [7:0]q;
                                            integer i;
                    dua_ram dua_ram0(
                                                                .clock(clock),
                                                                .data(data),
                                                                .rdaddress(rdaddress),
                                                                .wraddress(wraddress),
                                                                .wren(wren),
                                                                .q(q)
                                                                );//端口连接
                                                                
                                                                
                                                initial clock=1;
                                                always#(`clock_period/2)clock=~clock;
                                                
                                    initial begin 
                                    data=0;
                                    rdaddress=0;
                                    wraddress=0;
                                    wren=0;
                                    #(`clock_period*20+1);
                                    for(i=0;i<=15;i=i+1)begin     //    写操作
                                    wren=1;
                                    data=255-i;
                                    wraddress=i;
                                    #(`clock_period);
                                    end
                                    wren=0;
                                        #(`clock_period*20+1);//延迟一段时间后进行读操作
                                                for(i=0;i<=15;i=i+1)begin     //    读操作
                                                rdaddress=i;
                                                    #(`clock_period);
                                                    end
                                                    #5000;
                                                    $stop;
                                                end
    endmodule 

    设置仿真脚本,点击仿真,进行前仿

     仿真完了,可以对双口RAM有一个基本了解了,下面就将其添加到之前写的uart工程中

    新建一个uart_dpram.v文件,并设置其为顶层文件,代码按照结构图进行编辑如下:

    module uart_dpram(
                                                clk,
                                                rst_n,
                                                key_in,
                                                rs232_rx,
                                                rs232_tx);
                                input clk;                                
                                input rst_n;
                                input key_in;
                                input rs232_rx;                    //串口读取端口
                                output rs232_tx;                //串口写出端口
                                
                            wire key_flag;                        //按键检测标志
                            wire key_state;                        //按键状态标志
                            wire rx_done;                        //读取完成标志
                            wire tx_done;                        //写出完成标志
                            wire send_en;                        //写出使能
                            wire [7:0]rdaddress,wraddress;            //读地址和写地址
                            wire wren;                                //写入使能
                            wire [7:0]rx_data,tx_data;    //待读取数据与发送数据
                            
                    uart_tx         uart_tx_a(
                                                            .clk(clk),
                                                            .rst_n(rst_n),
                                                            .send_en(send_en),
                                                            .baud_set(3'd0),
                                                            .tx_done(tx_done),
                                                            .rs232_tx(rs232_tx),
                                                            .data_byte(tx_data),
                                                            .uart_state()
                                                            );
                                                            
                            uart_rx            uart_rx_a(
                                                                    .clk(clk),
                                                                    .rs232_rx(rs232_rx),
                                                                    .baud_set(3'd0),
                                                                    .rst_n(rst_n),
                                                                    .data_byte(rx_data),
                                                                    .rx_done(rx_done)
                                                                        );
                    key_filter         key_filter_a(
                                                                    .clk(clk),
                                                                    .rst_n(rst_n),
                                                                    .key_in(key_in),
                                                                    .key_flag(key_flag),
                                                                    .key_state(key_state)
                                                                        );
                            
                                dua_ram dua_ram_a(
                                                                            .clock(clk),
                                                                            .data(rx_data),                                //存储器入口是读取的数据
                                                                            .rdaddress(rdaddress),
                                                                            .wraddress(wraddress),
                                                                            .wren(wren),
                                                                            .q(tx_data)                                            //存储器的出口是要写出的数据
                                                                            );//端口连接    
                            ctrl                 ctrl_a(
                                                                .clk(clk),
                                                                .rst_n(rst_n),
                                                                .key_flag(key_flag),
                                                                .key_state(key_state),
                                                                .rx_done(rx_done),
                                                                .tx_done(tx_done),
                                                                .rdaddress(rdaddress),
                                                                .wraddress(wraddress),
                                                                .wren(wren),
                                                                .send_en(send_en)
                                                                    );
                                                                                
        endmodule 

    如代码中所说,ctrl模块没有定义,编译肯定是会报错的,下面继续编写ctrl 模块,新建一个ctrl.v文件,编辑如下:

    module ctrl(
                                                                clk,
                                                                rst_n,
                                                                key_flag,
                                                                key_state,
                                                                rx_done,
                                                                tx_done,
                                                                rdaddress,
                                                                wraddress,
                                                                wren,
                                                                send_en
                                                                    );//控制模块
                                                                    
                                    input            clk;
                                    input            rst_n;
                                    input          key_flag;
                                    input            key_state;
                                    input            rx_done;
                                    input            tx_done;
                                    output reg[7:0]rdaddress;
                                    output reg[7:0]wraddress;
                                    output     wren;                                                    //写入使能信号
                                    output  reg     send_en;                                        //发送使能
                                    
                                    
                assign wren=rx_done;                                                            //读取完成的信号即可以写入了
                                    reg   do_send;                                                        //发送标志
                                    reg r0_send_done,r1_send_done;                //发送缓冲寄存器
                                
                                
                                
                always@(posedge clk or negedge rst_n)//写地址
                        if(!rst_n)
                        wraddress<=8'd0;
                        else if(rx_done)                                                                    //每读取完一次,写入地址+1
                        wraddress<=wraddress+8'd1;
                        else 
                        wraddress<=wraddress;
                        
                    always@(posedge clk or negedge rst_n)
                        if(!rst_n)
                                    do_send<=0;                                                        
                            else if(key_flag&&!key_state)                                        //如果按键按下一次,发送状态改变一次
                                        do_send<=~do_send;
                                        
                                        
                always@(posedge clk or negedge rst_n)//读地址
                        if(!rst_n)        
                        rdaddress<=8'd0;
                        else if(do_send&&tx_done)                                                //发送状态为发送,且1byte数据已经发送完成了,则读地址+1
                                rdaddress<=rdaddress+8'd1;
                        
                always@(posedge clk or negedge rst_n)///ram读有两拍的延迟,所以加两级寄存器对发送使能进行缓存
                    if(!rst_n)        begin 
                            r0_send_done<=1'b0;
                            r1_send_done<=1'b0;
                            end
                            else begin 
                            r0_send_done<=(do_send&&tx_done);
                            r1_send_done<=r0_send_done;
                            end 
                                
                    always@(posedge clk or negedge rst_n)//发送使能
                        if(!rst_n)        
                        send_en<=0;
                                    else if(key_flag&&!key_state)
                                    send_en<=1'b1;
                                    else     if(r1_send_done)
                                                    send_en<=1;
                                    else 
                                        send_en<=0;
                        
                        
            
                             
                                
    
    endmodule 

    编写testbench文件进行仿真,将test9中的keymodule 复制到本工程的testbench文件夹下,并添加到工程中

    `timescale 1ns/1ns
    `define clock_period 20
    module uart_dpram_tb;
                                reg clk;
                                reg rst_n;
                                wire key_in;
                                wire rs232_rx;
                                wire rs232_tx;
                                wire tx_done;
                                reg  [7:0]data_byte_t;
                                reg send_en;
                                wire [2:0]baud_set;
                                reg press;
            
                assign baud_set = 3'd0;
                uart_dpram    uart_dpram_1(
                                                                                    .clk(clk),
                                                                                    .rst_n(rst_n),
                                                                                    .key_in(rst_n),
                                                                                    .rs232_rx(rs232_rx),
                                                                                    .rs232_tx(rs232_tx));
                                                                                    
                    uart_tx            uart_tx1(
                                                                                .clk(clk),
                                                                                .rst_n(rst_n),
                                                                                .send_en(send_en),
                                                                                .baud_set(baud_set),
                                                                                .tx_done(tx_done),
                                                                                .rs232_tx(rs232_rx),
                                                                                .data_byte(data_byte_t),
                                                                                .uart_state()
                                                                            );
    
                    key_module key_module1(
                                                                                .press(press),
                                                                                .key(key_in)
                                                                                );
                                    initial clk=1;
                                    always#(`clock_period/2)  clk=~clk;
                                    //发送数据
                                    initial begin 
                                            rst_n = 1'b0;
                                            press = 0;
                                            data_byte_t = 8'd0;
                                            send_en = 1'd0;
                                    #(`clock_period*20+1)
                                    rst_n=1'b1;
                                        #(`clock_period*50+1)
                                        
                                        data_byte_t<=8'haa;
                                    send_en<=1'd1;
                                    #(`clock_period)
                                    send_en<=1'd0;
                                    
                                    
                                    @(posedge tx_done)//等待传输完成的上升沿
                                    
                                    #(`clock_period*500)//重新发送
                                    data_byte_t<=8'h55;
                                    send_en<=1'd1;
                                    #(`clock_period)
                                    send_en<=1'd0;
                            @(posedge tx_done)//等待传输完成的上升沿
                                #(`clock_period*500)//重新发送
                                    data_byte_t<=8'hcc;
                                    send_en<=1'd1;
                                    #(`clock_period)
                                    send_en<=1'd0;
                                    
                                @(posedge tx_done)//等待传输完成的上升沿        
                            #(`clock_period*500)//重新发送
                                    data_byte_t<=8'hff;
                                    send_en<=1'd1;
                                    #(`clock_period)
                                    send_en<=1'd0;
                                    
                                    //按下按键读取发送出去的内容
                                        @(posedge tx_done)
            
                                            #(`clock_period*5000);
                                            
                                            press = 1;
                                            #(`clock_period*3)
                                            press = 0;
                                            #(`clock_period*500000);
                            
                                    
                                    end
        endmodule 

    添加路径如下:

    点击仿真,仿真结果如下

     引脚配置,烧写程序,进行扳级验证,这里GPIO0_D0连接到USB_TTL的TXD,GPIO0_D1连接到USB_TTL 的RXD即可。

    打开串口调试软件,连接USB-TTL模块,发送数据,按下按键KEY_1,FPGA不断把刚才发到ram中的数据读取出来,再按一下,停止发送,效果图如下所示

  • 相关阅读:
    《不懂说话你怎么带团队》读书笔记
    Java内存模型与指令重排
    线程的基本操作
    Spring MVC核心技术
    Spring MVC注解式开发
    Spring MVC执行流程
    大厂技术博客汇总
    内嵌tomcat启动速度慢
    Java 对IP请求进行限流.
    Java过滤XSS脚本, 可通过Appscan扫描
  • 原文地址:https://www.cnblogs.com/noticeable/p/7246900.html
Copyright © 2011-2022 走看看