`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