• 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
  • 相关阅读:
    活动投票
    人品问题
    网站记录
    浅谈底层常数优化及编译器优化
    透过用户思维谈程序员的进阶之路
    我们为什么要学习?写给我的组员们
    原来你是这样的Websocket--抓包分析
    我看依赖注入
    使用反射+策略模式代替项目中大量的switch case判断
    JavaScript 词法作用域不完全指北
  • 原文地址:https://www.cnblogs.com/suozhang/p/13915640.html
Copyright © 2020-2023  润新知