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
原文地址:https://www.cnblogs.com/suozhang/p/13915640.html