Commit f202b3a6 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

testbench for DMA

parent 5e84804a
`include "simdrv_defs.svh"
`include "eth_packet.svh"
`include "minic_regs.vh"
`define MAX_PACKET_SIZE 1536
class CSimDrv_Minic;
const uint32_t TX_DESC_VALID = (1<<31);
const uint32_t TX_DESC_WITH_OOB = (1<<30);
const uint32_t TX_DESC_HAS_OWN_MAC = (1<<28);
`define RX_DESC_VALID(d) ((d) & (1<<31) ? 1 : 0)
`define RX_DESC_ERROR(d) ((d) & (1<<30) ? 1 : 0)
`define RX_DESC_HAS_OOB(d) ((d) & (1<<29) ? 1 : 0)
`define RX_DESC_SIZE(d) (((d) & (1<<0) ? -1 : 0) + (d & 'hffe))
protected CBusAccessor acc_regs, acc_pmem;
protected uint32_t base_regs, base_pmem;
protected int pmem_size;
protected bit little_endian;
protected uint32_t tx_head, tx_base, tx_avail, tx_size, tx_count, tx_oob_val;
protected uint32_t rx_head, rx_base, rx_avail, rx_size, rx_count;
protected EthPacket rx_queue[$];
protected EthPacket tx_queue[$];
const int MINIC_MTU = 1536;
function new(int pmem_size_, CBusAccessor regs_, uint32_t base_regs_, CBusAccessor pmem_, uint32_t base_pmem_);
base_pmem = base_pmem_;
base_regs = base_regs_;
acc_regs = regs_;
acc_pmem = pmem_;
pmem_size = pmem_size_;
little_endian = 1;
endfunction // new
task minic_writel(uint32_t addr, uint32_t val);
acc_regs.write(base_regs + addr, val, 4);
endtask // minic_writel
task minic_readl(uint32_t addr, output uint32_t val);
uint64_t tmp;
acc_regs.read(base_regs + addr, tmp, 4);
val = tmp;
endtask // minic_writel
task new_tx_buffer();
tx_head = tx_base;
tx_avail = (tx_size - MINIC_MTU) >> 2;
minic_writel(`ADDR_MINIC_TX_ADDR, tx_base);
endtask // new_tx_buffers
task new_rx_buffer();
rx_head = rx_base;
minic_writel(`ADDR_MINIC_MCR, 0);
minic_writel(`ADDR_MINIC_RX_ADDR, rx_base);
minic_writel(`ADDR_MINIC_RX_SIZE, rx_size >> 2);
minic_writel(`ADDR_MINIC_EIC_ISR, `MINIC_EIC_ISR_RX);
minic_writel(`ADDR_MINIC_MCR, `MINIC_MCR_RX_EN);
endtask // new_rx_buffer
task init();
uint32_t lo, hi;
minic_writel(`ADDR_MINIC_EIC_IDR, `MINIC_EIC_IDR_RX);
minic_writel(`ADDR_MINIC_EIC_ISR, `MINIC_EIC_ISR_RX);
rx_base = base_pmem;
rx_size = pmem_size / 4;
tx_base = base_pmem + pmem_size / 2;
tx_size = pmem_size / 4;
tx_oob_val = 12345;
lo = rx_base >> 2;
hi = (rx_base >> 2) + (rx_size >> 2) - 1;
minic_writel(`ADDR_MINIC_MPROT, (lo << `MINIC_MPROT_LO_OFFSET) | (hi << `MINIC_MPROT_HI_OFFSET));
tx_count = 0;
rx_count = 0;
new_rx_buffer();
minic_writel(`ADDR_MINIC_EIC_IER, `MINIC_EIC_IER_RX);
endtask // init
task tx_frame(byte payload[], uint32_t size, bit with_oob, int ts_id, output uint32_t ts, output int port_id);
int i;
uint32_t d_hdr, mcr, nwords;
u64_array_t buff;
byte tmp[];
byte oob[2];
new_tx_buffer();
if(size < 60) size = 60;
if(size & 1) size = size + 1;
tmp = new[size](payload);
buff = SimUtils.pack({0,0,0,0, tmp, 0,0,0,0}, 4, 1);
size = size / 2;
for(i=0;i<buff.size(); i++)
acc_pmem.write(tx_head + i*4, buff[i], 4);
acc_pmem.write(tx_head, TX_DESC_HAS_OWN_MAC | TX_DESC_VALID | (with_oob ? TX_DESC_WITH_OOB :0 )| size | (ts_id << 12), 4);
minic_readl(`ADDR_MINIC_MCR, mcr);
minic_writel(`ADDR_MINIC_MCR, mcr | `MINIC_MCR_TX_START);
endtask // tx_frame
task rx_frame(ref byte payload[], output uint32_t size, output bit with_ts, output uint32_t ts);
uint32_t payload_size, num_words;
uint64_t desc_hdr;
uint32_t raw_ts;
uint32_t rx_addr_cur, mcr, cur_avail;
u64_array_t pbuff;
int i;
int n_recvd;
uint32_t isr;
minic_readl(`ADDR_MINIC_EIC_ISR, isr);
if(! (isr & `MINIC_EIC_ISR_RX))
return;
acc_pmem.read(rx_head, desc_hdr);
if(!`RX_DESC_VALID(desc_hdr))
begin
$error("SimDRV_Minic::rx_frame: weird, invalid RX desc header");
$stop;
end
payload_size = `RX_DESC_SIZE(desc_hdr);
num_words = (payload_size + 3) >> 2;
pbuff = new [num_words];
// $display("NWords %d hdr %x", num_words, desc_hdr);
if(`RX_DESC_HAS_OOB(desc_hdr))
payload_size = payload_size - 6;
if(!`RX_DESC_ERROR(desc_hdr))
begin
for(i=0; i<num_words;i++)
acc_pmem.read((rx_head + 4 + i * 4) % rx_size, pbuff[i]);
payload = SimUtils.unpack(pbuff, 4, payload_size);
end
size = payload_size;
rx_head = (rx_head + 4 + num_words * 4) % rx_size;
minic_writel(`ADDR_MINIC_RX_AVAIL, (num_words + 1));
minic_readl(`ADDR_MINIC_RX_AVAIL, cur_avail);
acc_pmem.read(rx_head, desc_hdr);
if( cur_avail == (rx_size>>2) || !(`RX_DESC_VALID(desc_hdr)))
begin
minic_readl(`ADDR_MINIC_MCR, mcr);
if(mcr & `MINIC_MCR_RX_FULL)
new_rx_buffer();
minic_writel(`ADDR_MINIC_EIC_ISR, `MINIC_EIC_ISR_RX);
end
endtask // rx_frame
task do_rx();
byte payload[];
uint32_t size, ts;
bit with_ts;
rx_frame(payload, size, with_ts, ts);
if(payload.size() > 0)
begin
EthPacket pkt;
pkt = new;
pkt.deserialize(payload);
rx_queue.push_back(pkt);
end
endtask // do_rx
task run();
uint32_t mcr;
if(tx_queue.size() > 0)
begin
minic_readl(`ADDR_MINIC_MCR, mcr);
// $display("mcr %x, Minic::q_not_empty %d", mcr, tx_queue.size());
if(mcr & `MINIC_MCR_TX_IDLE) begin
byte b[];
uint32_t ts;
int pid;
EthPacket pkt;
pkt = tx_queue.pop_front();
pkt.serialize(b);
tx_frame(b, b.size(), pkt.oob_type == TX_FID ? 1 : 0, pkt.ts.frame_id,ts, pid);
end
end // if (tx_queue.size() > 0)
do_rx();
endtask // run
task send(EthPacket pkt);
tx_queue.push_back(pkt);
endtask // send
function poll();
return rx_queue.size() > 0;
endfunction // poll
task recv(ref EthPacket pkt);
pkt = rx_queue.pop_front();
endtask // recv
endclass // CSimDrv_Minic
`define ADDR_MDIO_MCR 7'h0
`define MDIO_MCR_RESV_OFFSET 0
`define MDIO_MCR_RESV 32'h0000001f
`define MDIO_MCR_UNI_EN_OFFSET 5
`define MDIO_MCR_UNI_EN 32'h00000020
`define MDIO_MCR_SPEED1000_OFFSET 6
`define MDIO_MCR_SPEED1000 32'h00000040
`define MDIO_MCR_CTST_OFFSET 7
`define MDIO_MCR_CTST 32'h00000080
`define MDIO_MCR_FULLDPLX_OFFSET 8
`define MDIO_MCR_FULLDPLX 32'h00000100
`define MDIO_MCR_ANRESTART_OFFSET 9
`define MDIO_MCR_ANRESTART 32'h00000200
`define MDIO_MCR_ISOLATE_OFFSET 10
`define MDIO_MCR_ISOLATE 32'h00000400
`define MDIO_MCR_PDOWN_OFFSET 11
`define MDIO_MCR_PDOWN 32'h00000800
`define MDIO_MCR_ANENABLE_OFFSET 12
`define MDIO_MCR_ANENABLE 32'h00001000
`define MDIO_MCR_SPEED100_OFFSET 13
`define MDIO_MCR_SPEED100 32'h00002000
`define MDIO_MCR_LOOPBACK_OFFSET 14
`define MDIO_MCR_LOOPBACK 32'h00004000
`define MDIO_MCR_RESET_OFFSET 15
`define MDIO_MCR_RESET 32'h00008000
`define ADDR_MDIO_MSR 7'h4
`define MDIO_MSR_ERCAP_OFFSET 0
`define MDIO_MSR_ERCAP 32'h00000001
`define MDIO_MSR_JCD_OFFSET 1
`define MDIO_MSR_JCD 32'h00000002
`define MDIO_MSR_LSTATUS_OFFSET 2
`define MDIO_MSR_LSTATUS 32'h00000004
`define MDIO_MSR_ANEGCAPABLE_OFFSET 3
`define MDIO_MSR_ANEGCAPABLE 32'h00000008
`define MDIO_MSR_RFAULT_OFFSET 4
`define MDIO_MSR_RFAULT 32'h00000010
`define MDIO_MSR_ANEGCOMPLETE_OFFSET 5
`define MDIO_MSR_ANEGCOMPLETE 32'h00000020
`define MDIO_MSR_MFSUPPRESS_OFFSET 6
`define MDIO_MSR_MFSUPPRESS 32'h00000040
`define MDIO_MSR_UNIDIRABLE_OFFSET 7
`define MDIO_MSR_UNIDIRABLE 32'h00000080
`define MDIO_MSR_ESTATEN_OFFSET 8
`define MDIO_MSR_ESTATEN 32'h00000100
`define MDIO_MSR_100HALF2_OFFSET 9
`define MDIO_MSR_100HALF2 32'h00000200
`define MDIO_MSR_100FULL2_OFFSET 10
`define MDIO_MSR_100FULL2 32'h00000400
`define MDIO_MSR_10HALF_OFFSET 11
`define MDIO_MSR_10HALF 32'h00000800
`define MDIO_MSR_10FULL_OFFSET 12
`define MDIO_MSR_10FULL 32'h00001000
`define MDIO_MSR_100HALF_OFFSET 13
`define MDIO_MSR_100HALF 32'h00002000
`define MDIO_MSR_100FULL_OFFSET 14
`define MDIO_MSR_100FULL 32'h00004000
`define MDIO_MSR_100BASE4_OFFSET 15
`define MDIO_MSR_100BASE4 32'h00008000
`define ADDR_MDIO_PHYSID1 7'h8
`define MDIO_PHYSID1_OUI_OFFSET 0
`define MDIO_PHYSID1_OUI 32'h0000ffff
`define ADDR_MDIO_PHYSID2 7'hc
`define MDIO_PHYSID2_REV_NUM_OFFSET 0
`define MDIO_PHYSID2_REV_NUM 32'h0000000f
`define MDIO_PHYSID2_MMNUM_OFFSET 4
`define MDIO_PHYSID2_MMNUM 32'h000003f0
`define MDIO_PHYSID2_OUI_OFFSET 10
`define MDIO_PHYSID2_OUI 32'h0000fc00
`define ADDR_MDIO_ADVERTISE 7'h10
`define MDIO_ADVERTISE_RSVD3_OFFSET 0
`define MDIO_ADVERTISE_RSVD3 32'h0000001f
`define MDIO_ADVERTISE_FULL_OFFSET 5
`define MDIO_ADVERTISE_FULL 32'h00000020
`define MDIO_ADVERTISE_HALF_OFFSET 6
`define MDIO_ADVERTISE_HALF 32'h00000040
`define MDIO_ADVERTISE_PAUSE_OFFSET 7
`define MDIO_ADVERTISE_PAUSE 32'h00000180
`define MDIO_ADVERTISE_RSVD2_OFFSET 9
`define MDIO_ADVERTISE_RSVD2 32'h00000e00
`define MDIO_ADVERTISE_RFAULT_OFFSET 12
`define MDIO_ADVERTISE_RFAULT 32'h00003000
`define MDIO_ADVERTISE_RSVD1_OFFSET 14
`define MDIO_ADVERTISE_RSVD1 32'h00004000
`define MDIO_ADVERTISE_NPAGE_OFFSET 15
`define MDIO_ADVERTISE_NPAGE 32'h00008000
`define ADDR_MDIO_LPA 7'h14
`define MDIO_LPA_RSVD3_OFFSET 0
`define MDIO_LPA_RSVD3 32'h0000001f
`define MDIO_LPA_FULL_OFFSET 5
`define MDIO_LPA_FULL 32'h00000020
`define MDIO_LPA_HALF_OFFSET 6
`define MDIO_LPA_HALF 32'h00000040
`define MDIO_LPA_PAUSE_OFFSET 7
`define MDIO_LPA_PAUSE 32'h00000180
`define MDIO_LPA_RSVD2_OFFSET 9
`define MDIO_LPA_RSVD2 32'h00000e00
`define MDIO_LPA_RFAULT_OFFSET 12
`define MDIO_LPA_RFAULT 32'h00003000
`define MDIO_LPA_LPACK_OFFSET 14
`define MDIO_LPA_LPACK 32'h00004000
`define MDIO_LPA_NPAGE_OFFSET 15
`define MDIO_LPA_NPAGE 32'h00008000
`define ADDR_MDIO_EXPANSION 7'h18
`define MDIO_EXPANSION_RSVD1_OFFSET 0
`define MDIO_EXPANSION_RSVD1 32'h00000001
`define MDIO_EXPANSION_LWCP_OFFSET 1
`define MDIO_EXPANSION_LWCP 32'h00000002
`define MDIO_EXPANSION_ENABLENPAGE_OFFSET 2
`define MDIO_EXPANSION_ENABLENPAGE 32'h00000004
`define MDIO_EXPANSION_RSVD2_OFFSET 3
`define MDIO_EXPANSION_RSVD2 32'h0000fff8
`define ADDR_MDIO_ESTATUS 7'h3c
`define MDIO_ESTATUS_RSVD1_OFFSET 0
`define MDIO_ESTATUS_RSVD1 32'h00000fff
`define MDIO_ESTATUS_1000_THALF_OFFSET 12
`define MDIO_ESTATUS_1000_THALF 32'h00001000
`define MDIO_ESTATUS_1000_TFULL_OFFSET 13
`define MDIO_ESTATUS_1000_TFULL 32'h00002000
`define MDIO_ESTATUS_1000_XHALF_OFFSET 14
`define MDIO_ESTATUS_1000_XHALF 32'h00004000
`define MDIO_ESTATUS_1000_XFULL_OFFSET 15
`define MDIO_ESTATUS_1000_XFULL 32'h00008000
`define ADDR_MDIO_WR_SPEC 7'h40
`define MDIO_WR_SPEC_TX_CAL_OFFSET 0
`define MDIO_WR_SPEC_TX_CAL 32'h00000001
`define MDIO_WR_SPEC_RX_CAL_STAT_OFFSET 1
`define MDIO_WR_SPEC_RX_CAL_STAT 32'h00000002
`define MDIO_WR_SPEC_CAL_CRST_OFFSET 2
`define MDIO_WR_SPEC_CAL_CRST 32'h00000004
`define MDIO_WR_SPEC_BSLIDE_OFFSET 4
`define MDIO_WR_SPEC_BSLIDE 32'h000001f0
`define ADDR_EP_ECR 7'h0
`define EP_ECR_PORTID_OFFSET 0
`define EP_ECR_PORTID 32'h0000001f
`define EP_ECR_RST_CNT_OFFSET 5
`define EP_ECR_RST_CNT 32'h00000020
`define EP_ECR_TX_EN_OFFSET 6
`define EP_ECR_TX_EN 32'h00000040
`define EP_ECR_RX_EN_OFFSET 7
`define EP_ECR_RX_EN 32'h00000080
`define EP_ECR_FEAT_VLAN_OFFSET 24
`define EP_ECR_FEAT_VLAN 32'h01000000
`define EP_ECR_FEAT_DMTD_OFFSET 25
`define EP_ECR_FEAT_DMTD 32'h02000000
`define EP_ECR_FEAT_PTP_OFFSET 26
`define EP_ECR_FEAT_PTP 32'h04000000
`define EP_ECR_FEAT_DPI_OFFSET 27
`define EP_ECR_FEAT_DPI 32'h08000000
`define ADDR_EP_TSCR 7'h4
`define EP_TSCR_EN_TXTS_OFFSET 0
`define EP_TSCR_EN_TXTS 32'h00000001
`define EP_TSCR_EN_RXTS_OFFSET 1
`define EP_TSCR_EN_RXTS 32'h00000002
`define EP_TSCR_CS_START_OFFSET 2
`define EP_TSCR_CS_START 32'h00000004
`define EP_TSCR_CS_DONE_OFFSET 3
`define EP_TSCR_CS_DONE 32'h00000008
`define EP_TSCR_RX_CAL_START_OFFSET 4
`define EP_TSCR_RX_CAL_START 32'h00000010
`define EP_TSCR_RX_CAL_RESULT_OFFSET 5
`define EP_TSCR_RX_CAL_RESULT 32'h00000020
`define ADDR_EP_RFCR 7'h8
`define EP_RFCR_A_RUNT_OFFSET 0
`define EP_RFCR_A_RUNT 32'h00000001
`define EP_RFCR_A_GIANT_OFFSET 1
`define EP_RFCR_A_GIANT 32'h00000002
`define EP_RFCR_A_HP_OFFSET 2
`define EP_RFCR_A_HP 32'h00000004
`define EP_RFCR_KEEP_CRC_OFFSET 3
`define EP_RFCR_KEEP_CRC 32'h00000008
`define EP_RFCR_HPAP_OFFSET 4
`define EP_RFCR_HPAP 32'h00000ff0
`define EP_RFCR_MRU_OFFSET 12
`define EP_RFCR_MRU 32'h03fff000
`define ADDR_EP_VCR0 7'hc
`define EP_VCR0_QMODE_OFFSET 0
`define EP_VCR0_QMODE 32'h00000003
`define EP_VCR0_FIX_PRIO_OFFSET 2
`define EP_VCR0_FIX_PRIO 32'h00000004
`define EP_VCR0_PRIO_VAL_OFFSET 4
`define EP_VCR0_PRIO_VAL 32'h00000070
`define EP_VCR0_PVID_OFFSET 16
`define EP_VCR0_PVID 32'h0fff0000
`define ADDR_EP_VCR1 7'h10
`define EP_VCR1_OFFSET_OFFSET 0
`define EP_VCR1_OFFSET 32'h000003ff
`define EP_VCR1_DATA_OFFSET 10
`define EP_VCR1_DATA 32'h0ffffc00
`define ADDR_EP_PFCR0 7'h14
`define EP_PFCR0_MM_ADDR_OFFSET 0
`define EP_PFCR0_MM_ADDR 32'h0000003f
`define EP_PFCR0_MM_WRITE_OFFSET 6
`define EP_PFCR0_MM_WRITE 32'h00000040
`define EP_PFCR0_ENABLE_OFFSET 7
`define EP_PFCR0_ENABLE 32'h00000080
`define EP_PFCR0_MM_DATA_MSB_OFFSET 8
`define EP_PFCR0_MM_DATA_MSB 32'hffffff00
`define ADDR_EP_PFCR1 7'h18
`define EP_PFCR1_MM_DATA_LSB_OFFSET 0
`define EP_PFCR1_MM_DATA_LSB 32'h00000fff
`define ADDR_EP_TCAR 7'h1c
`define EP_TCAR_PCP_MAP_OFFSET 0
`define EP_TCAR_PCP_MAP 32'h00ffffff
`define ADDR_EP_FCR 7'h20
`define EP_FCR_RXPAUSE_OFFSET 0
`define EP_FCR_RXPAUSE 32'h00000001
`define EP_FCR_TXPAUSE_OFFSET 1
`define EP_FCR_TXPAUSE 32'h00000002
`define EP_FCR_RXPAUSE_802_1Q_OFFSET 2
`define EP_FCR_RXPAUSE_802_1Q 32'h00000004
`define EP_FCR_TXPAUSE_802_1Q_OFFSET 3
`define EP_FCR_TXPAUSE_802_1Q 32'h00000008
`define EP_FCR_TX_THR_OFFSET 8
`define EP_FCR_TX_THR 32'h0000ff00
`define EP_FCR_TX_QUANTA_OFFSET 16
`define EP_FCR_TX_QUANTA 32'hffff0000
`define ADDR_EP_MACH 7'h24
`define ADDR_EP_MACL 7'h28
`define ADDR_EP_MDIO_CR 7'h2c
`define EP_MDIO_CR_DATA_OFFSET 0
`define EP_MDIO_CR_DATA 32'h0000ffff
`define EP_MDIO_CR_ADDR_OFFSET 16
`define EP_MDIO_CR_ADDR 32'h00ff0000
`define EP_MDIO_CR_RW_OFFSET 31
`define EP_MDIO_CR_RW 32'h80000000
`define ADDR_EP_MDIO_ASR 7'h30
`define EP_MDIO_ASR_RDATA_OFFSET 0
`define EP_MDIO_ASR_RDATA 32'h0000ffff
`define EP_MDIO_ASR_PHYAD_OFFSET 16
`define EP_MDIO_ASR_PHYAD 32'h00ff0000
`define EP_MDIO_ASR_READY_OFFSET 31
`define EP_MDIO_ASR_READY 32'h80000000
`define ADDR_EP_IDCODE 7'h34
`define ADDR_EP_DSR 7'h38
`define EP_DSR_LSTATUS_OFFSET 0
`define EP_DSR_LSTATUS 32'h00000001
`define EP_DSR_LACT_OFFSET 1
`define EP_DSR_LACT 32'h00000002
`define ADDR_EP_DMCR 7'h3c
`define EP_DMCR_EN_OFFSET 0
`define EP_DMCR_EN 32'h00000001
`define EP_DMCR_N_AVG_OFFSET 16
`define EP_DMCR_N_AVG 32'h0fff0000
`define ADDR_EP_DMSR 7'h40
`define EP_DMSR_PS_VAL_OFFSET 0
`define EP_DMSR_PS_VAL 32'h00ffffff
`define EP_DMSR_PS_RDY_OFFSET 24
`define EP_DMSR_PS_RDY 32'h01000000
`define ADDR_EP_INJ_CTRL 7'h44
`define EP_INJ_CTRL_PIC_CONF_IFG_OFFSET 0
`define EP_INJ_CTRL_PIC_CONF_IFG 32'h0000ffff
`define EP_INJ_CTRL_PIC_CONF_SEL_OFFSET 16
`define EP_INJ_CTRL_PIC_CONF_SEL 32'h00070000
`define EP_INJ_CTRL_PIC_CONF_VALID_OFFSET 19
`define EP_INJ_CTRL_PIC_CONF_VALID 32'h00080000
`define EP_INJ_CTRL_PIC_MODE_ID_OFFSET 20
`define EP_INJ_CTRL_PIC_MODE_ID 32'h00700000
`define EP_INJ_CTRL_PIC_MODE_VALID_OFFSET 23
`define EP_INJ_CTRL_PIC_MODE_VALID 32'h00800000
`define EP_INJ_CTRL_PIC_ENA_OFFSET 24
`define EP_INJ_CTRL_PIC_ENA 32'h01000000
`ifndef __ETH_PACKET_SVH
`define __ETH_PACKET_SVH
`include "simdrv_defs.svh"
typedef byte mac_addr_t[6];
typedef bit[11:0] vid_t;
typedef bit[2:0] pcp_t;
typedef enum
{
NONE = 0,
TX_FID,
RX_TIMESTAMP
} oob_type_t;
typedef struct {
bit [27:0] ts_r;
bit [3:0] ts_f;
bit [5:0] port_id;
bit [15:0] frame_id;
} wr_timestamp_t;
class EthPacket;
static const mac_addr_t dummy_mac = '{0,0,0,0,0,0} ;
static int _zero = 0;
static const int CMP_OOB = 1;
static const int CMP_STATUS = 2;
byte payload[];
int size;
mac_addr_t src, dst;
oob_type_t oob_type;
bit is_q;
bit is_hp;
bit has_smac;
bit has_crc;
bit error;
bit [15:0] ethertype;
bit [7:0] pclass;
vid_t vid;
pcp_t pcp;
oob_type_t oob;
wr_timestamp_t ts;
task set_size(int size);
payload = new[size](payload);
endtask
function new(int size = _zero);
// size = 0;
src = dummy_mac;
dst = dummy_mac;
is_q = 0;
is_hp = 0;
has_crc = 0;
oob_type = NONE;
payload = new[size](payload);
endfunction // new
task deserialize(byte data[]);
int i, hsize, psize;
if(data.size < 14)
begin
error = 1;
return;
end
for(i=0; i<6;i++)
begin
dst[i] = data[i];
src[i] = data [i+6];
end
has_crc = 0;
if(data[12] == 'h81 && data[13] == 'h00)
begin
is_q = 1;
hsize = 18;
ethertype = {data[16], data[17]};
vid = ((int'(data[14]) << 8) | data[15]) & 12'hfff;
pcp = data[14] >> 5;
end else begin
is_q = 0;
hsize = 14;
ethertype = {data[12], data[13]};
end
psize = data.size() - hsize;
if(psize <= 0)
begin
error = 1;
return;
end
payload = new[psize];
for(i=0;i<data.size() - hsize;i++)
payload[i] = data[hsize + i];
// error = 0;
endtask
task automatic serialize(ref byte data[]);
int i, hsize;
hsize = is_q ? 18 : 14;
data = new[payload.size() + hsize](data);
for(i=0; i<6;i++)
begin
data[i] = dst[i];
data[i + 6] = src[i];
end
if(is_q)
begin
data [12] = 8'h81;
data [13] = 8'h00;
data [14] = {pcp, 1'b0, vid[11:8]};
data [15] = vid[7:0];
data [16] = ethertype[15:8];
data [17] = ethertype[7:0];
end else begin
data[12] = ethertype [15:8];
data[13] = ethertype [7:0];
end
for (i=0; i<payload.size(); i++)
data[i + hsize] = payload[i];
endtask // serialize
function bit equal(ref EthPacket b, input int flags = 0);
if(src != b.src || dst != b.dst || ethertype != b.ethertype)
begin
$display("notequal: hdr");
return 0;
end
if(is_q ^ b.is_q)
begin
$display("notequal: q");
return 0;
end
if(is_q && (vid != b.vid || pcp != b.pcp))
return 0;
if(payload != b.payload)
begin
$display("notequal: payload");
return 0;
end
// return 0;
if(flags & CMP_STATUS)
if(error ^ b.error)
return 0;
if(flags & CMP_OOB) begin
if (b.oob_type != oob_type)
return 0;
if(oob_type == TX_FID && (b.ts.frame_id != ts.frame_id))
return 0;
end
return 1;
endfunction // equal
task copy(ref EthPacket b);
endtask // copy
task hexdump(byte buffer []);
string str;
int size ;
int i;
int offset = 0;
const int per_row = 16;
size = buffer.size();
while(size > 0)
begin
int n;
n = (size > per_row ? per_row : size);
$sformat(str,"+%03x: ", offset);
for(i=0;i<n;i++) $sformat(str,"%s%s%02x", str, (i==(per_row/2)?"-":" "), buffer[offset + i]);
$display(str);
offset = offset + n;
size = size - n;
end
endtask // hexdump
task dump(int full = _zero);
string str, tmp;
int t;
if(is_q)
$sformat(str, "802.1q [VID %5d/PCP %d] ", vid, pcp);
else
str = "802.1 ";
$sformat(str, "%s DST [%02x:%02x:%02x:%02x:%02x:%02x] SRC: [%02x:%02x:%02x:%02x:%02x:%02x] Type = 0x%04x size = %d F:(%s%s)", str, dst[0],dst[1],dst[2],dst[3],dst[4],dst[5], src[0],src[1],src[2],src[3],src[4], src[5], ethertype, (is_q ? 18 : 14) + payload.size(),
is_hp ? "H" : " ", has_crc ? "C" : " ");
if(oob_type == TX_FID)
begin
$sformat(tmp, "TxOOB: %x", ts.frame_id);
str = {str, tmp};
end
$display(str);
hexdump(payload);
endtask // dump
endclass // EthPacket
class EthPacketGenerator;
protected EthPacket template;
protected int min_size, max_size;
protected int seed;
static const int SMAC = (1<<0);
static const int DMAC = (1<<1);
static const int ETHERTYPE = (1<<2);
static const int VID = (1<<3);
static const int PCP = (1<<4);
static const int PAYLOAD = (1<<5);
static const int SEQ_PAYLOAD = (1<<7);
static const int SEQ_ID = (1<<10);
static const int TX_OOB = (1<<6);
static const int EVEN_LENGTH = (1<<8);
static const int RX_OOB = (1<<9);
static const int ALL = SMAC | DMAC | VID | ETHERTYPE | PCP | PAYLOAD ;
protected int r_flags;
protected int m_current_frame_id;
protected int cur_seq_id;
function new();
r_flags =ALL;
min_size = 64;
max_size = 128;
m_current_frame_id = 0;
template = new;
cur_seq_id = 0;
endfunction // new
task set_randomization(int flags);
r_flags = flags;
endtask // randomize
typedef byte dyn_array[];
protected function dyn_array random_bvec(int size);
byte v[];
int i;
// $display("RandomBVEC %d", size);
v = new[size](v);
for(i=0;i<size;i++)
v[i] = $dist_uniform(seed, 0, 256);
return v;
endfunction // random_bvec
task set_seed(int seed_);
seed = seed_;
endtask // set_seed
function int get_seed();
return seed;
endfunction // get_seed
protected function dyn_array seq_payload(int size);
byte v[];
int i;
v = new[size](v);
for(i=0;i<size;i++)
v[i] = i;
return v;
endfunction // random_bvec
function automatic EthPacket gen(int set_len = 0);
EthPacket pkt;
int len;
pkt = new;
if (r_flags & SMAC) pkt.src = random_bvec(6); else pkt.src = template.src;
if (r_flags & DMAC) pkt.dst = random_bvec(6); else pkt.dst = template.dst;
pkt.ethertype = (r_flags & ETHERTYPE ? $dist_uniform(seed, 0, 1<<16) : template.ethertype);
pkt.is_q = template.is_q;
pkt.vid = template.vid;
pkt.pcp = template.pcp;
pkt.has_smac = template.has_smac;
if(set_len > 0) len = set_len;
else len = $dist_uniform(seed, min_size, max_size);
if((len & 1) && (r_flags & EVEN_LENGTH))
len++;
if(r_flags & PAYLOAD) pkt.payload = random_bvec(len);
else if(r_flags & SEQ_PAYLOAD) pkt.payload = seq_payload(len);
else pkt.payload = template.payload;
if(r_flags & SEQ_ID)
begin
pkt.payload[0] = cur_seq_id & 'hff;
pkt.payload[1] = (cur_seq_id>>8) & 'hff;
pkt.payload[2] = (cur_seq_id>>16) & 'hff;
pkt.payload[3] = (cur_seq_id>>24) & 'hff;
cur_seq_id++;
end
if(r_flags & TX_OOB)
begin
pkt.ts.frame_id = m_current_frame_id++;
pkt.oob_type = TX_FID;
end
pkt.size = len + 14; //payload + header
return pkt;
endfunction
task set_template(EthPacket pkt);
template = pkt;
endtask // set_template
task set_size(int smin, int smax);
min_size = smin;
max_size = smax;
endtask // set_size
endclass // EthPacketGenerator
virtual class EthPacketSink;
static int _null = 0;
pure virtual function int poll();
virtual function int permanent_stall_enable(); endfunction
virtual function int permanent_stall_disable(); endfunction
pure virtual task recv(ref EthPacket pkt, ref int result = _null);
endclass // EthPacketSink
virtual class EthPacketSource;
static int _null = 0;
pure virtual task send(ref EthPacket pkt, ref int result = _null);
endclass // PacketSource
`endif
// Fabric TAP emulator example.
// usage: (as root)
// tunctl -t tap0
// ifconfig tap0 192.168.100.100
// arping -I tap0 192.168.100.101
// you should see some ARP requests coming
`timescale 1ns / 1ps
`include "fabric_emu.sv"
`include "fabric_emu_tap.sv"
module main;
const int c_clock_period = 8;
reg clk = 0;
reg rst_n = 0;
`WRF_WIRES(from_tap); // Data coming from tap0 interface
`WRF_WIRES(to_tap); // Data going to tap0 interface
// generate clock and reset signals
always #(c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
// Two fabric emulators talking to each other
fabric_emu_tap U_tap
(
.clk_sys_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, from_tap), // connect fabric source/sinks
`WRF_CONNECT_SINK(tx, to_tap)
);
fabric_emu U_emu
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, to_tap),
`WRF_CONNECT_SINK(tx, from_tap)
);
// Check if there's anything received by the TAP emulator
always @(posedge clk) if (U_emu.poll())
begin
ether_frame_t frame;
$display("TAP Emulator received a frame!");
U_emu.receive(frame);
dump_frame_header("EmuB RX: ", frame);
frame.hdr.src = 'h010203040506; // modify the MAC address and send the frame back to tap interface
U_emu.send(frame.hdr, frame.payload, frame.size);
end
endmodule // main
This diff is collapsed.
`ifndef __FABRIC_EMU_DEFS_SV
`define __FABRIC_EMU_DEFS_SV
/* Ethernet frame header extended with WR-compliant OOB signalling */
typedef struct {
bit no_mac; // when 1, there's no valid source MAC present in the frame header and the SRC MAC field must be filled by the endpoint
bit [47:0] dst; // DST MAC
bit [47:0] src; // SRC MAC
bit [15:0] ethertype;
bit is_802_1q; // when 1, the frame has 802.1q header
bit [11:0] vid; // VLAN ID
bit [2:0] prio; // PCP priority tag
int oob_type; // OOB TYPE: OOB_TYPE_TXTS = TX frame ID (for TX timestamping), OOB_TYPE_RXTS = RX timestamp
bit[15:0] oob_fid; //
bit [27:0] timestamp_r;
bit [3:0] timestamp_f;
bit [4:0] port_id;
bit has_timestamp; // when 1, the TX/RX timestamp is valid
} ether_header_t;
/* Full ethernet frame */
typedef struct {
ether_header_t hdr;
int size;
bit[7:0] payload[$];
bit[31:0] fcs;
bit error;
bit has_payload;
bit has_raw;
byte raw_data[];
} ether_frame_t;
/* WR-compliant TX frame timestamp */
typedef struct {
bit[15:0] fid;
bit [4:0] pid;
bit [27:0] timestamp_r;
bit [3:0] timestamp_f;
} tx_timestamp_t;
`timescale 1ns/1ps
/* Bus widths definition, taken from global_defs.vhd */
`define c_wrsw_ctrl_size 4
`define c_wrsw_oob_frame_id_size 16
`define c_wrsw_timestamp_size_r 28
`define c_wrsw_timestamp_size_f 4
`define c_wrsw_mac_addr_width 48
`define c_wrsw_vid_width 12
`define c_wrsw_prio_width 3
/* ctrl bus codes */
`define c_wrsw_ctrl_none 4'h0
`define c_wrsw_ctrl_dst_mac 4'h1
`define c_wrsw_ctrl_src_mac 4'h2
`define c_wrsw_ctrl_ethertype 4'h3
`define c_wrsw_ctrl_vid_prio 4'h4
`define c_wrsw_ctrl_tx_oob 4'h5
`define c_wrsw_ctrl_rx_oob 4'h6
`define c_wrsw_ctrl_payload 4'h7
/* OOB types */
`define OOB_TYPE_TXTS 1
`define OOB_TYPE_RXTS 2
`define QUEUE_MAX_FRAMES 128
//
// WhiteRabbit Fabric Interface (WRF) Macros
//
// declares basic fabric interface (only the mandatory singals)
// sink port list in a verilog/SV module, prefixed with "prefix":
// for example `WRF_PORTS_SINK(test) will generate the following signals
// test_sof_p1_i, test_eof_p1_i, test_data_i, etc....
`define WRF_PORTS_SINK(prefix) \
input [15:0] prefix``_data_i,\
input [3:0] prefix``_ctrl_i,\
input prefix``_bytesel_i,\
input prefix``_sof_p1_i,\
input prefix``_eof_p1_i,\
output prefix``_dreq_o,\
input prefix``_valid_i,\
input prefix``_rerror_p1_i
// same as above but with all WRF signals
`define WRF_FULL_PORTS_SINK(prefix) \
`WRF_PORTS_SINK(prefix),\
output prefix``_terror_p1_o,\
input prefix``_idle_i,\
input prefix``_tabort_p1_i,\
output prefix``_rabort_p1_o
// like the macro above, but for fabric source, mandatory signals only
`define WRF_PORTS_SOURCE(prefix) \
output [15:0] prefix``_data_o,\
output [3:0] prefix``_ctrl_o,\
output prefix``_bytesel_o,\
output prefix``_sof_p1_o,\
output prefix``_eof_p1_o,\
input prefix``_dreq_i,\
output prefix``_valid_o,\
output prefix``_rerror_p1_o
// same as above, but for full WRF
`define WRF_FULL_PORTS_SOURCE(prefix) \
`WRF_PORTS_SOURCE(prefix), \
input prefix``_terror_p1_i,\
output prefix``_idle_o,\
output prefix``_tabort_p1_o,\
input prefix``_rabort_p1_i
// declares a list of verilog/SV wires for a given fabric name
`define WRF_WIRES(prefix) \
wire [15:0] prefix``_data;\
wire [3 :0] prefix``_ctrl;\
wire prefix``_bytesel;\
wire prefix``_dreq;\
wire prefix``_valid;\
wire prefix``_sof_p1;\
wire prefix``_eof_p1;\
wire prefix``_rerror_p1;
// same as above, but for full WRF
`define WRF_FULL_WIRES(prefix) \
`WRF_WIRES(prefix)\
wire prefix``_terror_p1;\
wire prefix``_idle;\
wire prefix``_tabort_p1;\
wire prefix``_rabort_p1;
// Connects fabric sink ports prefixed with port_pfx to fabric wires prefixed with fab_pfx
`define _WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx) \
.port_pfx``_data_i(fab_pfx``_data),\
.port_pfx``_ctrl_i(fab_pfx``_ctrl),\
.port_pfx``_bytesel_i(fab_pfx``_bytesel),\
.port_pfx``_dreq_o(fab_pfx``_dreq),\
.port_pfx``_valid_i(fab_pfx``_valid),\
.port_pfx``_sof_p1_i(fab_pfx``_sof_p1),\
.port_pfx``_eof_p1_i(fab_pfx``_eof_p1),\
.port_pfx``_rerror_p1_i(fab_pfx``_rerror_p1)
// full fabric I/F version
`define WRF_FULL_CONNECT_SINK(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx), \
.port_pfx``_terror_p1_o(fab_pfx``_terror_p1),\
.port_pfx``_tabort_p1_i(fab_pfx``_tabort_p1),\
.port_pfx``_rabort_p1_o(fab_pfx``_rabort_p1),\
.port_pfx``_idle_i(fab_pfx``_idle)
// Connects fabric sink ports prefixed with port_pfx to fabric wires prefixed with fab_pfx
`define WRF_CONNECT_SINK(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SINK(port_pfx, fab_pfx), \
.port_pfx``_terror_p1_o(),\
.port_pfx``_tabort_p1_i(1'b0),\
.port_pfx``_rabort_p1_o(),\
.port_pfx``_idle_i(1'b0)
`define _WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx) \
.port_pfx``_data_o(fab_pfx``_data),\
.port_pfx``_ctrl_o(fab_pfx``_ctrl),\
.port_pfx``_bytesel_o(fab_pfx``_bytesel),\
.port_pfx``_dreq_i(fab_pfx``_dreq),\
.port_pfx``_valid_o(fab_pfx``_valid),\
.port_pfx``_sof_p1_o(fab_pfx``_sof_p1),\
.port_pfx``_eof_p1_o(fab_pfx``_eof_p1),\
.port_pfx``_rerror_p1_o(fab_pfx``_rerror_p1)
// same as above, but for source ports, full WRF version
`define WRF_FULL_CONNECT_SOURCE(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx),\
.port_pfx``_terror_p1_i(fab_pfx``_terror_p1),\
.port_pfx``_tabort_p1_o(fab_pfx``_tabort_p1),\
.port_pfx``_rabort_p1_i(fab_pfx``_rabort_p1),\
.port_pfx``_idle_o(fab_pfx``_idle)
// same as above, but for source ports, basic WRF version
`define WRF_CONNECT_SOURCE(port_pfx, fab_pfx) \
`_WRF_CONNECT_MANDATORY_SOURCE(port_pfx, fab_pfx),\
.port_pfx``_terror_p1_i(1'b0),\
.port_pfx``_tabort_p1_o(),\
.port_pfx``_rabort_p1_i(1'b0),\
.port_pfx``_idle_o()
`endif
\ No newline at end of file
// Fabric emulator example, showing 2 fabric emulators connected together and exchanging packets.
`timescale 1ns / 1ps
`include "fabric_emu.sv"
module main;
const int c_clock_period = 8;
reg clk = 0;
reg rst_n = 0;
`WRF_WIRES(ab); // Emu A to B fabric
`WRF_WIRES(ba); // And the other way around
// generate clock and reset signals
always #(c_clock_period/2) clk <= ~clk;
initial begin
repeat(3) @(posedge clk);
rst_n = 1;
end
// Two fabric emulators talking to each other
fabric_emu U_emuA
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ba), // connect fabric source/sinks
`WRF_CONNECT_SINK(tx, ab)
);
fabric_emu U_emuB
(
.clk_i(clk),
.rst_n_i(rst_n),
`WRF_CONNECT_SOURCE(rx, ab),
`WRF_CONNECT_SINK(tx, ba)
);
initial begin
ether_header_t hdr;
int buffer[1024];
int i;
wait(U_emuA.ready); // wait until both emulators are initialized
wait(U_emuB.ready);
hdr.src = 'h123456789abcdef;
hdr.dst = 'hcafeb1badeadbef;
hdr.ethertype = 1234;
hdr.is_802_1q = 0;
hdr.oob_type = `OOB_TYPE_RXTS;
hdr.timestamp_r = 10000;
hdr.timestamp_f = 4;
hdr.port_id = 5;
for(i=0;i<100;i++)
buffer[i] = i;
// simulate some flow throttling
U_emuA.simulate_rx_throttling(1, 50);
U_emuA.send(hdr, buffer, 100);
hdr.src = 'h0f0e0a0b0d00;
U_emuB.send(hdr, buffer, 50);
end
// Check if there's anything received by EMU B
always @(posedge clk) if (U_emuB.poll())
begin
ether_frame_t frame;
$display("Emulator B received a frame!");
U_emuB.receive(frame);
dump_frame_header("EmuB RX: ", frame);
end
// Check if there's anything received by EMU A
always @(posedge clk) if (U_emuA.poll())
begin
ether_frame_t frame;
$display("Emulator A received a frame!");
U_emuA.receive(frame);
dump_frame_header("EmuA RX: ", frame);
end
endmodule // main
`timescale 1ns/1ps
/* Ethernet FCS calculator class */
class CCRC32;
protected bit [31:0] crc;
protected bit [31:0] crc_tab[256];
function new();
reg [31:0] c, poly;
int i, j;
poly = 32'hEDB88320;
for (i = 0; i < 256; i++) begin
c = i;
for (j = 8; j > 0; j--) begin
if (c & 1)
c = (c >> 1) ^ poly;
else
c >>= 1;
end
crc_tab[i] = c;
end
crc = 32'hffffffff;
endfunction // new
function bit[31:0] bitrev(bit[31:0] x, int n);
reg [31:0] y= 0;
int i;
for(i=0;i<n;i++) if(x & (1<<i)) y|= 1<< (n-1-i);
bitrev=y;
endfunction
task update_int(bit[7:0] x);
crc = ((crc >> 8) & 32'h00FFFFFF) ^ crc_tab[(crc ^ bitrev(x,8)) & 32'hFF];
endtask
task update(input [15:0] x, int bytesel);
update_int(x[15:8]);
if(!bytesel)
update_int(x[7:0]);
endtask // update
function bit[31:0] get();
get = bitrev(crc ^ 32'hffffffff, 32);
endfunction // get
endclass
/* Simple packet queue */
class CPacketQueue;
protected int head, tail, count;
protected int size;
protected ether_frame_t d[];
function new (int _size);
size = _size;
head = 0;
tail = 0;
count = 0;
d = new [_size];
endfunction // new
task push(input ether_frame_t frame);
if(count == size) begin
$display("CPacketQueue::push(): queue overflow");
$stop();
end
d[head] = frame;
head++; if(head == size) head = 0;
count++;
endtask // push
task pop (output ether_frame_t frame);
if(count <= 0) begin
$display("CPacketQueue::pop(): queue empty");
$stop();
end
frame = d[tail];
tail++; if(tail == size) tail = 0;
count--;
endtask // pop
function int get_count();
return count;
endfunction // get_count
/* Looks for a packet with matching OOB frame identifier and updates it with the new timestamp value */
function int update_tx_timestamp(input [15:0] oob_fid,
input [4:0] port_id,
input [31:0] ts_value);
int i;
i = tail;
while(i != head)
begin
if(d[i].hdr.oob_type == `OOB_TYPE_TXTS && d[i].hdr.oob_fid == oob_fid) begin
d[i].hdr.timestamp_r = ts_value[27:0];
d[i].hdr.timestamp_f = ts_value[31:28];
d[i].hdr.has_timestamp = 1;
return 1;
end
i++;
if(i == count) i = 0;
end
return 0;
endfunction // update_tx_timestamp
endclass // CPacketQueue
// converts a nbytes-long number (hex) to hexadecimal string
function automatic string hex_2_str(input [47:0] hex, int nbytes);
int i;
string s = "";
string hexchars = "0123456789abcdef";
reg [47:0] t;
t = hex;
for(i=0; i<2*nbytes; i++) begin
s= {hexchars[t&'hf], s};
t=t>>4;
end
return s;
endfunction // hex_2_str
// formats an Ethernet frame header as a nice looking string
function automatic string format_ether_header(input ether_header_t hdr);
string s = {"DST: ", hex_2_str(hdr.dst, 6),
" SRC: ", hex_2_str(hdr.src, 6),
" Type: 0x",hex_2_str(hdr.ethertype, 2) };
if(hdr.is_802_1q) s = {s, " VLAN: 0x", hex_2_str({4'b0,hdr.vid}, 2), " PRIO: ", hex_2_str({5'b0, hdr.prio},1) };
return s;
endfunction // automatic
task dump_frame_header(string s, ether_frame_t frame);
$display("%s %s length = %d %s %s", s, format_ether_header(frame.hdr), frame.size, frame.error?"ERROR":"OK", frame.hdr.has_timestamp?"TS":"NoTS");
endtask // dump_frame_header
\ No newline at end of file
/* Linux TAP driver interface to WR fabric */
`timescale 1ns/1ps
`include "fabric_emu_defs.sv"
// module uses Linux TAP interface as a packet source/sink for the fabric simulator.
// link with VPI tap.sl
/* TODO:
- add CTRL code generation
*/
class CPacketFIFO;
int m_size, m_wrptr, m_rdptr, m_count, m_pktcnt;
bit[8:0] m_buffer[];
function new(int size);
m_size = size;
m_buffer = new [size];
m_rdptr = 0;
m_wrptr = 0;
m_count = 0;
m_pktcnt = 0;
endfunction // new
task _push(bit[8:0] val);
if(m_count >= m_size)
$error("FIFO overflow");
m_buffer[m_wrptr++] = val;
m_count++;
endtask // _push
function bit[8:0] get();
return m_buffer[m_rdptr];
endfunction // _get
function bit[8:0] pop();
bit [8:0] rval;
rval = m_buffer[m_rdptr++];
m_count--;
return rval;
endfunction
function int empty();
return (m_count == 0);
endfunction // _empty
task write(bit [7:0] val, bit eop);
// $display("fwrite: %x %x", val, eop);
_push({eop,val});
endtask // write
function int got_packet();
return (m_pktcnt != 0 );
endfunction // got_packets
function int end_of_packet();
bit[8:0] rval;
rval = get();
return rval[8];
endfunction // end_of_packet
endclass // packet_fifo
module fabric_emu_tap
(
input clk_sys_i,
input rst_n_i,
`WRF_FULL_PORTS_SINK(tx),
`WRF_FULL_PORTS_SOURCE(rx)
);
reg [7:0] tap_rx;
reg tap_dvalid_rx;
reg [7:0] tap_tx = 0;
reg tap_dvalid_tx = 0;
CPacketFIFO rx_fifo;
CPacketFIFO tx_fifo;
const int c_FIFO_SIZE = 32768;
const int c_INTERFRAME_GAP = 32768;
assign tx_drop_o = 0;
initial begin
rx_fifo = new(c_FIFO_SIZE);
tx_fifo = new (c_FIFO_SIZE);
end
reg rx_sof_p_int = 0;
reg rx_eof_p_int = 0;
reg tx_dreq_int = 0;
reg [15:0] rx_data_int = 0;
reg [3:0] rx_ctrl_int = 0;
reg rx_error_p_int = 0;
reg rx_bytesel_int = 0;
reg rx_valid_int = 0;
assign rx_sof_p1_o = rx_sof_p_int;
assign rx_eof_p1_o = rx_eof_p_int;
assign tx_dreq_o = tx_dreq_int;
assign rx_data_o = rx_data_int;
assign rx_ctrl_o = rx_ctrl_int;
assign rx_rerror_p1_o = rx_error_p_int;
assign rx_bytesel_o = rx_bytesel_int;
assign rx_valid_o = rx_valid_int;
assign rx_idle_o = 0;
assign rx_tabort_p1_o = 0;
assign tx_terror_p1_o = 0;
assign tx_rabort_p1_o = 0;
reg tap_dvalid_rx_d0 = 0;
reg [7:0] tap_data_d0;
always@(posedge clk_sys_i or negedge clk_sys_i)
begin
// TAP interface PLI call
$tap_io(tap_tx, tap_dvalid_tx, tap_rx, tap_dvalid_rx);
tap_dvalid_rx_d0 <= tap_dvalid_rx;
// TAP reception
if(tap_dvalid_rx_d0 && !tap_dvalid_rx)
rx_fifo.write(0, 1);
else if (tap_dvalid_rx)
rx_fifo.write(tap_rx, 0);
// TAP transmission
if(!tx_fifo.empty())
begin
bit[7:0] data;
bit eof;
{eof, data} = tx_fifo.pop();
// $display("TX: %x eof %b", data, eof);
tap_data_d0 <= data;
tap_tx <= tap_data_d0;
tap_dvalid_tx = !eof;
end
end
task automatic wait_clks(int howmuch);
while(howmuch--) @(posedge clk_sys_i);
endtask // automatic
const int FRX_NOFRAME = 1;
const int FRX_TX = 2;
const int FRX_EOF = 3;
int fab_rx_state;
int fab_rx_offset;
function bit[3:0] gen_ctrl(int offset);
if(offset >=0 && offset <= 2)
return `c_wrsw_ctrl_dst_mac;
else if(offset >=3 && offset <= 5)
return `c_wrsw_ctrl_src_mac;
else if(offset == 6)
return `c_wrsw_ctrl_ethertype;
else
return `c_wrsw_ctrl_payload;
endfunction // gen_ctrl
task automatic fabric_do_rx();
// $display("FabDoRX");
case (fab_rx_state)
FRX_NOFRAME:begin
rx_eof_p_int <= 0;
if(!rx_fifo.empty()) begin
rx_sof_p_int <= 1;
fab_rx_state = FRX_TX;
fab_rx_offset = 0;
return;
end
end
FRX_TX:begin
bit [8:0] lsb, msb;
rx_sof_p_int <= 0;
if(rx_fifo.end_of_packet()) begin
rx_fifo.pop();
fab_rx_state <= FRX_EOF;
rx_valid_int <= 0;
return;
end
msb = rx_fifo.pop();
if(rx_fifo.end_of_packet()) begin
rx_fifo.pop();
fab_rx_state <= FRX_EOF;
rx_valid_int <= 1;
rx_data_int [15:8] <= msb[7:0];
rx_ctrl_int <= gen_ctrl(fab_rx_offset++);
rx_bytesel_int <= 1;
end else begin
lsb = rx_fifo.pop();
rx_valid_int <= 1;
rx_bytesel_int <= 0;
rx_data_int = {msb[7:0], lsb[7:0] };
rx_ctrl_int <= gen_ctrl(fab_rx_offset++);
end
end
FRX_EOF: begin
rx_eof_p_int <= 1;
wait_clks(1);
rx_eof_p_int <= 0;
fab_rx_state <= FRX_NOFRAME;
wait_clks(c_INTERFRAME_GAP);
end
endcase // case (fab_rx_state)
endtask // automatic
task fabric_do_tx();
bit[7:0] buffer[2048];
int i, len ;
i = 0;
while(1) begin
if(tx_valid_i) begin
// ignore OOB
if(tx_ctrl_i == `c_wrsw_ctrl_tx_oob || tx_ctrl_i == `c_wrsw_ctrl_rx_oob)
continue;
buffer[i++] = tx_data_i[15:8];
if(!tx_bytesel_i)
buffer[i++] = tx_data_i[7:0];
end
if(tx_eof_p1_i)
break;
wait_clks(1);
end
// $display("FabTX: %d bytes", i);
len = i;
for(i=0;i<len;i++)
tx_fifo.write(buffer[i], 0);
tx_fifo.write(0, 1);
endtask // fabric_do_tx
initial fab_rx_state = FRX_NOFRAME;
initial forever begin
wait_clks(1);
if(rx_dreq_i)
fabric_do_rx();
else
rx_valid_int <= 0;
end
initial forever begin
tx_dreq_int <= 1;
wait_clks(1);
if(tx_sof_p1_i)
fabric_do_tx();
end
endmodule // tap_if
\ No newline at end of file
//
// Title : Software Wishbone master unit for testbenches
//
// File : if_wishbone.sv
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : SystemVerilog
//
// Default values of certain WB parameters.
`include "simdrv_defs.sv"
interface IWishboneClassicMaster
(
input clk_i,
input rst_n_i
);
parameter g_data_width = 32;
parameter g_addr_width = 32;
/* Interface signals */
logic [g_addr_width - 1 : 0] adr;
logic [g_data_width - 1 : 0] dat_o;
logic [3 : 0] sel; // FIXME: 32-bit only
wire [g_data_width - 1 : 0] dat_i;
wire ack;
logic cyc;
logic stb;
logic we;
wire stall;
initial begin
adr = 0;
dat_o = 0;
sel = 0;
cyc = 0;
stb = 0;
we = 0;
end
time last_access_t = 0;
reg [g_data_width-1:0] dummy;
// enables/disables displaying information about each read/write operation.
int tb_verbose = 0;
task verbose(int onoff);
tb_verbose = onoff;
endtask // wb_verbose
task classic_single_rw_generic;
input [g_addr_width - 1 : 0] trans_addr;
input [g_data_width - 1 : 0] trans_wdata;
output [g_data_width - 1 : 0] trans_rdata;
input rw;
input [3:0] size;
begin : rw_generic_main
if(tb_verbose && rw)
$display("WB write %s: addr %x, data %x",
(size==1?"byte":((size==2)?"short":"int")),
trans_addr, trans_wdata);
if($time != last_access_t) begin
@(posedge clk_i);
end
stb<=1;
cyc<=1;
adr <= {2'b00, trans_addr[31:2]};
we <= rw;
if(rw) begin
case(size)
4: begin dat_o<=trans_wdata; sel <= 4'b1111; end
2: begin
if(adr[1]) begin
dat_o[31:16] <= trans_wdata[15:0];
sel <= 4'b1100;
end else begin
dat_o[15:0] <= trans_wdata[15:0];
sel <= 4'b0011;
end
end
1: begin
case(adr[1:0])
0: begin dat_o[31:24] <= trans_wdata[7:0]; sel <= 4'b1000; end
1: begin dat_o[23:16] <= trans_wdata[7:0]; sel <= 4'b0100; end
2: begin dat_o[15:8] <= trans_wdata[7:0]; sel <= 4'b0010; end
3: begin dat_o[7:0] <= trans_wdata[7:0]; sel <= 4'b0001; end
endcase // case(addr[1:0])
end
endcase // case(size)
end // if (rw)
@(posedge clk_i);
if(ack == 0) begin
while(ack == 0) begin @(posedge clk_i); end
end
trans_rdata = dat_i;
cyc <= 0;
we<=0;
stb<=0;
if(tb_verbose && !rw)
$display("WB read %s: addr %x, data %x",
(size==1?"byte":((size==2)?"short":"int")),
trans_addr, trans_rdata);
last_access_t = $time;
end
endtask // rw_generic
task write32;
input [g_addr_width - 1 : 0] addr;
input [31 : 0] data_i;
begin
classic_single_rw_generic(addr, data_i, dummy, 1, 4);
end
endtask // write32
task read32;
input [g_addr_width - 1 : 0] addr;
output [31 : 0] data_o;
begin : read32_body
reg [g_data_width - 1 : 0] rval;
classic_single_rw_generic(addr, 0, rval, 0, 4);
data_o = rval[31:0];
end
endtask // write32
modport master
(
output adr,
output dat_o,
output sel,
output cyc,
output stb,
output we,
input ack,
input dat_i,
input stall);
endinterface // IWishbone
interface IWishboneLink;
parameter g_data_width = 32;
parameter g_addr_width = 32;
wire [g_addr_width - 1 : 0] adr;
wire [g_data_width - 1 : 0] dat_o;
wire [g_data_width - 1 : 0] dat_i;
wire [(g_data_width/8)-1 : 0] sel;
wire ack;
wire stall;
wire err;
wire rty;
wire cyc;
wire stb;
wire we;
modport slave
(
output adr,
output dat_o,
input dat_i,
output sel,
output cyc,
output stb,
output we,
input ack,
input stall,
input err,
input rty
);
modport master
(
input adr,
input dat_o,
output dat_i,
input sel,
input cyc,
input stb,
input we,
output ack,
output stall,
output err,
output rty
);
endinterface // IWishboneLink
This diff is collapsed.
`ifndef __IF_WISHBONE_SLAVE_SVH
`define __IF_WISHBONE_SLAVE_SVH
`timescale 1ns/1ps
`include "if_wishbone_types.svh"
interface IWishboneSlave
(
input clk_i,
input rst_n_i
);
parameter g_addr_width = 32;
parameter g_data_width = 32;
wire [g_addr_width - 1: 0] adr;
wire [g_data_width - 1: 0] dat_i;
wire [(g_data_width/8)-1 : 0] sel;
logic [g_data_width - 1 : 0] dat_o;
logic ack;
logic stall;
logic err;
logic rty;
wire cyc;
wire stb;
wire we;
time last_access_t = 0;
modport slave
(
input adr,
input dat_o,
input sel,
input cyc,
input stb,
input we,
output ack,
output dat_i,
output stall,
output err,
output rty
);
wb_cycle_t c_queue[$];
wb_cycle_t current_cycle;
reg cyc_prev;
int trans_index;
int first_transaction;
struct {
wb_cycle_type_t mode;
int gen_random_stalls;
int gen_random_errors;
int stall_min_duration;
int stall_max_duration;
real stall_prob;
real error_prob;
} settings;
int permanent_stall = 0;
function automatic int _poll(); return poll(); endfunction
function automatic int _permanent_stall_enable(); return permanent_stall_enable(); endfunction
function automatic int _permanent_stall_disable(); return permanent_stall_disable(); endfunction
task automatic _get(ref wb_cycle_t xfer); get(xfer); endtask
class CIWBSlaveAccessor extends CWishboneAccessor;
function automatic int poll();
return _poll();
endfunction
function automatic int permanent_stall_enable();
return _permanent_stall_enable();
endfunction
function automatic int permanent_stall_disable();
return _permanent_stall_disable();
endfunction
task get(ref wb_cycle_t xfer);
_get(xfer);
endtask
task clear();
endtask // clear
endclass // CIWBSlaveAccessor
function CIWBSlaveAccessor get_accessor();
CIWBSlaveAccessor tmp;
tmp = new;
return tmp;
endfunction // get_accessor
function automatic int permanent_stall_enable();
permanent_stall = 1;
$display("permanent stall ON");
return permanent_stall;
endfunction
function automatic int permanent_stall_disable();
permanent_stall = 0;
$display("permanent stall OFF");
return permanent_stall;
endfunction
function automatic int poll();
return c_queue.size() != 0;
endfunction // poll
task automatic get(ref wb_cycle_t xfer);
while(c_queue.size() <= 0)
@(posedge clk_i);
xfer = c_queue.pop_front();
endtask // pop_cycle
always@(posedge clk_i) cyc_prev <= cyc;
wire cyc_start = !cyc_prev && cyc;
wire cyc_end = cyc_prev && !cyc;
task gen_random_stalls();
static int stall_remaining = 0;
static int seed = 0;
// $display("stallr: %d\n", stall_remaining);
if(settings.gen_random_stalls && (probability_hit(settings.stall_prob) || stall_remaining > 0))
begin
if(stall_remaining == 0)
stall_remaining = $dist_uniform(seed,
settings.stall_min_duration,
settings.stall_max_duration);
if(stall_remaining)
stall_remaining--;
stall <= 1;
end else
stall <= 0;
endtask // gen_random_stalls
function automatic int count_ones(int x, int n_bits);
int i, cnt;
cnt = 0;
for(i=0;i<n_bits;i++) if(x & (1<<i)) cnt ++;
return cnt;
endfunction
function automatic int count_leading_zeroes(int x, int n_bits);
int i;
for(i=0;i<n_bits && !(x & (1<<i)); i++);
return i;
endfunction // count_leading_zeroes
function automatic int count_trailing_zeroes(int x, int n_bits);
int i;
for(i=n_bits-1;i>=0 && !(x & (1<<i)); i--);
return (n_bits-1-i);
endfunction
task pipelined_fsm();
// ML
if(permanent_stall)
stall <= 1;
else if(settings.gen_random_stalls)
gen_random_stalls();
else
stall <= 0;
/* -----\/----- EXCLUDED -----\/-----
if(cyc) begin
end else
stall <= 0;
-----/\----- EXCLUDED -----/\----- */
if(cyc_start) begin
current_cycle.data = {};
trans_index <= 0;
first_transaction = 1;
end
if(cyc_end) begin
c_queue.push_back(current_cycle);
end
if(cyc && settings.gen_random_errors && probability_hit(settings.error_prob))
err <= 1;
else
err <= 0;
if(stb && we && !stall && cyc) begin
int oc, lzc, tzc;
wb_xfer_t d;
oc = count_ones(sel, g_data_width/8);
lzc = count_leading_zeroes(sel, g_data_width/8);
tzc = count_trailing_zeroes(sel, g_data_width/8);
d.a = adr * (g_data_width / 8);
d.size = oc;
d.d = (dat_i>>(8*lzc)) & ((1<<(oc*8)) -1);
if(lzc + tzc + oc != g_data_width/8)
$error("IWishboneSlave [write a %x d %x sel %x]: non-contiguous sel", adr, dat_i, sel);
d.sel [g_data_width/8-1:0] = sel;
current_cycle.data.push_back(d);
// $display("ifWb:[%d] write a %x d %x sel %x",current_cycle.data.size(), adr, dat_i, sel);
ack <= 1;
end else if(stb && !we && !stall) begin
// $error("Sorry, no pipelined read for slave yet implemented");
ack <= 0;
end else
ack <= 0;
endtask // pipelined_fsm
always@(posedge clk_i)
begin
if(!rst_n_i)
begin
c_queue = {};
current_cycle.data = {};
trans_index = 0;
ack <= 0;
rty <= 0;
err <= 0;
dat_o <= 0;
stall <= 0;
end else begin
if(settings.mode == PIPELINED)
pipelined_fsm();
end
end
initial begin
settings.mode = PIPELINED;
settings.gen_random_stalls = 1;
settings.stall_prob = 0.1;
settings.stall_min_duration = 1;
settings.stall_max_duration = 2;
end
endinterface // IWishboneSlave
`endif
\ No newline at end of file
`ifndef IF_WISHBONE_ACCESSOR_SV
`define IF_WISHBONE_ACCESSOR_SV
`include "if_wishbone_types.svh"
virtual class CWishboneAccessor extends CBusAccessor;
static int _null = 0;
protected wb_cycle_type_t m_cycle_type;
function new();
m_cycle_type = CLASSIC;
m_default_xfer_size = 4;
endfunction // new
virtual task set_mode(wb_cycle_type_t mode);
m_cycle_type = mode;
endtask // set_mode
// [slave only] checks if there are any transactions in the queue
virtual function automatic int poll();
return 0;
endfunction // poll
// ML stuff [slave only]
virtual function automatic int permanent_stall_enable();
$display("CWisboneAccessor: permanent_stall: ON");
endfunction;
// ML stuff [slave only]
virtual function automatic int permanent_stall_disable();
$display("CWisboneAccessor: permanent_stall: OFF");
endfunction;
// [slave only] adds a simulation event (e.g. a forced STALL, RETRY, ERROR)
// evt = event type (STALL, ERROR, RETRY)
// behv = event behavior: DELAYED - event occurs after a predefined delay (dly_start)
// RANDOM - event occurs randomly with probability (prob)
// These two can be combined (random events occuring after a certain initial delay)
// DELAYED events can be repeated (rep_rate parameter)
virtual task add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate);
endtask // add_event
// [slave only] gets a cycle from the queue
virtual task get(ref wb_cycle_t xfer);
endtask // get
// [master only] executes a cycle and returns its result
virtual task put(ref wb_cycle_t xfer);
endtask // put
virtual function int idle();
return 1;
endfunction // idle
// [master only] generic write(s), blocking
virtual task writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
cycle.ctype = m_cycle_type;
cycle.rw = 1'b1;
for(i=0;i < addr.size(); i++)
begin
wb_xfer_t xfer;
xfer.a = addr[i];
xfer.d = data[i];
xfer.size = size;
cycle.data.push_back(xfer);
end
// $display("DS: %d", cycle.data.size());
put(cycle);
get(cycle);
result = cycle.result;
endtask // write
// [master only] generic read(s), blocking
virtual task readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
cycle.ctype = m_cycle_type;
cycle.rw = 1'b0;
for(i=0;i < addr.size(); i++)
begin
wb_xfer_t xfer;
xfer.a = addr[i];
xfer.size = size;
cycle.data.push_back(xfer);
end
put(cycle);
get(cycle);
for(i=0;i < addr.size(); i++)
data[i] = cycle.data[i].d;
result = cycle.result;
endtask // readm
virtual task read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
aa[0] = addr;
readm(aa, da, size, result);
data = da[0];
endtask
virtual task write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
aa[0] = addr;
da[0] = data;
writem(aa, da, size, result);
endtask
endclass // CWishboneAccessor
static int seed = 0;
function automatic int probability_hit(real prob);
real rand_val;
rand_val = real'($dist_uniform(seed, 0, 1000)) / 1000.0;
if(rand_val < prob)
return 1;
else
return 0;
endfunction // probability_hit
`endif // `ifndef IF_WISHBONE_ACCESSOR_SV
//
// Title : Software Wishbone master unit for testbenches
//
// File : wishbone_master_tb.v
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : Verilog 2001
//
`ifndef __IF_WB_DEFS_SV
`define __IF_WB_DEFS_SV
`include "simdrv_defs.sv"
typedef enum
{
R_OK = 0,
R_ERROR,
R_RETRY
} wb_cycle_result_t;
typedef enum
{
CLASSIC = 0,
PIPELINED = 1
} wb_cycle_type_t;
typedef struct {
uint64_t a;
uint64_t d;
bit[7:0] sel;
int size;
} wb_xfer_t;
typedef struct {
int rw;
wb_cycle_type_t ctype;
wb_xfer_t data[$];
wb_cycle_result_t result;
} wb_cycle_t;
virtual class CWishboneAccessor;
virtual function automatic int poll();
return 0;
endfunction // poll
virtual task get(output wb_cycle_t xfer);
endtask // get
virtual task put(input wb_cycle_t xfer);
endtask // put
virtual function int idle();
return 0;
endfunction // idle
virtual task clear(); endtask
endclass // CWishboneAccessor
int seed = 0;
function automatic int probability_hit(real prob);
real rand_val;
rand_val = real'($dist_uniform(seed, 0, 1000)) / 1000.0;
if(rand_val < prob)
return 1;
else
return 0;
endfunction // probability_hit
`endif // `ifndef __IF_WB_DEFS_SV
//
// Title : Pipelined Wishbone BFM - type definitions
//
// File : if_wishbone_types.sv
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : Verilog 2001
//
`ifndef __IF_WB_TYPES_SVH
`define __IF_WB_TYPES_SVH
`include "simdrv_defs.svh"
typedef enum
{
R_OK = 0,
R_ERROR,
R_RETRY
} wb_cycle_result_t;
typedef enum
{
CLASSIC = 0,
PIPELINED = 1
} wb_cycle_type_t;
typedef enum {
WORD = 0,
BYTE = 1
} wb_address_granularity_t;
typedef struct {
uint64_t a;
uint64_t d;
int size;
bit [7:0] sel;
} wb_xfer_t;
typedef struct {
int rw;
wb_cycle_type_t ctype;
wb_xfer_t data[$];
wb_cycle_result_t result;
} wb_cycle_t;
typedef enum
{
RETRY = 0,
STALL,
ERROR
} wba_sim_event_t;
typedef enum
{
RANDOM = (1<<0),
DELAYED = (1<<1)
} wba_sim_behavior_t;
`endif // `ifndef __IF_WB_TYPES_SVH
`define ADDR_MINIC_MCR 7'h0
`define MINIC_MCR_TX_START_OFFSET 0
`define MINIC_MCR_TX_START 32'h00000001
`define MINIC_MCR_TX_IDLE_OFFSET 1
`define MINIC_MCR_TX_IDLE 32'h00000002
`define MINIC_MCR_TX_ERROR_OFFSET 2
`define MINIC_MCR_TX_ERROR 32'h00000004
`define MINIC_MCR_RX_READY_OFFSET 8
`define MINIC_MCR_RX_READY 32'h00000100
`define MINIC_MCR_RX_FULL_OFFSET 9
`define MINIC_MCR_RX_FULL 32'h00000200
`define MINIC_MCR_RX_EN_OFFSET 10
`define MINIC_MCR_RX_EN 32'h00000400
`define MINIC_MCR_TX_TS_READY_OFFSET 11
`define MINIC_MCR_TX_TS_READY 32'h00000800
`define MINIC_MCR_RX_CLASS_OFFSET 16
`define MINIC_MCR_RX_CLASS 32'h00ff0000
`define ADDR_MINIC_TX_ADDR 7'h4
`define ADDR_MINIC_RX_ADDR 7'h8
`define ADDR_MINIC_RX_SIZE 7'hc
`define ADDR_MINIC_RX_AVAIL 7'h10
`define ADDR_MINIC_TSR0 7'h14
`define MINIC_TSR0_VALID_OFFSET 0
`define MINIC_TSR0_VALID 32'h00000001
`define MINIC_TSR0_PID_OFFSET 1
`define MINIC_TSR0_PID 32'h0000003e
`define MINIC_TSR0_FID_OFFSET 6
`define MINIC_TSR0_FID 32'h003fffc0
`define ADDR_MINIC_TSR1 7'h18
`define MINIC_TSR1_TSVAL_OFFSET 0
`define MINIC_TSR1_TSVAL 32'hffffffff
`define ADDR_MINIC_DBGR 7'h1c
`define MINIC_DBGR_IRQ_CNT_OFFSET 0
`define MINIC_DBGR_IRQ_CNT 32'h00ffffff
`define MINIC_DBGR_WB_IRQ_VAL_OFFSET 24
`define MINIC_DBGR_WB_IRQ_VAL 32'h01000000
`define ADDR_MINIC_MPROT 7'h20
`define MINIC_MPROT_LO_OFFSET 0
`define MINIC_MPROT_LO 32'h0000ffff
`define MINIC_MPROT_HI_OFFSET 16
`define MINIC_MPROT_HI 32'hffff0000
`define ADDR_MINIC_EIC_IDR 7'h40
`define MINIC_EIC_IDR_TX_OFFSET 0
`define MINIC_EIC_IDR_TX 32'h00000001
`define MINIC_EIC_IDR_RX_OFFSET 1
`define MINIC_EIC_IDR_RX 32'h00000002
`define MINIC_EIC_IDR_TXTS_OFFSET 2
`define MINIC_EIC_IDR_TXTS 32'h00000004
`define ADDR_MINIC_EIC_IER 7'h44
`define MINIC_EIC_IER_TX_OFFSET 0
`define MINIC_EIC_IER_TX 32'h00000001
`define MINIC_EIC_IER_RX_OFFSET 1
`define MINIC_EIC_IER_RX 32'h00000002
`define MINIC_EIC_IER_TXTS_OFFSET 2
`define MINIC_EIC_IER_TXTS 32'h00000004
`define ADDR_MINIC_EIC_IMR 7'h48
`define MINIC_EIC_IMR_TX_OFFSET 0
`define MINIC_EIC_IMR_TX 32'h00000001
`define MINIC_EIC_IMR_RX_OFFSET 1
`define MINIC_EIC_IMR_RX 32'h00000002
`define MINIC_EIC_IMR_TXTS_OFFSET 2
`define MINIC_EIC_IMR_TXTS 32'h00000004
`define ADDR_MINIC_EIC_ISR 7'h4c
`define MINIC_EIC_ISR_TX_OFFSET 0
`define MINIC_EIC_ISR_TX 32'h00000001
`define MINIC_EIC_ISR_RX_OFFSET 1
`define MINIC_EIC_ISR_RX 32'h00000002
`define MINIC_EIC_ISR_TXTS_OFFSET 2
`define MINIC_EIC_ISR_TXTS 32'h00000004
`define OLD_ADDR_EP_ECR 8'h0
`define OLD_EP_ECR_PORTID_OFFSET 0
`define OLD_EP_ECR_PORTID 32'h0000001f
`define OLD_EP_ECR_RST_CNT_OFFSET 5
`define OLD_EP_ECR_RST_CNT 32'h00000020
`define OLD_EP_ECR_TX_EN_FRA_OFFSET 6
`define OLD_EP_ECR_TX_EN_FRA 32'h00000040
`define OLD_EP_ECR_RX_EN_FRA_OFFSET 7
`define OLD_EP_ECR_RX_EN_FRA 32'h00000080
`define OLD_ADDR_EP_TSCR 8'h4
`define OLD_EP_TSCR_EN_TXTS_OFFSET 0
`define OLD_EP_TSCR_EN_TXTS 32'h00000001
`define OLD_EP_TSCR_EN_RXTS_OFFSET 1
`define OLD_EP_TSCR_EN_RXTS 32'h00000002
`define OLD_EP_TSCR_CS_START_OFFSET 2
`define OLD_EP_TSCR_CS_START 32'h00000004
`define OLD_EP_TSCR_CS_DONE_OFFSET 3
`define OLD_EP_TSCR_CS_DONE 32'h00000008
`define OLD_ADDR_EP_RFCR 8'h8
`define OLD_EP_RFCR_A_RUNT_OFFSET 0
`define OLD_EP_RFCR_A_RUNT 32'h00000001
`define OLD_EP_RFCR_A_GIANT_OFFSET 1
`define OLD_EP_RFCR_A_GIANT 32'h00000002
`define OLD_EP_RFCR_A_HP_OFFSET 2
`define OLD_EP_RFCR_A_HP 32'h00000004
`define OLD_EP_RFCR_A_FRAG_OFFSET 3
`define OLD_EP_RFCR_A_FRAG 32'h00000008
`define OLD_EP_RFCR_QMODE_OFFSET 4
`define OLD_EP_RFCR_QMODE 32'h00000030
`define OLD_EP_RFCR_FIX_PRIO_OFFSET 6
`define OLD_EP_RFCR_FIX_PRIO 32'h00000040
`define OLD_EP_RFCR_PRIO_VAL_OFFSET 8
`define OLD_EP_RFCR_PRIO_VAL 32'h00000700
`define OLD_EP_RFCR_VID_VAL_OFFSET 16
`define OLD_EP_RFCR_VID_VAL 32'h0fff0000
`define OLD_ADDR_EP_FCR 8'hc
`define OLD_EP_FCR_RXPAUSE_OFFSET 0
`define OLD_EP_FCR_RXPAUSE 32'h00000001
`define OLD_EP_FCR_TXPAUSE_OFFSET 1
`define OLD_EP_FCR_TXPAUSE 32'h00000002
`define OLD_EP_FCR_TX_THR_OFFSET 8
`define OLD_EP_FCR_TX_THR 32'h0000ff00
`define OLD_EP_FCR_TX_QUANTA_OFFSET 16
`define OLD_EP_FCR_TX_QUANTA 32'hffff0000
`define OLD_ADDR_EP_MACH 8'h10
`define OLD_ADDR_EP_MACL 8'h14
`define OLD_ADDR_EP_DMCR 8'h18
`define OLD_EP_DMCR_EN_OFFSET 0
`define OLD_EP_DMCR_EN 32'h00000001
`define OLD_EP_DMCR_N_AVG_OFFSET 16
`define OLD_EP_DMCR_N_AVG 32'h0fff0000
`define OLD_ADDR_EP_DMSR 8'h1c
`define OLD_EP_DMSR_PS_VAL_OFFSET 0
`define OLD_EP_DMSR_PS_VAL 32'h00ffffff
`define OLD_EP_DMSR_PS_RDY_OFFSET 24
`define OLD_EP_DMSR_PS_RDY 32'h01000000
`define OLD_ADDR_EP_MDIO_CR 8'h20
`define OLD_EP_MDIO_CR_DATA_OFFSET 0
`define OLD_EP_MDIO_CR_DATA 32'h0000ffff
`define OLD_EP_MDIO_CR_ADDR_OFFSET 16
`define OLD_EP_MDIO_CR_ADDR 32'h00ff0000
`define OLD_EP_MDIO_CR_RW_OFFSET 31
`define OLD_EP_MDIO_CR_RW 32'h80000000
`define OLD_ADDR_EP_MDIO_SR 8'h24
`define OLD_EP_MDIO_SR_RDATA_OFFSET 0
`define OLD_EP_MDIO_SR_RDATA 32'h0000ffff
`define OLD_EP_MDIO_SR_READY_OFFSET 31
`define OLD_EP_MDIO_SR_READY 32'h80000000
`define OLD_ADDR_EP_IDCODE 8'h28
`define OLD_ADDR_EP_DSR 8'h2c
`define OLD_EP_DSR_LSTATUS_OFFSET 0
`define OLD_EP_DSR_LSTATUS 32'h00000001
`define OLD_EP_DSR_LACT_OFFSET 1
`define OLD_EP_DSR_LACT 32'h00000002
`define OLD_ADDR_EP_AFCR 8'h30
`define OLD_EP_AFCR_ENABLE_OFFSET 0
`define OLD_EP_AFCR_ENABLE 32'h00000001
`define OLD_EP_AFCR_RULE_SEL_OFFSET 1
`define OLD_EP_AFCR_RULE_SEL 32'h0000000e
`define OLD_EP_AFCR_MATRIX_ADDR_OFFSET 4
`define OLD_EP_AFCR_MATRIX_ADDR 32'h00000ff0
`define OLD_EP_AFCR_MATRIX_DATA_OFFSET 12
`define OLD_EP_AFCR_MATRIX_DATA 32'h000ff000
`define OLD_EP_AFCR_MATRIX_WRITE_P_OFFSET 20
`define OLD_EP_AFCR_MATRIX_WRITE_P 32'h00100000
`define OLD_ADDR_EP_AFR0 8'h34
`define OLD_EP_AFR0_DMAC_EN_OFFSET 0
`define OLD_EP_AFR0_DMAC_EN 32'h00000001
`define OLD_EP_AFR0_VID_EN_OFFSET 1
`define OLD_EP_AFR0_VID_EN 32'h00000002
`define OLD_EP_AFR0_ETYPE_EN_OFFSET 2
`define OLD_EP_AFR0_ETYPE_EN 32'h00000004
`define OLD_EP_AFR0_VID_OFFSET 3
`define OLD_EP_AFR0_VID 32'h00007ff8
`define OLD_ADDR_EP_AFR1 8'h38
`define OLD_EP_AFR1_DMAC_LO_OFFSET 0
`define OLD_EP_AFR1_DMAC_LO 32'hffffffff
`define OLD_ADDR_EP_AFR2 8'h3c
`define OLD_EP_AFR2_DMAC_HI_OFFSET 0
`define OLD_EP_AFR2_DMAC_HI 32'h0000ffff
`define OLD_EP_AFR2_ETYPE_OFFSET 16
`define OLD_EP_AFR2_ETYPE 32'hffff0000
`define OLD_BASE_EP_RMON_RAM 8'h80
`define OLD_SIZE_EP_RMON_RAM 32'h20
/* Packet Filter microcode definitions */
class PFilterMicrocode;
typedef enum
{
AND = 0,
NAND = 4,
OR = 1,
NOR = 5,
XOR = 2,
XNOR = 6,
MOV = 3,
NOT = 7
} pfilter_op_t;
const uint64_t PF_MODE_LOGIC = (1<<34);
const uint64_t PF_MODE_CMP = 0;
const int max_size = 64;
protected int code_pos;
protected uint64_t code_buf[];
function new();
code_pos = 0;
code_buf = new[max_size];
endfunction // new
task check_size();
if(code_pos == max_size - 1)
$error("microcode: code too big (max size: %d)", max_size);
endtask // check_size
task check_reg_range(int val, int minval, int maxval, string name);
if(val < minval || val > maxval)
$error("microcode: %s register out of range (%d to %d)", name, minval,maxval);
endtask // check_reg_range
// rd = (packet[offset] & mask == value) op rd
task cmp(int offset, int value, int mask, pfilter_op_t op, int rd);
uint64_t ir;
check_size();
if(offset > code_pos-1)
$error("microcode: comparison offset is bigger than current PC. Insert some nops before comparing");
check_reg_range(rd, 1, 15, "ra/rd");
ir = (PF_MODE_CMP | (offset << 7)
| ((mask & 'h1) ? (1<<29) : 0)
| ((mask & 'h10) ? (1<<30) : 0)
| ((mask & 'h100) ? (1<<31) : 0)
| ((mask & 'h1000) ? (1<<32) : 0))
| op | (rd << 3);
ir = ir | (value & 'hffff) << 13;
code_buf[code_pos++] = ir;
endtask // cmp
// rd = (packet[offset] & (1<<bit_index)) op rd
task btst(int offset, int bit_index, pfilter_op_t op, int rd);
uint64_t ir;
check_size();
if(offset > code_pos-1)
$error("microcode: comparison offset is bigger than current PC. Insert some nops before comparing");
check_reg_range(rd, 1, 15, "ra/rd");
check_reg_range(bit_index, 0, 15, "bit index");
ir = ((1<<33) | PF_MODE_CMP | (offset << 7) | (bit_index << 29) | op | (rd << 3));
code_buf[code_pos++] = ir;
endtask // cmp
task nop();
uint64_t ir;
check_size();
ir = PF_MODE_LOGIC;
code_buf[code_pos++] = ir;
endtask // nop
// rd = ra op rb
task logic2(int rd, int ra, pfilter_op_t op, int rb);
uint64_t ir;
check_size();
check_reg_range(ra, 0, 31, "ra");
check_reg_range(rb, 0, 31, "rb");
check_reg_range(rd, 1, 31, "rd");
ir = (ra << 8) | (rb << 13) | ((rd & 'hf) << 3) | ((rd & 'h10) ? (1<<7) : 0) | op;
ir = ir | PF_MODE_LOGIC | (3<<23);
code_buf[code_pos++] = ir;
endtask // logic2
// rd = (ra op rb) op2 rc
task logic3(int rd, int ra, pfilter_op_t op, int rb, pfilter_op_t op2, int rc);
uint64_t ir;
check_size();
check_reg_range(ra, 0, 31, "ra");
check_reg_range(rb, 0, 31, "rb");
check_reg_range(rc, 0, 31, "rb");
check_reg_range(rd, 1, 31, "rd");
ir = (ra << 8) | (rb << 13) | (rc << 18) | ((rd & 'hf) << 3) | ((rd & 'h10) ? (1<<7) : 0) | op;
ir = ir | PF_MODE_LOGIC | (op2<<23);
code_buf[code_pos++] = ir;
endtask // logic3
typedef uint64_t u64_array[];
function u64_array assemble();
u64_array tmp;
// code_buf[code_pos++] = (1<<35); // insert FIN instruction
// tmp = new [code_pos](code_buf);
code_buf[code_pos] = (1<<35); // insert FIN instruction
tmp = new [code_pos+1](code_buf);
return tmp;
endfunction // assemble
endclass // PFilterMicrocode
`define ADDR_PPSG_CR 5'h0
`define PPSG_CR_CNT_RST_OFFSET 0
`define PPSG_CR_CNT_RST 32'h00000001
`define PPSG_CR_CNT_EN_OFFSET 1
`define PPSG_CR_CNT_EN 32'h00000002
`define PPSG_CR_CNT_ADJ_OFFSET 2
`define PPSG_CR_CNT_ADJ 32'h00000004
`define PPSG_CR_CNT_SET_OFFSET 3
`define PPSG_CR_CNT_SET 32'h00000008
`define PPSG_CR_PWIDTH_OFFSET 4
`define PPSG_CR_PWIDTH 32'hfffffff0
`define ADDR_PPSG_CNTR_NSEC 5'h4
`define ADDR_PPSG_CNTR_UTCLO 5'h8
`define ADDR_PPSG_CNTR_UTCHI 5'hc
`define ADDR_PPSG_ADJ_NSEC 5'h10
`define ADDR_PPSG_ADJ_UTCLO 5'h14
`define ADDR_PPSG_ADJ_UTCHI 5'h18
`define ADDR_PPSG_ESCR 5'h1c
`define PPSG_ESCR_SYNC_OFFSET 0
`define PPSG_ESCR_SYNC 32'h00000001
`define PPSG_ESCR_PPS_VALID_OFFSET 1
`define PPSG_ESCR_PPS_VALID 32'h00000002
`define PPSG_ESCR_TM_VALID_OFFSET 2
`define PPSG_ESCR_TM_VALID 32'h00000004
`define PPSG_ESCR_SEC_SET_OFFSET 3
`define PPSG_ESCR_SEC_SET 32'h00000008
`define PPSG_ESCR_NSEC_SET_OFFSET 4
`define PPSG_ESCR_NSEC_SET 32'h00000010
`define ADDR_SI570_RFREQL 4'h0
`define ADDR_SI570_RFREQH 4'h4
`define ADDR_SI570_GPSR 4'h8
`define SI570_GPSR_SCL_OFFSET 0
`define SI570_GPSR_SCL 32'h00000001
`define SI570_GPSR_SDA_OFFSET 1
`define SI570_GPSR_SDA 32'h00000002
`define ADDR_SI570_GPCR 4'hc
`define SI570_GPCR_SCL_OFFSET 0
`define SI570_GPCR_SCL 32'h00000001
`define SI570_GPCR_SDA_OFFSET 1
`define SI570_GPCR_SDA 32'h00000002
`ifndef SIMDRV_DEFS_SV
`define SIMDRV_DEFS_SV 1
typedef longint unsigned uint64_t;
typedef int unsigned uint32_t;
typedef shortint unsigned uint16_t;
typedef uint64_t u64_array_t[];
typedef byte byte_array_t[];
virtual class CBusAccessor;
static int _null = 0;
int m_default_xfer_size;
task set_default_xfer_size(int default_size);
m_default_xfer_size = default_size;
endtask // set_default_xfer_size
pure virtual task writem(uint64_t addr[], uint64_t data[], input int size, ref int result);
pure virtual task readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result);
virtual task read(uint64_t addr, ref uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
int res;
uint64_t aa[1], da[];
da= new[1];
aa[0] = addr;
readm(aa, da, size, res);
data = da[0];
endtask
virtual task write(uint64_t addr, uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
uint64_t aa[1], da[1];
aa[0] = addr;
da[0] = data;
writem(aa, da, size, result);
endtask
endclass // CBusAccessor
class CSimUtils;
static function automatic u64_array_t pack(byte x[], int size, int big_endian = 1);
u64_array_t tmp;
int i, j;
int nwords, nbytes;
nwords = (x.size() + size - 1) / size;
tmp = new [nwords];
for(i=0;i<nwords;i++)
begin
uint64_t d;
d =0;
nbytes = (x.size() - i * nbytes > size ? size : x.size() - i*nbytes);
for(j=0;j<nbytes;j++)
begin
if(big_endian)
d = d | ((x[i*size+j] << (8*(size-1-j))));
else
d = d | ((x[i*size+j] << (8*j)));
end
tmp[i] = d;
end
return tmp;
endfunction // pack
static function automatic byte_array_t unpack(u64_array_t x, int entry_size, int size, int big_endian = 1);
byte_array_t tmp;
int i, n;
tmp = new[size];
n = 0;
i = 0;
while(n < size)
begin
tmp[n] = x[i] >> (8*(entry_size-1 - (n % entry_size)));
n++;
if(n % entry_size == 0)
i++;
end
return tmp;
endfunction // unpack
endclass // CSimUtils
static CSimUtils SimUtils;
`endif
\ No newline at end of file
`define ADDR_SPLL_CSR 6'h0
`define SPLL_CSR_N_REF_OFFSET 0
`define SPLL_CSR_N_REF 32'h0000003f
`define SPLL_CSR_N_OUT_OFFSET 8
`define SPLL_CSR_N_OUT 32'h00000700
`define ADDR_SPLL_OCCR 6'h4
`define SPLL_OCCR_OUT_EN_OFFSET 0
`define SPLL_OCCR_OUT_EN 32'h000000ff
`define SPLL_OCCR_AUX_LOCK_OFFSET 8
`define SPLL_OCCR_AUX_LOCK 32'h0000ff00
`define ADDR_SPLL_RCER 6'h8
`define ADDR_SPLL_PER_HPLL 6'hc
`define ADDR_SPLL_DAC_HPLL 6'h10
`define ADDR_SPLL_DAC_MAIN 6'h14
`define SPLL_DAC_MAIN_VALUE_OFFSET 0
`define SPLL_DAC_MAIN_VALUE 32'h0000ffff
`define SPLL_DAC_MAIN_DAC_SEL_OFFSET 16
`define SPLL_DAC_MAIN_DAC_SEL 32'h000f0000
`define ADDR_SPLL_DEGLITCH_THR 6'h18
`define ADDR_SPLL_EIC_IDR 6'h20
`define SPLL_EIC_IDR_TAG_OFFSET 0
`define SPLL_EIC_IDR_TAG 32'h00000001
`define ADDR_SPLL_EIC_IER 6'h24
`define SPLL_EIC_IER_TAG_OFFSET 0
`define SPLL_EIC_IER_TAG 32'h00000001
`define ADDR_SPLL_EIC_IMR 6'h28
`define SPLL_EIC_IMR_TAG_OFFSET 0
`define SPLL_EIC_IMR_TAG 32'h00000001
`define ADDR_SPLL_EIC_ISR 6'h2c
`define SPLL_EIC_ISR_TAG_OFFSET 0
`define SPLL_EIC_ISR_TAG 32'h00000001
`define ADDR_SPLL_TRR_R0 6'h30
`define SPLL_TRR_R0_VALUE_OFFSET 0
`define SPLL_TRR_R0_VALUE 32'h00ffffff
`define SPLL_TRR_R0_CHAN_ID_OFFSET 24
`define SPLL_TRR_R0_CHAN_ID 32'h7f000000
`define SPLL_TRR_R0_DISC_OFFSET 31
`define SPLL_TRR_R0_DISC 32'h80000000
`define ADDR_SPLL_TRR_CSR 6'h34
`define SPLL_TRR_CSR_EMPTY_OFFSET 17
`define SPLL_TRR_CSR_EMPTY 32'h00020000
`define ADDR_SPLL_CSR 8'h0
`define SPLL_CSR_UNUSED0_OFFSET 8
`define SPLL_CSR_UNUSED0 32'h00003f00
`define SPLL_CSR_N_REF_OFFSET 16
`define SPLL_CSR_N_REF 32'h003f0000
`define SPLL_CSR_N_OUT_OFFSET 24
`define SPLL_CSR_N_OUT 32'h07000000
`define SPLL_CSR_DBG_SUPPORTED_OFFSET 27
`define SPLL_CSR_DBG_SUPPORTED 32'h08000000
`define ADDR_SPLL_ECCR 8'h4
`define SPLL_ECCR_EXT_EN_OFFSET 0
`define SPLL_ECCR_EXT_EN 32'h00000001
`define SPLL_ECCR_EXT_SUPPORTED_OFFSET 1
`define SPLL_ECCR_EXT_SUPPORTED 32'h00000002
`define SPLL_ECCR_EXT_REF_PRESENT_OFFSET 2
`define SPLL_ECCR_EXT_REF_PRESENT 32'h00000004
`define ADDR_SPLL_AL_CR 8'h8
`define SPLL_AL_CR_VALID_OFFSET 0
`define SPLL_AL_CR_VALID 32'h000001ff
`define SPLL_AL_CR_REQUIRED_OFFSET 9
`define SPLL_AL_CR_REQUIRED 32'h0003fe00
`define ADDR_SPLL_AL_CREF 8'hc
`define ADDR_SPLL_AL_CIN 8'h10
`define ADDR_SPLL_F_DMTD 8'h14
`define SPLL_F_DMTD_FREQ_OFFSET 0
`define SPLL_F_DMTD_FREQ 32'h0fffffff
`define SPLL_F_DMTD_VALID_OFFSET 28
`define SPLL_F_DMTD_VALID 32'h10000000
`define ADDR_SPLL_F_REF 8'h18
`define SPLL_F_REF_FREQ_OFFSET 0
`define SPLL_F_REF_FREQ 32'h0fffffff
`define SPLL_F_REF_VALID_OFFSET 28
`define SPLL_F_REF_VALID 32'h10000000
`define ADDR_SPLL_F_EXT 8'h1c
`define SPLL_F_EXT_FREQ_OFFSET 0
`define SPLL_F_EXT_FREQ 32'h0fffffff
`define SPLL_F_EXT_VALID_OFFSET 28
`define SPLL_F_EXT_VALID 32'h10000000
`define ADDR_SPLL_OCCR 8'h20
`define SPLL_OCCR_OUT_EN_OFFSET 8
`define SPLL_OCCR_OUT_EN 32'h0000ff00
`define SPLL_OCCR_OUT_LOCK_OFFSET 16
`define SPLL_OCCR_OUT_LOCK 32'h00ff0000
`define ADDR_SPLL_RCER 8'h24
`define ADDR_SPLL_OCER 8'h28
`define ADDR_SPLL_DAC_HPLL 8'h40
`define ADDR_SPLL_DAC_MAIN 8'h44
`define SPLL_DAC_MAIN_VALUE_OFFSET 0
`define SPLL_DAC_MAIN_VALUE 32'h0000ffff
`define SPLL_DAC_MAIN_DAC_SEL_OFFSET 16
`define SPLL_DAC_MAIN_DAC_SEL 32'h000f0000
`define ADDR_SPLL_DEGLITCH_THR 8'h48
`define ADDR_SPLL_DFR_SPLL 8'h4c
`define SPLL_DFR_SPLL_VALUE_OFFSET 0
`define SPLL_DFR_SPLL_VALUE 32'h7fffffff
`define SPLL_DFR_SPLL_EOS_OFFSET 31
`define SPLL_DFR_SPLL_EOS 32'h80000000
`define ADDR_SPLL_EIC_IDR 8'h60
`define SPLL_EIC_IDR_TAG_OFFSET 0
`define SPLL_EIC_IDR_TAG 32'h00000001
`define ADDR_SPLL_EIC_IER 8'h64
`define SPLL_EIC_IER_TAG_OFFSET 0
`define SPLL_EIC_IER_TAG 32'h00000001
`define ADDR_SPLL_EIC_IMR 8'h68
`define SPLL_EIC_IMR_TAG_OFFSET 0
`define SPLL_EIC_IMR_TAG 32'h00000001
`define ADDR_SPLL_EIC_ISR 8'h6c
`define SPLL_EIC_ISR_TAG_OFFSET 0
`define SPLL_EIC_ISR_TAG 32'h00000001
`define ADDR_SPLL_DFR_HOST_R0 8'h70
`define SPLL_DFR_HOST_R0_VALUE_OFFSET 0
`define SPLL_DFR_HOST_R0_VALUE 32'hffffffff
`define ADDR_SPLL_DFR_HOST_R1 8'h74
`define SPLL_DFR_HOST_R1_SEQ_ID_OFFSET 0
`define SPLL_DFR_HOST_R1_SEQ_ID 32'h0000ffff
`define ADDR_SPLL_DFR_HOST_CSR 8'h78
`define SPLL_DFR_HOST_CSR_FULL_OFFSET 16
`define SPLL_DFR_HOST_CSR_FULL 32'h00010000
`define SPLL_DFR_HOST_CSR_EMPTY_OFFSET 17
`define SPLL_DFR_HOST_CSR_EMPTY 32'h00020000
`define SPLL_DFR_HOST_CSR_USEDW_OFFSET 0
`define SPLL_DFR_HOST_CSR_USEDW 32'h00001fff
`define ADDR_SPLL_TRR_R0 8'h7c
`define SPLL_TRR_R0_VALUE_OFFSET 0
`define SPLL_TRR_R0_VALUE 32'h00ffffff
`define SPLL_TRR_R0_CHAN_ID_OFFSET 24
`define SPLL_TRR_R0_CHAN_ID 32'h7f000000
`define SPLL_TRR_R0_DISC_OFFSET 31
`define SPLL_TRR_R0_DISC 32'h80000000
`define ADDR_SPLL_TRR_CSR 8'h80
`define SPLL_TRR_CSR_EMPTY_OFFSET 17
`define SPLL_TRR_CSR_EMPTY 32'h00020000
`timescale 1ps/1ps
// Clock/reset generator module for the TBI interface.
module tbi_clock_rst_gen
(
output clk_ref_o,
output clk_sys_o,
output phy_rbclk_o,
output rst_n_o);
parameter g_rbclk_period = 8010;
parameter g_refclk_period = 8000;
parameter g_sysclk_period = 15900;
reg refclk = 0, refclk2 = 0, rbclk = 0, rst_n = 0;
always #(g_rbclk_period/2) rbclk <= ~rbclk;
always #(g_refclk_period/2) refclk <= ~refclk;
always #(g_sysclk_period/2) refclk2 <= ~refclk2;
// always@(posedge refclk) refclk2 <= ~refclk2;
initial begin repeat(10) @(posedge refclk2); rst_n = 1; end
assign clk_ref_o = refclk;
assign clk_sys_o = refclk2;
assign phy_rbclk_o = rbclk;
assign rst_n_o = rst_n;
endmodule // tbi_clock_gen
`timescale 1ns/1ps
// Clock alignment FIFO for looping back the endpoint TX/RX path
module tbi_loopback_fifo
(
input tx_clk_i,
input rx_clk_i,
input [9:0] tx_data_i,
output reg [9:0] rx_data_o
);
parameter g_buf_size = 20000;
parameter g_error_prob = 0;
function automatic int probability_hit(int prob, int max_prob);
int rand_val;
rand_val = $random % (max_prob+1);
if(rand_val < 0) rand_val = -rand_val;
if(rand_val < prob)
return 1;
else
return 0;
endfunction // probability_hit
reg[9:0] buffer[100000];
int write_ptr, read_ptr, count;
initial begin
write_ptr = 0;
read_ptr = 0;
count = 0;
end
always@(posedge tx_clk_i) begin
buffer[write_ptr] <= tx_data_i;
count++;
write_ptr++;
end
always@(posedge rx_clk_i) begin
if(count == 0) begin
$display("loopback FIFO underrun!");
rx_data_o <= 0;
end else begin
if(probability_hit(g_error_prob, 1000))
rx_data_o <= 'hfff;
else
rx_data_o <= buffer[read_ptr];
read_ptr++;
count--;
end
end
endmodule
# vsim -do {run;quit} -c work.main
# ** Note: (vsim-3813) Design is being optimized due to module recompilation...
# // ModelSim SE 6.5e Feb 26 2010 Linux 2.6.38-ARCH
# //
# // Copyright 1991-2010 Mentor Graphics Corporation
# // All Rights Reserved.
# //
# // THIS WORK CONTAINS TRADE SECRET AND
# // PROPRIETARY INFORMATION WHICH IS THE PROPERTY
# // OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS
# // AND IS SUBJECT TO LICENSE TERMS.
# //
# Loading sv_std.std
# Loading work.test_epacket_sv_unit(fast)
# Loading work.main(fast)
# run
# 802.1q [VID 555/PCP 0] DST [ff:ff:ff:ff:ff:ff] SRC: [01:02:03:04:05:06] Type = 0x1234 size = 118 F:( )
# +000: 00 01 02 03 04 05 06 07-08 09 0a 0b 0c 0d 0e 0f
# +010: 10 11 12 13 14 15 16 17-18 19 1a 1b 1c 1d 1e 1f
# +020: 20 21 22 23 24 25 26 27-28 29 2a 2b 2c 2d 2e 2f
# +030: 30 31 32 33 34 35 36 37-38 39 3a 3b 3c 3d 3e 3f
# +040: 40 41 42 43 44 45 46 47-48 49 4a 4b 4c 4d 4e 4f
# +050: 50 51 52 53 54 55 56 57-58 59 5a 5b 5c 5d 5e 5f
# +060: 60 61 62 63
# eq: 1
# RandomBVEC 72
# 802.1q [VID 555/PCP 0] DST [ff:ff:ff:ff:ff:ff] SRC: [01:02:03:04:05:06] Type = 0x9215 size = 90 F:( )
# +000: 04 32 87 c7 32 09 81 87-bb 9f f7 c6 fd 63 63 55
# +010: f3 3c 09 c8 fa 67 74 63-af 5e 16 32 32 85 40 90
# +020: d6 4f 4b 09 06 29 b6 6b-01 57 8f 68 92 85 65 1e
# +030: fa c5 a1 6c bc 44 f6 db-e4 d7 5e 95 05 38 c3 a8
# +040: 1d 9d 3f 8b f9 ed b1 a6
# RandomBVEC 89
# 802.1q [VID 555/PCP 0] DST [ff:ff:ff:ff:ff:ff] SRC: [01:02:03:04:05:06] Type = 0xcfa2 size = 107 F:( )
# +000: fd 5c 50 2e 2d c5 24 68-6c 28 cb 86 61 e5 3b 9f
# +010: 89 3f b7 9d 90 6a c3 3c-ae a5 20 95 ac 43 47 4e
# +020: fe 13 ba 51 17 5a 30 a2-fc 66 73 ad 95 76 6d 32
# +030: 5a 70 bd a2 68 95 d6 87-ef 4d 7f 62 ab a8 34 05
# +040: dc 1c bd 5c cb ca 02 2c-ee 27 ed 36 3b e6 db cb
# +050: 23 82 fc b5 5a c4 95 16-64
# ** Note: $finish : test_epacket.sv(53)
# Time: 0 ns Iteration: 0 Instance: /main
`ifndef __WB_FABRIC_DEFS_SVH
`define __WB_FABRIC_DEFS_SVH
const bit [2:0] WRF_STATUS = 3'b100;
const bit [2:0] WRF_DATA = 3'b000;
const bit [2:0] WRF_OOB = 3'b010;
const bit [2:0] WRF_USER = 3'b110;
const bit [3:0] WRF_OOB_TX_FID = 4'b0001;
const bit [3:0] WRF_OOB_RX_TIMESTAMP = 4'b0000;
`endif // `ifndef __WB_FABRIC_DEFS_SVH
`ifndef __WB_PACKET_SINK_SVH
`define __WB_PACKET_SINK_SVH
`include "simdrv_defs.svh"
`include "eth_packet.svh"
`include "if_wishbone_accessor.svh"
`include "wb_fabric_defs.svh"
class WBPacketSink extends EthPacketSink;
protected CWishboneAccessor m_acc;
function new(CWishboneAccessor acc);
m_acc = acc;
endfunction // new
function int poll();
return m_acc.poll();
endfunction // poll
function int permanent_stall_enable();
return m_acc.permanent_stall_enable();
endfunction
function int permanent_stall_disable();
return m_acc.permanent_stall_disable();
endfunction
protected task decode_status(uint64_t stat, ref EthPacket pkt);
if(stat & 'h2)
pkt.error = 1'b1;
else begin
pkt.has_smac = (stat & 'h4 ? 1'b1 : 1'b0);
pkt.has_crc = (stat & 'h8 ? 1'b1 : 1'b0);
pkt.pclass = (stat>>8) & 'hff;
end
endtask // decode_status
protected task decode_oob(uint64_t oob, int size, ref EthPacket pkt);
if(!size)
return;
else if(size == 2 && (oob >> 28) == WRF_OOB_TX_FID)
begin
// $display("GotTxOOB");
pkt.oob_type = TX_FID;
pkt.ts.frame_id = oob & 'hffff;
end
else if (size == 3 && (oob >> 46) == WRF_OOB_RX_TIMESTAMP)
begin
// $display("GotRXOOB");
end else begin
$error("Invalid OOB!");
$stop;
end
endtask // decode_oob
task recv(ref EthPacket pkt, ref int result = _null);
uint64_t oob = 0;
byte tmp[];
wb_cycle_t cyc;
int i, size = 0, n = 0, n_oob = 0;
int oob_size = 0;
pkt = new;
m_acc.get(cyc);
for(i=0;i<cyc.data.size(); i++)
if (cyc.data[i].a == WRF_DATA)
size = size + cyc.data[i].size;
tmp = new[size];
// $display("CDS %d size: %d\n", cyc.data.size(), size);
pkt.size = size;
for(i=0;i<cyc.data.size(); i++)
begin
wb_xfer_t xf = cyc.data[i];
case(xf.a)
WRF_STATUS:
begin
decode_status(xf.d, pkt);
if(pkt.error)
break;
end
WRF_DATA:
begin
if(xf.size == 1)
tmp[n++] = (xf.d & 'hff);
else if(xf.size == 2)begin
tmp[n++] = ((xf.d >> 8) & 'hff);
tmp[n++] = (xf.d & 'hff);
end
end
WRF_OOB:
begin
oob = (oob << 16) | xf.d;
oob_size ++;
end
endcase // case (xf.a)
end
pkt.deserialize(tmp);
if(pkt.error == 1'b0)
decode_oob(oob, oob_size, pkt);
endtask // recv
endclass // WBPacketSink
`endif
`ifndef __WB_PACKET_SOURCE_SVH
`define __WB_PACKET_SOURCE_SVH
`include "simdrv_defs.svh"
`include "eth_packet.svh"
`include "if_wishbone_accessor.svh"
`include "wb_fabric_defs.svh"
class WBPacketSource extends EthPacketSource;
protected CWishboneAccessor m_acc;
function new(CWishboneAccessor acc);
m_acc = acc;
endfunction // new
function bit[15:0] pack_status(ref EthPacket pkt, input bit error = 0);
bit [15:0] st;
st[0] = (pkt.is_hp ? 1'b1: 1'b0);
st[1] = 1'b0;
st[2] = (pkt.has_smac ? 1'b1: 1'b0);
st[3] = error;
st[15:8] = pkt.pclass; // FIXME: add packet classes
st[7:4]= 0;
return st;
endfunction // pack_status
task unpack_status(bit[15:0] status, ref EthPacket pkt);
endtask // unpack_status
typedef bit[15:0] oob_array16[];
function u64_array_t pack_oob(ref EthPacket pkt);
u64_array_t oob;
case(pkt.oob_type)
TX_FID: begin
oob = new[2];
oob[0] = {WRF_OOB_TX_FID, 12'b0};
oob[1] = pkt.ts.frame_id;
end
endcase // case (pkt.oob_type)
return oob;
endfunction // pack_oob
task send(ref EthPacket pkt, ref int result = _null);
byte pdata[]; // FIXME: dynamic allocation would be better...
u64_array_t pdata_p;
u64_array_t oob_p;
int i, len;
wb_cycle_t cyc;
wb_xfer_t xf;
cyc.ctype = PIPELINED;
cyc.rw = 1;
/* First, the status register */
xf.a = WRF_STATUS;
xf.d = pack_status(pkt);
xf.size = 2;
cyc.data.push_back(xf);
pkt.serialize(pdata);
pdata_p = SimUtils.pack(pdata, 2, 1);
len = pdata_p.size();
for(i=0; i < len; i++)
begin
xf.a = WRF_DATA;
if(i==len-1 && (pdata.size()&1))
begin
xf.size = 1;
xf.d = pdata_p[i] >> 8;
end else begin
xf.size = 2;
xf.d = pdata_p[i];
end
cyc.data.push_back(xf);
end
if(pkt.error)
begin
xf.a = WRF_STATUS;
xf.d = pack_status(pkt, 1);
xf.size = 2;
cyc.data.push_back(xf);
end else begin
// $display("WBPacketSource::send(): DataSize: %d\n", cyc.data.size());
oob_p = pack_oob(pkt);
for (i=0;i<oob_p.size(); i++)
begin
xf.a = WRF_OOB;
xf.d = oob_p[i] & 'hffff;
xf.size = 2;
cyc.data.push_back(xf);
end
end // else: !if(pkt.error)
m_acc.put(cyc);
m_acc.get(cyc);
result = cyc.result;
endtask // send
endclass // WBPacketSource
`endif
//
// Title : Software Wishbone master unit for testbenches
//
// File : wishbone_master_tb.v
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : Verilog 2001
//
// Default values of certain WB parameters.
`timescale 1ns/1ps
// Bus clock period
`ifndef WB_CLOCK_PERIOD
`define WB_CLOCK_PERIOD 16
`define WB_RESET_DELAY (3*`WB_CLOCK_PERIOD)
`endif
// Widths of wishbone address/data/byte select
`ifndef WB_DATA_BUS_WIDTH
`define WB_DATA_BUS_WIDTH 32
`endif
`ifndef WB_ADDRESS_BUS_WIDTH
`define WB_ADDRESS_BUS_WIDTH 32
`endif
`define WB_BWSEL_WIDTH ((`WB_DATA_BUS_WIDTH + 7) / 8)
module WB_TEST_MASTER (
`ifdef WB_USE_EXTERNAL_CLOCK
input clk_i,
input rst_n_i
`endif
);
// these signals make the WB bus, which can be accessed from outside the module
reg [`WB_ADDRESS_BUS_WIDTH - 1 : 0] wb_addr = 0;
reg [`WB_DATA_BUS_WIDTH - 1 : 0] wb_data_o = 0;
reg [`WB_BWSEL_WIDTH - 1 : 0] wb_bwsel = 0;
wire [`WB_DATA_BUS_WIDTH -1 : 0] wb_data_i;
wire wb_ack;
reg wb_cyc = 0;
reg wb_stb = 0;
reg wb_we = 0;
reg rst_reg = 0;
reg clk_reg = 1;
wire wb_clk, wb_rst;
reg wb_tb_verbose = 1;
reg wb_monitor_bus = 1;
time last_access_t = 0;
reg [`WB_DATA_BUS_WIDTH -1 : 0] dummy;
// ready signal. 1 indicates that WB_TEST unit is initialized and ready for commands
reg ready = 0;
`ifndef WB_USE_EXTERNAL_CLOCK
// generate the WB bus clock
always #(`WB_CLOCK_PERIOD/2) clk_reg <= ~clk_reg;
// generate the reset and ready signals
initial begin
#(`WB_RESET_DELAY) rst_reg <= 1;
#(`WB_CLOCK_PERIOD*2) ready <= 1;
end
assign wb_clk = clk_reg;
assign wb_rst = rst_reg;
`else // !`ifdef WB_USE_OWN_CLOCK
assign wb_clk = clk_i;
assign wb_rst = rst_n_i;
initial begin repeat(3) @(posedge wb_clk); ready = 1; end
`endif // !`ifdef WB_USE_OWN_CLOCK
// enables/disables displaying information about each read/write operation.
task verbose;
input onoff;
begin
wb_tb_verbose = onoff;
end
endtask // wb_verbose
task monitor_bus;
input onoff;
begin
wb_monitor_bus = onoff;
end
endtask // monitor_bus
task rw_generic;
input [`WB_ADDRESS_BUS_WIDTH - 1 : 0] addr;
input [`WB_DATA_BUS_WIDTH - 1 : 0] data_i;
output [`WB_DATA_BUS_WIDTH - 1 : 0] data_o;
input rw;
input [3:0] size;
begin : rw_generic_main
if(wb_tb_verbose && rw)
$display("WB write %s: addr %x, data %x",
(size==1?"byte":((size==2)?"short":"int")),
addr, data_i);
if($time != last_access_t) begin
@(posedge wb_clk);
end
wb_stb<=1;
wb_cyc<=1;
wb_addr <= {2'b00, addr[31:2]};
wb_we <= rw;
if(rw) begin
case(size)
4: begin wb_data_o<=data_i; wb_bwsel <= 4'b1111; end
2: begin
if(addr[1]) begin
wb_data_o[31:16] <= data_i[15:0];
wb_bwsel <= 4'b1100;
end else begin
wb_data_o[15:0] <= data_i[15:0];
wb_bwsel <= 4'b0011;
end
end
1: begin
case(addr[1:0])
0: begin wb_data_o[31:24] <= data_i[7:0]; wb_bwsel <= 4'b1000; end
1: begin wb_data_o[23:16] <= data_i[7:0]; wb_bwsel <= 4'b0100; end
2: begin wb_data_o[15:8] <= data_i[7:0]; wb_bwsel <= 4'b0010; end
3: begin wb_data_o[7:0] <= data_i[7:0]; wb_bwsel <= 4'b0001; end
endcase // case(addr[1:0])
end
endcase // case(size)
end // if (rw)
@(posedge wb_clk);
if(wb_ack == 0) begin
while(wb_ack == 0) begin @(posedge wb_clk); end
end
data_o = wb_data_i;
wb_cyc <= 0;
wb_we<=0;
wb_stb<=0;
if(wb_tb_verbose && !rw)
$display("WB read %s: addr %x, data %x",
(size==1?"byte":((size==2)?"short":"int")),
addr, wb_data_i);
last_access_t = $time;
end
endtask // rw_generic
task write8;
input [`WB_ADDRESS_BUS_WIDTH - 1 : 0] addr;
input [7 : 0] data_i;
begin
rw_generic(addr, data_i, dummy, 1, 1);
end
endtask // write8
task read8;
input [`WB_ADDRESS_BUS_WIDTH - 1 : 0] addr;
output [7 : 0] data_o;
begin : read8_body
reg [`WB_DATA_BUS_WIDTH - 1 : 0] rval;
rw_generic(addr, 0, rval, 0, 1);
data_o = rval[7:0];
end
endtask // write8
task write32;
input [`WB_ADDRESS_BUS_WIDTH - 1 : 0] addr;
input [31 : 0] data_i;
begin
rw_generic(addr, data_i, dummy, 1, 4);
end
endtask // write32
task read32;
input [`WB_ADDRESS_BUS_WIDTH - 1 : 0] addr;
output [31 : 0] data_o;
begin : read32_body
reg [`WB_DATA_BUS_WIDTH - 1 : 0] rval;
rw_generic(addr, 0, rval, 0, 4);
data_o = rval[31:0];
end
endtask // write32
// bus monitor
always@(posedge wb_clk) begin
if(wb_monitor_bus && wb_cyc && wb_stb && wb_ack)begin
if(wb_we) $display("ACK-Write: addr %x wdata %x bwsel %b", wb_addr, wb_data_o, wb_bwsel);
else $display("ACK-Read: addr %x rdata %x", wb_addr, wb_data_i);
end
end
endmodule
\ No newline at end of file
`define ADDR_SYSC_RSTR 5'h0
`define SYSC_RSTR_TRIG_OFFSET 0
`define SYSC_RSTR_TRIG 32'h0fffffff
`define SYSC_RSTR_RST_OFFSET 28
`define SYSC_RSTR_RST 32'h10000000
`define ADDR_SYSC_GPSR 5'h4
`define SYSC_GPSR_LED_STAT_OFFSET 0
`define SYSC_GPSR_LED_STAT 32'h00000001
`define SYSC_GPSR_LED_LINK_OFFSET 1
`define SYSC_GPSR_LED_LINK 32'h00000002
`define SYSC_GPSR_FMC_SCL_OFFSET 2
`define SYSC_GPSR_FMC_SCL 32'h00000004
`define SYSC_GPSR_FMC_SDA_OFFSET 3
`define SYSC_GPSR_FMC_SDA 32'h00000008
`define SYSC_GPSR_NET_RST_OFFSET 4
`define SYSC_GPSR_NET_RST 32'h00000010
`define SYSC_GPSR_BTN1_OFFSET 5
`define SYSC_GPSR_BTN1 32'h00000020
`define SYSC_GPSR_BTN2_OFFSET 6
`define SYSC_GPSR_BTN2 32'h00000040
`define SYSC_GPSR_SFP_DET_OFFSET 7
`define SYSC_GPSR_SFP_DET 32'h00000080
`define SYSC_GPSR_SFP_SCL_OFFSET 8
`define SYSC_GPSR_SFP_SCL 32'h00000100
`define SYSC_GPSR_SFP_SDA_OFFSET 9
`define SYSC_GPSR_SFP_SDA 32'h00000200
`define ADDR_SYSC_GPCR 5'h8
`define SYSC_GPCR_LED_STAT_OFFSET 0
`define SYSC_GPCR_LED_STAT 32'h00000001
`define SYSC_GPCR_LED_LINK_OFFSET 1
`define SYSC_GPCR_LED_LINK 32'h00000002
`define SYSC_GPCR_FMC_SCL_OFFSET 2
`define SYSC_GPCR_FMC_SCL 32'h00000004
`define SYSC_GPCR_FMC_SDA_OFFSET 3
`define SYSC_GPCR_FMC_SDA 32'h00000008
`define SYSC_GPCR_SFP_SCL_OFFSET 8
`define SYSC_GPCR_SFP_SCL 32'h00000100
`define SYSC_GPCR_SFP_SDA_OFFSET 9
`define SYSC_GPCR_SFP_SDA 32'h00000200
`define ADDR_SYSC_HWFR 5'hc
`define SYSC_HWFR_MEMSIZE_OFFSET 0
`define SYSC_HWFR_MEMSIZE 32'h0000000f
`define ADDR_SYSC_TCR 5'h10
`define SYSC_TCR_TDIV_OFFSET 0
`define SYSC_TCR_TDIV 32'h00000fff
`define SYSC_TCR_ENABLE_OFFSET 31
`define SYSC_TCR_ENABLE 32'h80000000
`define ADDR_SYSC_TVR 5'h14
sim_tool="modelsim"
top_module="main"
action = "simulation"
target = "xilinx"
fetchto = "../../ip_cores"
syn_device="xc6slx45t"
include_dirs=["../include","gn4124_bfm", "ddr3"]
files = [ "main.sv","l2p_fifo.vhd","ddr3/ddr3.v" ]
modules = { "local" : [ "../../rtl", "gn4124_bfm", "../../../adc/rtl", "../../../ip_cores/timetag_core/rtl",
"../../../ip_cores/general-cores", "../../../ip_cores/ddr3-sp6-core",
"../../../ip_cores/gn4124-core" ]};
This diff is collapsed.
/****************************************************************************************
*
* File Name: ddr3_mcp.v
*
* Dependencies: ddr3.v, ddr3_parameters.vh
*
* Description: Micron SDRAM DDR3 (Double Data Rate 3) multi-chip package model
*
* Disclaimer This software code and all associated documentation, comments or other
* of Warranty: information (collectively "Software") is provided "AS IS" without
* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY
* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES
* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE
* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR
* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI,
* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT,
* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING,
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION,
* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE
* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGES. Because some jurisdictions prohibit the exclusion or
* limitation of liability for consequential or incidental damages, the
* above limitation may not apply to you.
*
* Copyright 2003 Micron Technology, Inc. All rights reserved.
*
****************************************************************************************/
`timescale 1ps / 1ps
module ddr3_mcp (
rst_n,
ck,
ck_n,
cke,
cs_n,
ras_n,
cas_n,
we_n,
dm_tdqs,
ba,
addr,
dq,
dqs,
dqs_n,
tdqs_n,
odt
);
`include "ddr3_parameters.vh"
// Declare Ports
input rst_n;
input ck;
input ck_n;
input [CS_BITS-1:0] cke;
input [CS_BITS-1:0] cs_n;
input ras_n;
input cas_n;
input we_n;
inout [DM_BITS-1:0] dm_tdqs;
input [BA_BITS-1:0] ba;
input [ADDR_BITS-1:0] addr;
inout [DQ_BITS-1:0] dq;
inout [DQS_BITS-1:0] dqs;
inout [DQS_BITS-1:0] dqs_n;
output [DQS_BITS-1:0] tdqs_n;
input [CS_BITS-1:0] odt;
wire [RANKS-1:0] cke_mcp = cke;
wire [RANKS-1:0] cs_n_mcp = cs_n;
wire [RANKS-1:0] odt_mcp = odt;
ddr3 rank [RANKS-1:0] (
rst_n,
ck,
ck_n,
cke_mcp,
cs_n_mcp,
ras_n,
cas_n,
we_n,
dm_tdqs,
ba,
addr,
dq,
dqs,
dqs_n,
tdqs_n,
odt_mcp
);
endmodule
This diff is collapsed.
This diff is collapsed.
files = ["mem_model.vhd", "textutil.vhd", "gn412x_bfm.vhd", "util.vhd"]
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment