SPI_Test/rtl/qubitmcu/qbmcu_exu_lsuagu.v

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"