【iCore1S 雙核心板_FPGA】例程十七:基於雙口RAM的ARM+FPGA資料存取實驗

XiaomaGee發表於2017-10-13

實驗現象:

 

核心程式碼:

module DUAL_PORT_RAM(
    input CLK_12M,
    inout WR,
    input RD,
    input CS0,
    input [24:16]A,
    inout [15:0]DB,
    output FPGA_LEDR,
    output FPGA_LEDG,
    output FPGA_LEDB
 );
 //-------------------------------rst_n---------------------------------//
    reg rst_n;
    reg [3:0]cnt_rst;
    
    always@(posedge CLK_12M)
        begin
            if(cnt_rst==4'd10)
                begin
                    rst_n <= 1'd1;
                    cnt_rst <= 4'd10;
                end
            else cnt_rst <= cnt_rst + 1'd1;
        end
        
//---------------------------------PLL--------------------------------//
    //例項化PLL
    my_pll u1(
                .inclk0(CLK_12M),
                .c0(PLL_48M)
                );
                
//--------------------------------RAM---------------------------------//
    //例項化雙口ram
    wire [15:0]a_dataout;
    wire [15:0]b_dataout;
    
    my_ram  u2(
                    .address_a(a_addr),
                    .address_b(A),
                    .data_a(a_datain),
                    .data_b(DB),
                    .clock_a(!a_clk),
                    .clock_b(b_clk),
                    .wren_a(a_wren),
                    .wren_b(1'd0),
                    .rden_a(a_rden),
                    .rden_b(!rd),
                    .q_a(a_dataout),
                    .q_b(b_dataout)                    
                    );
                    
//-------------------------------delay-------------------------------//
    //對CLK_12M做延時處理
    reg clk1,clk2;
    
    always@(posedge PLL_48M or negedge rst_n)
        begin
            if(!rst_n)
                begin
                    clk1 <= 1'd0;
                    clk2 <= 1'd0;
                end
            else 
                begin
                    {clk2,clk1} <= {clk1,CLK_12M};
                end
        end
        
    wire a_clk = (CLK_12M & clk2);
    
//---------------------------------ram_cnt----------------------------//
    //ram地址資料計數器
    reg [9:0]cnt_addr;
    
    always@(posedge CLK_12M or negedge rst_n)
        begin
            if(!rst_n)
                begin
                    cnt_addr <= 10'd0;
                end
            else if(cnt_addr==10'd511)
                begin
                    cnt_addr <= 10'd0;
                end
            else cnt_addr <= cnt_addr + 1'd1;
        end
        
//------------------------------ram_a wr&rd----------------------------//
    reg a_wren,a_rden;
    reg [9:0]a_datain;
    reg [9:0]a_addr;
    
    always@(posedge a_clk or negedge rst_n)
        begin
            if(!rst_n)
                begin
                    a_wren <= 1'd0;
                    a_rden <= 1'd0;
                    a_datain <= 10'd0;
                    a_addr <= 10'd0;
                end
            else if(cnt_addr >= 10'd0 && cnt_addr <= 10'd255)
                begin
                    a_wren <= 1'd1;
                    a_datain <= cnt_addr;
                    a_addr <= cnt_addr;
                    a_rden <= 1'd0;
                end
            else if(cnt_addr>=10'd256 && cnt_addr <= 1'd511)
                begin
                    a_rden <= 1'd1;
                    a_addr <= cnt_addr - 10'd256;
                    a_wren <= 1'd0;
                end
        end
        
//------------------------------a_ram_error---------------------------//
    //判斷讀取地址與輸出資料是否相等。相等,綠燈亮;不相等,紅燈亮。
    reg error;
    reg [2:0]led;
    
    always@(negedge clk1 or negedge rst_n)
        begin
            if(!rst_n)
                begin
                    error <= 1'd0;
                end
            else if(a_wren || a_dataout == a_addr)
                begin
                    error <= 1'd0;
                    led <= 3'b101;
                end
            else 
                begin
                    error <= 1'd1;
                    led <= 3'b011;
                end
        end
        
        assign {FPGA_LEDR,FPGA_LEDG,FPGA_LEDB} = led;
            
//-------------------------------b_ram_rd-----------------------------//
    //控制ram_b的讀取功能,當讀訊號來臨時,讀取資料傳送到FSMC匯流排上
    wire wr = (CS0 | WR );
    wire rd = (CS0 | RD);    
    reg wr_clk1,wr_clk2;
    
    always@(posedge PLL_48M or negedge rst_n)    
        begin
            if(!rst_n)
                begin
                    wr_clk1 <= 1'd1;
                    wr_clk2 <= 1'd1;
                end
            else 
                begin
                    {wr_clk2,wr_clk1} <= {wr_clk1,wr};
                end
        end 
    wire b_clk = (!wr_clk2 | !rd);
    assign DB = !rd ? b_dataout : 16'hzzzz;
    
//------------------------------endmodule-----------------------------//
 endmodule

實驗方法及指導書:

連結:http://pan.baidu.com/s/1hsEeYxe 密碼:004h

相關文章