/* AXI FULL SLAVE */ module AxiSlave #( parameter AXI_DATA_WIDTH = 64 ) ( AxiMMBus Bus, /* Read Data From RegMap of FIFO's */ input wire [AXI_DATA_WIDTH-1:0] RdData_i, /* Validity Data and Address for the RegMap or FIFO's */ output reg Val_o, output reg ValToRdFifo_o, output wire [AXI_DATA_WIDTH-1:0] Data_o, output wire [AXI_DATA_WIDTH-1:0] RdAddr_o, output reg [AXI_DATA_WIDTH-1:0] Addr_o ); //*********************************************** // REG/WIRE //*********************************************** /* Write State Machine */ typedef enum logic [2:0] { WRITE_IDLE, WRITE_DATA, WRESP } WriteState_t; /* Read State Machine */ typedef enum logic [2:0] { READ_IDLE, READ_DATA, RRESP } ReadState_t; WriteState_t currWriteState, nextWriteState; ReadState_t currReadState, nextReadState; /* Write Regs */ reg [AXI_DATA_WIDTH-1:0] writeDataReg; reg [AXI_DATA_WIDTH-1:0] writeAddrReg; reg [AXI_DATA_WIDTH/8-1:0] writeStrbReg; reg [7:0] awLenReg; reg [2:0] awSizeReg; reg [1:0] awBurstReg; /* Read Regs */ reg [AXI_DATA_WIDTH-1:0] readDataReg; reg [AXI_DATA_WIDTH-1:0] readAddrReg; reg [AXI_DATA_WIDTH/8-1:0] readStrbReg; reg [7:0] arLenReg; reg [2:0] arSizeReg; reg [1:0] arBurstReg; /* Read Burst Count */ reg [7:0] readBurstCountReg; reg [AXI_DATA_WIDTH-1:0] s_axi_rvalid; //*********************************************** // ASSIGNMENTS //*********************************************** assign Data_o = writeDataReg; assign RdAddr_o = readAddrReg; assign s_axi_rdata_o = RdData_i; //*********************************************** // CODING //*********************************************** always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin currWriteState <= WRITE_IDLE; end else begin currWriteState <= nextWriteState; end end always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin currReadState <= READ_IDLE; end else begin currReadState <= nextReadState; end end /* Write Data Reg */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin writeDataReg <= 0; end else begin if (Bus.s_axi_wvalid_i && Bus.s_axi_wready_o) begin writeDataReg <= Bus.s_axi_wdata_i; end end end /* Val_o */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin Val_o <= 0; end else begin if (Bus.s_axi_wvalid_i && Bus.s_axi_wready_o) begin Val_o <= 1; end else begin Val_o <= 0; end end end /* Addr_o */ always_ff @(posedge Bus.s_axi_aclk_i) begin Addr_o <= writeAddrReg; end /* Write Strb Reg */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin writeStrbReg <= 0; end else begin if (Bus.s_axi_wvalid_i && Bus.s_axi_wready_o) begin writeStrbReg <= Bus.s_axi_wstrb_i; end end end /* awLenReg, awSize,awBurst */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin awLenReg <= 0; awSizeReg <= 0; awBurstReg <= 0; end else begin if (Bus.s_axi_awvalid_i && Bus.s_axi_wready_o) begin awLenReg <= Bus.s_axi_awlen_i; awSizeReg <= Bus.s_axi_awsize_i; awBurstReg <= Bus.s_axi_awburst_i; end end end /* Bvalid */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin Bus.s_axi_bvalid_o <= 1'b0; end else begin case(nextWriteState) WRESP: begin if (Bus.s_axi_bready_i) begin Bus.s_axi_bvalid_o <= 1'b1; end else begin Bus.s_axi_bvalid_o <= 1'b0; end end default: begin Bus.s_axi_bvalid_o <= 1'b0; end endcase end end /* Address Calculation */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin writeAddrReg <= 0; end else begin case (currWriteState) WRITE_IDLE: begin if (Bus.s_axi_awvalid_i && Bus.s_axi_awready_o) begin writeAddrReg <= Bus.s_axi_awaddr_i; end end WRITE_DATA : begin /* if need to increment the address */ if (awBurstReg == 2'b01) begin if (Bus.s_axi_wvalid_i && Bus.s_axi_wready_o) begin writeAddrReg <= writeAddrReg + AXI_DATA_WIDTH/8; end end else begin writeAddrReg <= writeAddrReg; end end default: begin writeAddrReg <= writeAddrReg; end endcase end end always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin Bus.s_axi_awready_o <= 1'b0; end else begin case (nextWriteState) WRITE_IDLE: begin Bus.s_axi_awready_o <= 1'b1; end WRITE_DATA: begin Bus.s_axi_awready_o <= 1'b1; end WRESP: begin Bus.s_axi_awready_o <= 1'b0; end default: begin Bus.s_axi_awready_o <= 1'b0; end endcase end end always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin Bus.s_axi_wready_o <= 1'b0; end else begin case (nextWriteState) WRITE_IDLE: begin Bus.s_axi_wready_o <= 1'b1; end WRITE_DATA: begin Bus.s_axi_wready_o <= 1'b1; end WRESP: begin Bus.s_axi_wready_o <= 1'b0; end default: begin Bus.s_axi_wready_o <= 1'b0; end endcase end end /* Write State Machine */ always_comb begin if (!Bus.s_axi_aresetn_i) begin nextWriteState = WRITE_IDLE; end else begin case (currWriteState) WRITE_IDLE: begin if (Bus.s_axi_awvalid_i) begin nextWriteState = WRITE_DATA; end else begin nextWriteState = WRITE_IDLE; end end WRITE_DATA: begin if (Bus.s_axi_wlast_i) begin nextWriteState = WRESP; end else begin nextWriteState = WRITE_DATA; end end WRESP: begin if (Bus.s_axi_bready_i) begin nextWriteState = WRITE_IDLE; end else begin nextWriteState = WRESP; end end default: begin nextWriteState = WRITE_IDLE; end endcase end end /* Bresp */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin Bus.s_axi_bresp_o <= 2'b0; end else begin Bus.s_axi_bresp_o <= 2'b0; end end always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin Bus.s_axi_arready_o <= 1'b0; end else begin case (currReadState) READ_IDLE: begin Bus.s_axi_arready_o <= 1'b1; end READ_DATA: begin Bus.s_axi_arready_o <= 1'b1; end default: begin Bus.s_axi_arready_o <= 1'b0; end endcase end end /* RRESP */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin Bus.s_axi_rresp_o <= 2'b0; end else begin Bus.s_axi_rresp_o <= 2'b0; end end /* Read Address Reg */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin readAddrReg <= 0; end else begin case (currReadState) READ_IDLE: begin if (Bus.s_axi_arvalid_i && Bus.s_axi_arready_o) begin readAddrReg <= Bus.s_axi_araddr_i; end end READ_DATA : begin /* if need to increment the address */ if (arBurstReg == 2'b01) begin if (Bus.s_axi_rvalid_o && Bus.s_axi_rready_i) begin readAddrReg <= readAddrReg + AXI_DATA_WIDTH/8; end end else begin readAddrReg <= readAddrReg; end end default: begin readAddrReg <= readAddrReg; end endcase end end /* arLenReg, arSize, arBurst */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin arLenReg <= 0; arSizeReg <= 0; arBurstReg <= 0; end else begin if (Bus.s_axi_arvalid_i && Bus.s_axi_arready_o) begin arLenReg <= Bus.s_axi_arlen_i; arSizeReg <= Bus.s_axi_arsize_i; arBurstReg <= Bus.s_axi_arburst_i; end end end /* Read Burst Count */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin readBurstCountReg <= 0; end else begin case (currReadState) READ_IDLE: begin if (Bus.s_axi_arvalid_i && Bus.s_axi_arready_o) begin readBurstCountReg <= Bus.s_axi_arlen_i; end else begin readBurstCountReg <= 0; end end READ_DATA : begin if (Bus.s_axi_rvalid_o && Bus.s_axi_rready_i) begin readBurstCountReg <= readBurstCountReg - 1; end end default: begin readBurstCountReg <= readBurstCountReg; end endcase end end /* Rvalid */ always_ff @(posedge Bus.s_axi_aclk_i) begin if (!Bus.s_axi_aresetn_i) begin Bus.s_axi_rvalid_o <= 1'b0; end else begin case (currReadState) READ_IDLE: begin if (Bus.s_axi_arvalid_i && Bus.s_axi_arready_o) begin Bus.s_axi_rvalid_o <= 1'b1; end else begin Bus.s_axi_rvalid_o <= 1'b0; end end READ_DATA: begin if (readBurstCountReg == 0 ) begin if (Bus.s_axi_rready_i) begin Bus.s_axi_rvalid_o <= 1'b0; end else begin Bus.s_axi_rvalid_o <= 1'b1; end end else begin Bus.s_axi_rvalid_o <= 1'b1; end end default: begin Bus.s_axi_rvalid_o <= 1'b0; end endcase end end /* ValToRdFifo_o */ always_comb begin if (!Bus.s_axi_aresetn_i) begin ValToRdFifo_o = 0; end else begin case (currReadState) READ_DATA : begin if (readBurstCountReg && Bus.s_axi_rready_i ) begin ValToRdFifo_o = 1; end else begin ValToRdFifo_o = 0; end end default: begin ValToRdFifo_o = 0; end endcase end end /* Rlast */ always_comb begin if (!Bus.s_axi_aresetn_i) begin Bus.s_axi_rlast_o = 1'b0; end else begin case (currReadState) READ_IDLE: begin Bus.s_axi_rlast_o = 1'b0; end READ_DATA: begin if (readBurstCountReg == 0) begin Bus.s_axi_rlast_o = 1'b1; end else begin Bus.s_axi_rlast_o = 1'b0; end end default: begin Bus.s_axi_rlast_o = 1'b0; end endcase end end /* Read State Machine */ always_comb begin if (!Bus.s_axi_aresetn_i) begin nextReadState = READ_IDLE; end else begin case (currReadState) READ_IDLE: begin if (Bus.s_axi_arvalid_i) begin nextReadState = READ_DATA; end else begin nextReadState = READ_IDLE; end end READ_DATA: begin if (Bus.s_axi_rlast_o && Bus.s_axi_rready_i) begin nextReadState = READ_IDLE; end else begin nextReadState = READ_DATA; end end default: begin nextReadState = READ_IDLE; end endcase end end endmodule