`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