//+FHDR-------------------------------------------------------------------------------------------------------- // Company: //----------------------------------------------------------------------------------------------------------------- // File Name : qbmcu_exu_lsuagu.v // Department : // Author : PWY // Author's Tel : //----------------------------------------------------------------------------------------------------------------- // Relese History // Version Date Author Description // 0.1 2024-03-13 PWY This module to implement the AGU (address generation unit // for load/store instructions) //----------------------------------------------------------------------------------------------------------------- // Keywords : // //----------------------------------------------------------------------------------------------------------------- // Parameter // //----------------------------------------------------------------------------------------------------------------- // Purpose : // //----------------------------------------------------------------------------------------------------------------- // Target Device: // Tool versions: //----------------------------------------------------------------------------------------------------------------- // Reuse Issues // Reset Strategy: // Clock Domains: // Critical Timing: // Asynchronous I/F: // Synthesizable (y/n): // Other: //-FHDR-------------------------------------------------------------------------------------------------------- `include "qbmcu_defines.v" module qbmcu_exu_lsuagu( //system port input clk ,input rst_n ////////////////////////////////////////////////////////////// //The operands and instruction information from the decoding module ,input [`QBMCU_XLEN-1 :0] agu_i_rs1 ,input [`QBMCU_XLEN-1 :0] agu_i_rs2 ,input [`QBMCU_XLEN-1 :0] agu_i_imm ,input [`QBMCU_DECINFO_AGU_WIDTH-1:0] agu_i_info ,input agu_i_op //The enable signal from the master control state machine ,input agu_i_active ////////////////////////////////////////////////////////////// //Address, data, and enable signals connected to the memory space ,output [`QBMCU_ADDR_SIZE-1 :0] agu_o_addr ,output [`QBMCU_XLEN-1 :0] agu_o_wdata ,output agu_o_wren // Write enable ,output agu_o_rden // Read enable ,output [`QBMCU_XLEN/8-1 :0] agu_o_wmask ,input [`QBMCU_XLEN-1 :0] agu_i_rdata ////////////////////////////////////////////////////////////// //Data sent to the write-back module //write back interface ,output [`QBMCU_XLEN-1 :0] agu_o_wbck_wdat ,output agu_o_wbck_valid //Misaligned memory address ,output agu_o_addr_unalgn ); ///////////////////////////////////////////////////////////////////////////////// //Memory Address Generation ///////////////////////////////////////////////////////////////////////////////// //Generate Operand 1 wire [`QBMCU_XLEN-1:0] agu_addr_gen_op1 = agu_i_rs1; //The Operand 2 of the memory access instructions are immediate values wire [`QBMCU_XLEN-1:0] agu_addr_gen_op2 = agu_i_imm; wire [`QBMCU_ADDR_SIZE-1:0] agu_addr = agu_addr_gen_op1 + agu_addr_gen_op2; //Fetch memory access instruction //Load operation wire agu_i_load = agu_i_op & agu_i_info [`QBMCU_DECINFO_AGU_LOAD ] ; //Store operation wire agu_i_store = agu_i_op & agu_i_info [`QBMCU_DECINFO_AGU_STORE ] ; //Fetching memory size wire [1:0] agu_i_size = {2{agu_i_op}} & agu_i_info [`QBMCU_DECINFO_AGU_SIZE ]; //sign extraction wire agu_i_usign = agu_i_op & agu_i_info [`QBMCU_DECINFO_AGU_USIGN ]; //Generate size information wire agu_i_size_b = (agu_i_size == 2'b00); wire agu_i_size_hw = (agu_i_size == 2'b01); wire agu_i_size_w = (agu_i_size == 2'b10); //Generation of misaligned memory access signal wire agu_i_addr_unalgn = (agu_i_size_hw & agu_addr[0] ) | (agu_i_size_w & (|agu_addr[1:0])); wire agu_addr_unalgn = agu_i_addr_unalgn; //Abnormal memory access operation wire agu_i_unalgnld = (agu_addr_unalgn & agu_i_load); wire agu_i_unalgnst = (agu_addr_unalgn & agu_i_store) ; wire agu_i_unalgnldst = (agu_i_unalgnld | agu_i_unalgnst); //Normal memory access operation wire agu_i_algnld = (~agu_addr_unalgn) & agu_i_load; wire agu_i_algnst = (~agu_addr_unalgn) & agu_i_store; wire agu_i_algnldst = (agu_i_algnld | agu_i_algnst); ///////////////////////////////////////////////////////////////////////////////// //Read/Write Command, and Data Generation ///////////////////////////////////////////////////////////////////////////////// //write enable, active hight wire agu_wren = (agu_i_algnldst & agu_i_store) & agu_i_active; //read enable, active hight wire agu_rden = (agu_i_algnldst & agu_i_load ) & agu_i_active; //write data wire [`QBMCU_XLEN-1:0] algnst_wdata = ({`QBMCU_XLEN{agu_i_size_b }} & {4{agu_i_rs2[ 7:0]}}) | ({`QBMCU_XLEN{agu_i_size_hw}} & {2{agu_i_rs2[15:0]}}) | ({`QBMCU_XLEN{agu_i_size_w }} & {1{agu_i_rs2[31:0]}}); //write mask wire [`QBMCU_XLEN/8-1:0] algnst_wmask = ({`QBMCU_XLEN/8{agu_i_size_b }} & (4'b0001 << agu_addr[1:0])) | ({`QBMCU_XLEN/8{agu_i_size_hw}} & (4'b0011 << {agu_addr[1],1'b0})) | ({`QBMCU_XLEN/8{agu_i_size_w }} & (4'b1111)); ///////////////////////////////////////////////////////////////////////////////// // Write-Back Data Generation ///////////////////////////////////////////////////////////////////////////////// wire agu_lbu = agu_i_size_b & agu_i_usign; wire agu_lb = agu_i_size_b & ~agu_i_usign; wire agu_lhu = agu_i_size_hw & agu_i_usign; wire agu_lh = agu_i_size_hw & ~agu_i_usign; wire agu_lw = agu_i_size_w; //Write-Back Data wire [`QBMCU_XLEN-1:0] agu_wbck_wdat = ( ({`QBMCU_XLEN{agu_lbu}} & {{24{ 1'b0}} , agu_i_rdata[8*(agu_addr[1:0]+1)-1-:8]}) | ({`QBMCU_XLEN{agu_lb }} & {{24{agu_i_rdata[8*(agu_addr[1:0]+1)-1]}}, agu_i_rdata[8*(agu_addr[1:0]+1)-1-:8]}) | ({`QBMCU_XLEN{agu_lhu}} & {{16{ 1'b0}} , agu_i_rdata[16*(agu_addr[1]+1)-1-:16]}) | ({`QBMCU_XLEN{agu_lh }} & {{16{agu_i_rdata[16*(agu_addr[1]+1)-1]}} , agu_i_rdata[16*(agu_addr[1]+1)-1-:16]}) | ({`QBMCU_XLEN{agu_lw }} & agu_i_rdata[31:0])); ///////////////////////////////////////////////////////////////////////////////// // Output ///////////////////////////////////////////////////////////////////////////////// //agu_o_wren sirv_gnrl_dffr #(1) agu_o_wren_dffr (agu_wren, agu_o_wren, clk, rst_n); //agu_o_wdata sirv_gnrl_dfflr #(`QBMCU_XLEN) agu_o_wdata_dfflr (agu_i_active, algnst_wdata, agu_o_wdata, clk, rst_n); //agu_o_wmask sirv_gnrl_dfflr #(`QBMCU_XLEN/8) agu_o_wmask_dfflr (agu_i_active, algnst_wmask, agu_o_wmask, clk, rst_n); //agu_o_addr sirv_gnrl_dfflr #(`QBMCU_ADDR_SIZE) agu_o_addr_dfflr (agu_i_active, agu_addr, agu_o_addr, clk, rst_n); //agu_o_rden sirv_gnrl_dffr #(1) agu_o_rden_dffr (agu_rden, agu_o_rden, clk, rst_n); //agu_o_wbck_wdat //sirv_gnrl_dffr #(`QBMCU_XLEN) agu_o_wbck_wdat_dffr (agu_wbck_wdat, agu_o_wbck_wdat, clk, rst_n); assign agu_o_wbck_wdat = agu_wbck_wdat; //agu_o_wbck_valid sirv_gnrl_dfflr #(1) agu_o_wbck_valid_dfflr (agu_i_active, agu_i_op, agu_o_wbck_valid, clk, rst_n); //agu_o_addr_unalgn sirv_gnrl_dfflr #(1) agu_o_addr_unalgn_dfflr (agu_i_active, agu_i_unalgnldst, agu_o_addr_unalgn, clk, rst_n); endmodule `include "qbmcu_undefines.v"