176 lines
8.1 KiB
Verilog
176 lines
8.1 KiB
Verilog
//+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"
|
|
|