OpenCores
URL https://opencores.org/ocsvn/neo430/neo430/trunk

Subversion Repositories neo430

[/] [neo430/] [trunk/] [neo430/] [sw/] [lib/] [neo430/] [source/] [neo430_wishbone.c] - Rev 198

Compare with Previous | Blame | View Log

// #################################################################################################
// #  < neo430_wishbone.c - Internal Wishbone interface control functions >                        #
// # ********************************************************************************************* #
// # Use the normal Wishbone functions for BLOCKING access (until ACK is asserted).                #
// # Use non-blocking functions (*_start, wishbone_busy, wishbone_get_data*) to prevent dead locks #
// # when accessing invalid addresses and to do things in parallel when using the Wishbone bus.    #
// # ********************************************************************************************* #
// # BSD 3-Clause License                                                                          #
// #                                                                                               #
// # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
// #                                                                                               #
// # Redistribution and use in source and binary forms, with or without modification, are          #
// # permitted provided that the following conditions are met:                                     #
// #                                                                                               #
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
// #    conditions and the following disclaimer.                                                   #
// #                                                                                               #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
// #    conditions and the following disclaimer in the documentation and/or other materials        #
// #    provided with the distribution.                                                            #
// #                                                                                               #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
// #    endorse or promote products derived from this software without specific prior written      #
// #    permission.                                                                                #
// #                                                                                               #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
// # ********************************************************************************************* #
// # The NEO430 Processor - https://github.com/stnolting/neo430                                    #
// #################################################################################################
 
#include "neo430.h"
#include "neo430_wishbone.h"
 
 
// ************************************************************************************************
// Byte-wise access functions, with address alignment, blocking
// ************************************************************************************************
 
/* ------------------------------------------------------------
 * INFO Read 32-bit from Wishbone device (blocking), standard mode, pipelined
 * PARAM 32-bit device address
 * RETURN read data
 * ------------------------------------------------------------ */
uint32_t neo430_wishbone32_read32(uint32_t a) {
 
  // 32-bit transfer
  WB32_CT = 0xF;
 
  // device address aligned to 32-bit + transfer trigger
  WB32_RA_32bit = a & (~3);
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
 
  return WB32_D_32bit;
}
 
 
/* ------------------------------------------------------------
 * INFO Write 32-bit to Wishbone device (blocking), standard mode, pipelined
 * PARAM a: 32-bit device address
 * PARAM d: 32-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone32_write32(uint32_t a, uint32_t d) {
 
  // 32-bit transfer
  WB32_CT = 0xF;
 
  // write data
  WB32_D_32bit = d;
 
  // device address aligned to 32-bit + transfer trigger
  WB32_WA_32bit = a & (~3);
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
}
 
 
/* ------------------------------------------------------------
 * INFO Read 16-bit from Wishbone device (blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM 32-bit device address
 * RETURN 16-bit read data
 * ------------------------------------------------------------ */
uint16_t neo430_wishbone32_read16(uint32_t a) {
 
  // 16-bit transfer
  if (a & 2)
    WB32_CT = 0b1100; // high 16-bit word
  else
    WB32_CT = 0b0011; // low 16-bit word
 
  // device address aligned to 16-bit + transfer trigger
  WB32_RA_32bit = a & (~1);
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
 
  if (a & 2)
    return WB32_HD; // high 16-bit word
  else
    return WB32_LD; // low 16-bit word
}
 
 
/* ------------------------------------------------------------
 * INFO Write 16-bit to Wishbone device (blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM a: 32-bit device address
 * PARAM d: 16-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone32_write16(uint32_t a, uint16_t d) {
 
  // 16-bit transfer
  if (a & 2) {
    WB32_CT = 0b1100; // high 16-bit word
    WB32_HD = d;
  }
  else {
    WB32_CT = 0b0011; // low 16-bit word
    WB32_LD = d;
  }
 
  // device address aligned to 16-bit + transfer trigger
  WB32_WA_32bit = a & (~1);
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
}
 
 
/* ------------------------------------------------------------
 * INFO Read 8-bit from Wishbone device (blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM 32-bit device address
 * RETURN 0 if fail, 1 if timeout
 * ------------------------------------------------------------ */
uint8_t neo430_wishbone32_read8(uint32_t a) {
 
  // 8-bit transfer
  WB32_CT = 1 << (a & 3); // corresponding byte enable
 
  // device address aligned to 8-bit + transfer trigger
  WB32_RA_32bit = a;
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
 
  // select correct byte to be read
  uint16_t data;
  if (a & 2)
    data = WB32_HD;
  else
    data = WB32_LD;
 
  if (a & 1)
    data = neo430_bswap(data);
 
  return (uint8_t)data;
}
 
 
/* ------------------------------------------------------------
 * INFO Write 8-bit to Wishbone device (blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM a: 32-bit device address
 * PARAM d: 8-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone32_write8(uint32_t a, uint8_t d) {
 
  // 8-bit transfer
  WB32_CT = 1 << (a & 3); // corresponding byte enable
 
  // select correct byte to be written
  uint16_t data = (uint16_t)d;
  data = (data << 8) | data;
  WB32_LD = data;
  WB32_HD = data;
 
  // device address aligned to 8-bit + transfer trigger
  WB32_WA_32bit = a;
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
}
 
// ************************************************************************************************
// NONBLOCKING FUNCTIONS
// ************************************************************************************************
// Use wishbone_busy() to check status
// Use Wishbone_get_data(address) to get data from read accesses
// ************************************************************************************************
 
/* ------------------------------------------------------------
 * INFO Initiate read 32-bit from Wishbone device (non-blocking), standard mode, pipelined
 * PARAM 32-bit device address
 * ------------------------------------------------------------ */
void neo430_wishbone32_read32_start(uint32_t a) {
 
  // 32-bit transfer
  WB32_CT = 0xF;
 
  // device address aligned to 32-bit + transfer trigger
  WB32_RA_32bit = a & (~3);
}
 
 
/* ------------------------------------------------------------
 * INFO Initiate write 32-bit to Wishbone device (non-blocking), standard mode, pipelined
 * PARAM a: 32-bit device address
 * PARAM d: 32-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone32_write32_start(uint32_t a, uint32_t d) {
 
  // 32-bit transfer
  WB32_CT = 0xF;
 
  // write data
  WB32_D_32bit = d;
 
  // device address aligned to 32-bit + transfer trigger
  WB32_WA_32bit = a & (~3);
}
 
 
/* ------------------------------------------------------------
 * INFO Initiate read 16-bit from Wishbone device (non-blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM 32-bit device address
 * ------------------------------------------------------------ */
void neo430_wishbone32_read16_start(uint32_t a) {
 
  // 16-bit transfer
  if (a & 2)
    WB32_CT = 0b1100; // high 16-bit word
  else
    WB32_CT = 0b0011; // low 16-bit word
 
  // device address aligned to 16-bit + transfer trigger
  WB32_RA_32bit = a & (~1);
}
 
 
/* ------------------------------------------------------------
 * INFO Initiate write 16-bit to Wishbone device (non-blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM a: 32-bit device address
 * PARAM d: 16-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone32_write16_start(uint32_t a, uint16_t d) {
 
  // 16-bit transfer
  if (a & 2) {
    WB32_CT = 0b1100; // high 16-bit word
    WB32_HD = d;
  }
  else {
    WB32_CT = 0b0011; // low 16-bit word
    WB32_LD = d;
  }
}
 
 
/* ------------------------------------------------------------
 * INFO Initiate read 8-bit from Wishbone device (non-blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM 32-bit device address
 * ------------------------------------------------------------ */
void neo430_wishbone32_read8_start(uint32_t a) {
 
  // 8-bit transfer
  WB32_CT = 1 << (a & 3); // corresponding byte enable
 
  // device address aligned to 8-bit + transfer trigger
  WB32_RA_32bit = a;
}
 
 
/* ------------------------------------------------------------
 * INFO Initiate write 8-bit to Wishbone device (non-blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM a: 32-bit device address
 * PARAM d: 8-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone32_write8_start(uint32_t a, uint8_t d) {
 
  // select correct byte to be written
  uint16_t data = (uint16_t)d;
  data = (data << 8) | data;
  WB32_LD = data;
  WB32_HD = data;
 
  // 8-bit transfer
  WB32_CT = 1 << (a & 3); // corresponding byte enable
 
  // device address aligned to 8-bit + transfer trigger
  WB32_WA_32bit = a;
}
 
 
/* ------------------------------------------------------------
 * INFO Read 32-bit data after nonblocking transaction has been started
 * RETURN read data
 * ------------------------------------------------------------ */
uint32_t neo430_wishbone32_get_data32(void) {
 
  return WB32_D_32bit;
}
 
 
/* ------------------------------------------------------------
 * INFO Read 16-bit data after nonblocking transaction has been started
 * PARAM 32-bit device address
 * RETURN read data
 * ------------------------------------------------------------ */
uint16_t neo430_wishbone32_get_data16(uint32_t a) {
 
  if (a & 2)
    return WB32_HD; // high 16-bit word
  else
    return WB32_LD; // low 16-bit word
}
 
 
/* ------------------------------------------------------------
 * INFO Read 8-bit data after nonblocking transaction has been started
 * PARAM 32-bit device address
 * RETURN read data
 * ------------------------------------------------------------ */
uint8_t neo430_wishbone32_get_data8(uint32_t a) {
 
  // select correct byte to be read
  uint16_t data;
  if (a & 2)
    data = WB32_HD;
  else
    data = WB32_LD;
 
  if (a & 1)
    data = neo430_bswap(data);
 
  return (uint8_t)data;
}
 
 
// ************************************************************************************************
// Blocking access functions for data bus width = 32-bit, NO ADDRESS ALIGNMENT
// ************************************************************************************************
 
 
/* ------------------------------------------------------------
 * INFO Read 32-bit from Wishbone device (blocking), standard mode, pipelined
 * PARAM 32-bit device address
 * RETURN 32-bit read data
 * ------------------------------------------------------------ */
uint32_t neo430_wishbone32_read(uint32_t a) {
 
  // 32-bit transfer
  WB32_CT = 0xF;
 
  // device address + transfer trigger
  WB32_RA_32bit = a;
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
 
  return WB32_D_32bit;
}
 
 
/* ------------------------------------------------------------
 * INFO Write 32-bit to Wishbone device (blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM a: 32-bit device address
 * PARAM d: 32-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone32_write(uint32_t a, uint32_t d) {
 
  // 32-bit transfer
  WB32_CT = 0xf;
  WB32_D_32bit = d;
 
  // device address + transfer trigger
  WB32_WA_32bit = a;
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
}
 
 
// ************************************************************************************************
// NONBLOCKING FUNCTIONS
// ************************************************************************************************
// Use wishbone_busy() to check status
// Use Wishbone_get_data(address) to get data from read accesses
// ************************************************************************************************
 
/* ------------------------------------------------------------
 * INFO Initiate read 32-bit from Wishbone device (non-blocking), standard mode, pipelined
 * PARAM 32-bit device address
 * ------------------------------------------------------------ */
void neo430_wishbone32_read_start(uint32_t a) {
 
  // 32-bit transfer
  WB32_CT = 0xF;
 
  // device address + transfer trigger
  WB32_RA_32bit = a;
}
 
 
/* ------------------------------------------------------------
 * INFO Initiate write 32-bit to Wishbone device (non-blocking), standard mode, pipelined
 * PARAM a: 32-bit device address
 * PARAM d: 32-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone32_write_start(uint32_t a, uint32_t d) {
 
  // 32-bit transfer
  WB32_CT = 0xF;
 
  // write data
  WB32_D_32bit = d;
 
  // device address + transfer trigger
  WB32_WA_32bit = a;
}
 
 
/* ------------------------------------------------------------
 * INFO Read 32-bit data after nonblocking transaction has been started
 * PARAM 32-bit device address
 * RETURN 32-bit read data
 * ------------------------------------------------------------ */
uint32_t neo430_wishbone32_get_data(void) {
 
  return WB32_D_32bit;
}
 
 
// ************************************************************************************************
// Blocking access functions for data bus width = 16-bit, NO ADDRESS ALIGNMENT
// ************************************************************************************************
 
 
/* ------------------------------------------------------------
 * INFO Read 16-bit from Wishbone device (blocking), standard mode, pipelined
 * PARAM 32-bit device address
 * RETURN 16-bit read data
 * ------------------------------------------------------------ */
uint16_t neo430_wishbone16_read(uint32_t a) {
 
  // 16-bit transfer
  WB32_CT = 0x3; // low 16-bit word
 
  // device address + transfer trigger
  WB32_RA_32bit = a;
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
 
  return WB32_LD; // low 16-bit word
}
 
 
/* ------------------------------------------------------------
 * INFO Write 16-bit to Wishbone device (blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM a: 32-bit device address
 * PARAM d: 16-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone16_write(uint32_t a, uint16_t d) {
 
  // 16-bit transfer
  WB32_CT = 0x3; // low 16-bit word
  WB32_LD = d;
 
  // device address + transfer trigger
  WB32_WA_32bit = a;
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
}
 
 
// ************************************************************************************************
// NONBLOCKING FUNCTIONS
// ************************************************************************************************
// Use wishbone_busy() to check status
// Use Wishbone_get_data(address) to get data from read accesses
// ************************************************************************************************
 
/* ------------------------------------------------------------
 * INFO Initiate read 16-bit from Wishbone device (non-blocking), standard mode, pipelined
 * PARAM 32-bit device address
 * ------------------------------------------------------------ */
void neo430_wishbone16_read_start(uint32_t a) {
 
  // 16-bit transfer
  WB32_CT = 0x3;
 
  // device address + transfer trigger
  WB32_RA_32bit = a;
}
 
 
/* ------------------------------------------------------------
 * INFO Initiate write 16-bit to Wishbone device (non-blocking), standard mode, pipelined
 * PARAM a: 32-bit device address
 * PARAM d: 16-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone16_write_start(uint32_t a, uint16_t d) {
 
  // 16-bit transfer
  WB32_CT = 0x3;
 
  // write data
  WB32_LD = d;
 
  // device address + transfer trigger
  WB32_WA_32bit = a;
}
 
 
/* ------------------------------------------------------------
 * INFO Read 16-bit data after nonblocking transaction has been started
 * RETURN 16-bit read data
 * ------------------------------------------------------------ */
uint16_t neo430_wishbone16_get_data(void) {
 
  return WB32_LD;
}
 
 
// ************************************************************************************************
// Blocking access functions for data bus width = 8-bit, NO ADDRESS ALIGNMENT
// ************************************************************************************************
 
 
/* ------------------------------------------------------------
 * INFO Read 8-bit from Wishbone device (blocking), standard mode, pipelined
 * PARAM 32-bit device address
 * RETURN 8-bit read data
 * ------------------------------------------------------------ */
uint8_t neo430_wishbone8_read(uint32_t a) {
 
  // 8-bit transfer
  WB32_CT = 0x1;
 
  // device address + transfer trigger
  WB32_RA_32bit = a;
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
 
  return (uint8_t)WB32_LD; // low 16-bit word
}
 
 
/* ------------------------------------------------------------
 * INFO Write 8-bit to Wishbone device (blocking), standard mode, pipelined
 * INFO This function performs a data alignment based on the address!
 * PARAM a: 32-bit device address
 * PARAM d: 8-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone8_write(uint32_t a, uint8_t d) {
 
  // 8-bit transfer
  WB32_CT = 0x1; // low 8-bit word
  WB32_LD = (uint16_t)d;
 
  // device address + transfer trigger
  WB32_WA_32bit = a;
 
  // wait for access to be completed - blocking!
  while((WB32_CT & (1<<WB32_CT_PENDING)) != 0);
}
 
 
// ************************************************************************************************
// NONBLOCKING FUNCTIONS
// ************************************************************************************************
// Use wishbone_busy() to check status
// Use Wishbone_get_data(address) to get data from read accesses
// ************************************************************************************************
 
/* ------------------------------------------------------------
 * INFO Initiate read 16-bit from Wishbone device (non-blocking), standard mode, pipelined
 * PARAM 8-bit device address
 * ------------------------------------------------------------ */
void neo430_wishbone8_read_start(uint32_t a) {
 
  // 8-bit transfer
  WB32_CT = 0x1;
 
  // device address + transfer trigger
  WB32_RA_32bit = a;
}
 
 
/* ------------------------------------------------------------
 * INFO Initiate write 8-bit to Wishbone device (non-blocking), standard mode, pipelined
 * PARAM a: 32-bit device address
 * PARAM d: 8-bit write data
 * ------------------------------------------------------------ */
void neo430_wishbone8_write_start(uint32_t a, uint8_t d) {
 
  // 8-bit transfer
  WB32_CT = 0x1;
 
  // write data
  WB32_LD = (uint16_t)d;
 
  // device address + transfer trigger
  WB32_WA_32bit = a;
}
 
 
/* ------------------------------------------------------------
 * INFO Read 8-bit data after nonblocking transaction has been started
 * RETURN 8-bit read data
 * ------------------------------------------------------------ */
uint8_t neo430_wishbone8_get_data(void) {
 
  return (uint8_t)WB32_LD;
}
 
 
// ************************************************************************************************
// NONBLOCKING ARBITRATION FUNCTIONS
// ************************************************************************************************
 
/* ------------------------------------------------------------
 * INFO Check if Wishbone transaction is (still) in progress
 * RETURN 1 if transfer in progress, 0 if idel
 * ------------------------------------------------------------ */
uint16_t neo430_wishbone_busy(void) {
 
  return (WB32_CT & (1<<WB32_CT_PENDING));
}
 
 
/* ------------------------------------------------------------
 * INFO Terminate current Wishbone transfer
 * ------------------------------------------------------------ */
void neo430_wishbone_terminate(void) {
 
  WB32_CT = 0;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.