verilog BRAM 讀寫


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2020/10/30 15:51:21
// Design Name: 
// Module Name: pl_bram_ctrl_1
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.02 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module pl_bram_ctrl_1
(
     input              clk,
     input              rst_n,
     
     //bram port
     input      [31:0]  din,     
     output reg [31:0]  dout,
     output reg         en,
     output reg [3:0]   we,
     output             rst,
     output reg [31:0]  addr,
     
     //control signal
     input              start,       //start to read and write bram
     input      [31:0]  init_data,   //initial data defined by software
     output reg         start_clr,   //clear start register
     input      [31:0]  len,         //data count
     input      [31:0]  start_addr,   //start bram address
     
     //Interrupt
     input              intr_clr,    //clear interrupt
     output reg         intr         //interrupt
     
);

// 復位信號初始化 復位信號拉高
assign rst = 1'b0 ;

// 定義變量 並賦值 用於表示 BRAM 狀態
// 變量 用於 CASE 邏輯 處理
localparam IDLE      = 3'd0 ;  // BRAM 空閑狀態
localparam READ_RAM  = 3'd1 ;  // 正在 讀取 BRAM 狀態
localparam READ_END  = 3'd2 ;  // 讀取 BRAM 狀態結束
localparam WRITE_RAM = 3'd3 ;  // 正在 寫入 BRAM 狀態
localparam WRITE_END = 3'd4 ;  // 寫入 BRAM 狀態結束

// 對 reg 寄存器 變量 賦值時 必須在 always 塊內進行
reg [2:0] state ;               // 狀態 寄存器
reg [31:0] len_tmp ;         // 數據長度 寄存器
reg [31:0] start_addr_tmp ; // 開始地址 寄存器


// Main statement

// 在Veriog 中由兩種賦值方式,一種是
// 非阻塞賦值(<=),另一種是阻塞賦值(=)
// 阻塞賦值時,輸入改變輸出也同時改變,在非阻塞賦值中,只有在時鍾變化
// 的時候,輸出才會發生變化。

// 時鍾信號 上升沿 邏輯賦值處理
// 復位信號 下降沿 邏輯賦值處理
always @(posedge clk or negedge rst_n)begin
  if (~rst_n) begin  // 復位信號 低電平 處理
    state      <= IDLE  ;  // 狀態寄存器初始化為 空閑狀態
    dout       <= 32'd0 ;  // 數據輸出寄存器 清零
    en         <= 1'b0  ;  // 使能寄存器 為 0 ,即 非使能 狀態
    we         <= 4'd0  ;  // 
    addr       <= 32'd0 ;  // 地址寄存器 清零
    intr       <= 1'b0  ;  // 中斷寄存器 清零
    start_clr  <= 1'b0  ;  // 
    len_tmp    <= 32'd0 ;  // 數據長度寄存器 清零
    start_addr_tmp <= 32'd0 ; // 地址 臨時存儲寄存器 清零
    end
  else begin // 復位信號 高電平 處理
    case( state ) // 根據 狀態寄存器 進行分狀態 邏輯處理
    
    IDLE: begin // 空閑狀態處理‘
    
        if (start) begin // 開始變量 為1 邏輯處理
          state <= READ_RAM; // 狀態寄存器 更改為 讀取 BRAM 狀態
          addr  <= start_addr; // 地址寄存器 更改為 讀取寄存器地址
          start_addr_tmp <= start_addr; // 讀取地址 賦值
          len_tmp <= len ; // 讀取長度
          dout <= init_data ; //  數據輸出 賦值
          en    <= 1'b1 ;  // 使能信號 賦值
          start_clr <= 1'b1 ; // 開始信號  賦值
        end
                    
        if (intr_clr) // 中斷清除 變量 為 1 處理 
            intr <= 1'b0 ;
    end
    
    READ_RAM : begin // 讀取 BRAM 狀態處理
    
        if ((addr - start_addr_tmp) == len_tmp - 4) begin // 根據地址 讀取完成處理 
          state <= READ_END ; // 狀態切換到 讀取完成結束狀態
          en    <= 1'b0     ; // 使能 信號清零
        end
        else begin 
          addr <= addr + 32'd4; // address is byte based, for 32bit data width, adding 4 
        end
        
        start_clr <= 1'b0; // 開始控制信號 清零
        
     end
                      
    READ_END : begin // 讀取 BRAM 結束 狀態處理
        addr  <= start_addr_tmp ; // 讀取地址 改為 開始地址
        en <= 1'b1 ; // 使能信號 置位
        we <= 4'hf ; // 
        state <= WRITE_RAM  ; // 狀態 等於 寫入狀態                
      end
    
    WRITE_RAM : begin // 寫入 BRAM 狀態處理
        if ((addr - start_addr_tmp) == len_tmp - 4) begin // write completed 寫入完成處理 
          state <= WRITE_END ; // 狀態更改為 寫入結束狀態
          dout  <= 32'd0 ; // 數據輸出信號 清零
          en    <= 1'b0  ; // 使能信號 清零
          we    <= 4'd0  ; // 
        end
        
        else begin
          addr <= addr + 32'd4 ; 
          dout <= dout + 32'd1 ;                          
        end
      end
                      
    WRITE_END       
    : begin
                        addr <= 32'd0 ;
                        intr <= 1'b1 ;
                        state <= IDLE ; // 狀態 切換到 空閑狀態                
                      end    
    default         : state <= IDLE ;
    endcase
  end
end    

endmodule

 


免責聲明!

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



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