用嵌入式塊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中的數據讀取出來,再按一下,停止發送,效果圖如下所示

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM