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