From de5eb461f6d131c87d0b59faf659e1170851f872 Mon Sep 17 00:00:00 2001 From: RuigeLee Date: Mon, 17 Jul 2023 09:26:20 +0800 Subject: [PATCH] sim env --- .gitignore | 1 + Makefile | 66 ++ tb/sim_main.cpp | 189 +++++ tb/sw/.gitignore | 5 + tb/sw/axi_gpio/gpio.c | 40 + tb/sw/axi_gpio/gpio.h | 24 + tb/sw/axi_timer/timer.c | 232 ++++++ tb/sw/axi_timer/timer.h | 50 ++ tb/sw/axi_uart/uart.c | 82 +++ tb/sw/axi_uart/uart.h | 26 + tb/sw/linker.lds | 39 + tb/sw/src/main.c | 38 + tb/sw/src/startup.S | 156 ++++ tb/vtb/SimTop.v | 431 +++++++++++ tb/vtb/axi_full_slv_sram.v | 291 ++++++++ tb/vtb/debuger.v | 209 ++++++ tb/vtb/eth_phy.v | 1426 ++++++++++++++++++++++++++++++++++++ tb/vtb/eth_phy_defines.v | 90 +++ tb/vtb/gen_dffr.v | 57 ++ tb/vtb/gen_dffren.v | 62 ++ tb/vtb/gen_dpdffren.v | 69 ++ tb/vtb/gen_rsffr.v | 70 ++ tb/vtb/gen_slffr.v | 54 ++ tb/vtb/gen_sram.v | 97 +++ tb/vtb/tb_eth_defines.v | 212 ++++++ 25 files changed, 4016 insertions(+) create mode 100644 tb/sim_main.cpp create mode 100644 tb/sw/.gitignore create mode 100644 tb/sw/axi_gpio/gpio.c create mode 100644 tb/sw/axi_gpio/gpio.h create mode 100644 tb/sw/axi_timer/timer.c create mode 100644 tb/sw/axi_timer/timer.h create mode 100644 tb/sw/axi_uart/uart.c create mode 100644 tb/sw/axi_uart/uart.h create mode 100644 tb/sw/linker.lds create mode 100644 tb/sw/src/main.c create mode 100644 tb/sw/src/startup.S create mode 100644 tb/vtb/SimTop.v create mode 100644 tb/vtb/axi_full_slv_sram.v create mode 100644 tb/vtb/debuger.v create mode 100644 tb/vtb/eth_phy.v create mode 100644 tb/vtb/eth_phy_defines.v create mode 100644 tb/vtb/gen_dffr.v create mode 100644 tb/vtb/gen_dffren.v create mode 100644 tb/vtb/gen_dpdffren.v create mode 100644 tb/vtb/gen_rsffr.v create mode 100644 tb/vtb/gen_slffr.v create mode 100644 tb/vtb/gen_sram.v create mode 100644 tb/vtb/tb_eth_defines.v diff --git a/.gitignore b/.gitignore index 46a19b2..d35bf55 100644 --- a/.gitignore +++ b/.gitignore @@ -345,3 +345,4 @@ hs_err_pid* generated/ project/.bloop/riscv-mac-swich-build.json src/main/scala/mac/MacTilelink.scala +doc/ diff --git a/Makefile b/Makefile index 9c9e628..ca8324a 100644 --- a/Makefile +++ b/Makefile @@ -6,3 +6,69 @@ compile: sbt "test:runMain test.testModule \ -e verilog" + + +VSimTop: + rm -rf ./tb/build/ + mkdir -p ./tb/build/ + verilator -Wno-fatal \ + --timescale "1 ns / 1 ps" \ + -y ${PWD}/tb/ \ + -y ${PWD}/tb/vtb/ \ + --top-module SimTop \ + --trace-fst \ + --cc ./tb/behav_srams.v \ + --cc ./tb/UserFPGAConfig.v \ + --cc ./tb/vtb/SimTop.v \ + +define+RANDOMIZE_GARBAGE_ASSIGN \ + +define+RANDOMIZE_INVALID_ASSIGN \ + +define+RANDOMIZE_REG_INIT \ + +define+RANDOMIZE_MEM_INIT \ + +define+RANDOMIZE_DELAY=0 \ + +define+USE_POWER_PINS \ + --exe --build \ + ${PWD}/tb/sim_main.cpp \ + -Mdir ./tb/build/ \ + -j 30 + + +test: + ./tb/build/VSimTop -w -l -f ./tb/sw/build/test + + + + +sw: + riscv64-unknown-elf-gcc -Os -ggdb -march=rv32im -mabi=ilp32 -Wall -mcmodel=medany -mexplicit-relocs \ + -I ./tb/sw/ -I ./tb/sw/src -I ./tb/sw/axi_gpio -I ./tb/sw/axi_uart -I ./tb/sw/axi_timer \ + -c ./tb/sw/src/main.c \ + -o ./tb/sw/build/main.o + + riscv64-unknown-elf-gcc -Os -ggdb -march=rv32im -mabi=ilp32 -Wall -mcmodel=medany -mexplicit-relocs \ + -I ./tb/sw/ -I ./tb/sw/src -I ./tb/sw/axi_gpio -I ./tb/sw/axi_uart -I ./tb/sw/axi_timer \ + -c ./tb/sw/axi_uart/uart.c \ + -o ./tb/sw/build/uart.o + + riscv64-unknown-elf-gcc -Os -ggdb -march=rv32im -mabi=ilp32 -Wall -mcmodel=medany -mexplicit-relocs -mcmodel=medany -mexplicit-relocs \ + -I ./tb/sw/ -I ./tb/sw/src -I ./tb/sw/axi_gpio -I ./tb/sw/axi_uart -I ./tb/sw/axi_timer \ + -c ./tb/sw/src/startup.S \ + -o ./tb/sw/build/startup.o + + riscv64-unknown-elf-gcc -Os -ggdb -march=rv32im -mabi=ilp32 -Wall -mcmodel=medany -mexplicit-relocs -nostdlib -nodefaultlibs -nostartfiles \ + -T ./tb/sw/linker.lds \ + ./tb/sw/build/startup.o \ + ./tb/sw/build/uart.o \ + ./tb/sw/build/main.o \ + -o ./tb/sw/build/test.elf + + riscv64-unknown-elf-objcopy -O binary ./tb/sw/build/test.elf ./tb/sw/build/test.bin + + riscv64-unknown-elf-objdump --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.text.init --section=.data --section=.bss --section=.rodata ./tb/sw/build/test.elf > ./tb/sw/build/test.dump + + + riscv64-unknown-elf-objcopy -O verilog ./tb/sw/build/test.elf ./tb/sw/build/test.verilog + sed -i 's/@800/@000/g' ./tb/sw/build/test.verilog + +fst: + gtkwave ./tb/build/wave.fst & + diff --git a/tb/sim_main.cpp b/tb/sim_main.cpp new file mode 100644 index 0000000..7f4c92d --- /dev/null +++ b/tb/sim_main.cpp @@ -0,0 +1,189 @@ +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + +#include +#include "VSimTop.h" +#include +#include +#include + +#include + + + +#if VM_TRACE +#include "verilated_fst_c.h" +#endif + + +char* img; +VSimTop *top; +#if VM_TRACE +VerilatedFstC* tfp; +#endif +vluint64_t main_time = 0; + +double sc_time_stamp () { + return main_time; +} + + +uint8_t flag_waveEnable = 0; +uint8_t flag_limitEnable = 0; + +int prase_arg(int argc, char **argv) { + int opt; + while( -1 != ( opt = getopt( argc, argv, "pjldwf:" ) ) ) { + switch(opt) { + + case 'l': + flag_limitEnable = 1; + break; + + case 'w': + flag_waveEnable = 1; + std::cout << "Waveform is Enable" << std::endl; + break; + case 'f': + img = strdup(optarg); + // std::cout << "load in image is " << img << std::endl; + break; + case '?': + std::cout << "-w to enable waveform" << std::endl; + std::cout << "-f FILENAME to testfile" << std::endl; + return -1; + break; + default: + std::cout << opt << std::endl; + assert(0); + } + } + return 0; +} + +static void sim_exit(){ +#if VM_TRACE + if ( flag_waveEnable ) { tfp->close(); } +#endif + + top->final(); + + delete top; +} + + + + + + +int main(int argc, char **argv, char **env) { + + + if ( -1 == prase_arg(argc, argv) ) { + std::cout << "Prase Error." << std::endl; + return -1; + } + + char * temp[2]; + char cmd[64] = "+"; + strcat(cmd, img); + strcat(cmd, ".verilog"); + temp[0] = "Verilated"; + temp[1] = cmd; + char **argv_temp = temp; + Verilated::commandArgs(2, argv_temp); + + + + top = new VSimTop(); + +#if VM_TRACE + tfp = new VerilatedFstC; + if (flag_waveEnable) { + Verilated::traceEverOn(true); + top->trace(tfp, 99); // Trace 99 levels of hierarchy + + tfp->open("./tb/build/wave.fst"); + } + +#endif + + + top->RSTn = 0; + top->CLK = 0; + + + // printf("start diff\n"); + while(!Verilated::gotFinish()) { + + Verilated::timeInc(1); + + if ( main_time != 100 ){ + } else { + top->RSTn = 1; + } + + if ( main_time % 10 == 1 ) { + top->CLK = 1; + } else if ( main_time % 10 == 6 ) { + top->CLK = 0; + } + + top->eval(); +#if VM_TRACE + if ( flag_waveEnable ) { + tfp->dump(Verilated::time()); + } + +#endif + + if ( flag_limitEnable ) { + if ( main_time > 15000000 ){ + std::cout << "Timeout!!!!!" << std::endl; + sim_exit(); + return -1; + } + } + + if ( top -> fail == 1 && main_time % 100 == 0 ) { + std::cout << "Fail!!!!!!" << std::endl; + sim_exit(); + return -1; + } + else if ( top -> success == 1 && main_time % 100 == 0 ) { + std::cout << "Pass!" << std::endl; + + sim_exit(); + return 0; + } + + main_time ++; + } + + sim_exit(); + return -1; + + +} + + + + + + + + diff --git a/tb/sw/.gitignore b/tb/sw/.gitignore new file mode 100644 index 0000000..7d3a1f0 --- /dev/null +++ b/tb/sw/.gitignore @@ -0,0 +1,5 @@ + +*.elf +*.o +*.img +*.bin diff --git a/tb/sw/axi_gpio/gpio.c b/tb/sw/axi_gpio/gpio.c new file mode 100644 index 0000000..30c4290 --- /dev/null +++ b/tb/sw/axi_gpio/gpio.c @@ -0,0 +1,40 @@ + +#include +#include "gpio.h" + + + + +#ifndef GPIO_BASE +#error GPIO Base address not define!!! +#endif + + +// for 8 bit gpio + +volatile uint32_t *gpio_dat_reg = (uint32_t*)( GPIO_BASE + GPIO_DATA ); +volatile uint32_t *gpio_tri_reg = (uint32_t*)( GPIO_BASE + GPIO_TRI ); + + +uint8_t gpio_read() +{ + *gpio_tri_reg = 0xff; + return (uint8_t)(*gpio_dat_reg); +} + + +uint32_t gpio_write( uint32_t data ) +{ + *gpio_tri_reg = 0x00; + (*gpio_dat_reg) = data; + return 0; +} + + + + + + + + + diff --git a/tb/sw/axi_gpio/gpio.h b/tb/sw/axi_gpio/gpio.h new file mode 100644 index 0000000..91cbcbc --- /dev/null +++ b/tb/sw/axi_gpio/gpio.h @@ -0,0 +1,24 @@ +#ifndef _GPIO_H_ +#define _GPIO_H_ + +#include + +#define GPIO_BASE 0x20000000U + + + +#define GPIO_DATA 0x0000 +#define GPIO_TRI 0x0004 +#define GPIO2_DATA 0x0008 +#define GPIO2_TRI 0x000C +#define GIER 0x011C +#define IP_IER 0x0128 +#define IP_ISR 0x0120 + + +extern uint8_t gpio_read(); +extern uint32_t gpio_write( uint32_t data ); + +void gpio_test(); + +#endif diff --git a/tb/sw/axi_timer/timer.c b/tb/sw/axi_timer/timer.c new file mode 100644 index 0000000..a94a1e4 --- /dev/null +++ b/tb/sw/axi_timer/timer.c @@ -0,0 +1,232 @@ +/* +* @Author: Ruige Lee +* @Date: 2020-10-12 14:27:54 +* @Last Modified by: Ruige Lee +* @Last Modified time: 2020-10-12 17:16:04 +*/ + + +#include +#include "timer.h" + + +#ifndef TIMER_BASE +#error Timer Base address not define!!! +#endif + + + + +volatile uint32_t *timer_tcsr0_reg = (uint32_t*)( TIMER_BASE + TIMER_TCSR0 ); +volatile uint32_t *timer_tlr0_reg = (uint32_t*)( TIMER_BASE + TIMER_TLR0 ); +volatile uint32_t *timer_tcr0_reg = (uint32_t*)( TIMER_BASE + TIMER_TCR0 ); + + +volatile uint32_t *timer_tcsr1_reg = (uint32_t*)( TIMER_BASE + TIMER_TCSR1 ); +volatile uint32_t *timer_tlr1_reg = (uint32_t*)( TIMER_BASE + TIMER_TLR1 ); +volatile uint32_t *timer_tcr1_reg = (uint32_t*)( TIMER_BASE + TIMER_TCR1 ); + + +int32_t timerIsINT(uint8_t timerNo) +{ + if ( ( ( (*timer_tcsr0_reg) & 0x00000100 ) && ( timerNo == 0 ) ) + || + ( ( (*timer_tcsr1_reg) & 0x00000100 ) && ( timerNo == 1 ) ) + ) + { + return 1; + } + else + { + return 0; + } +} + +int32_t timerClearINT(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) | 0x00000100; + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) | 0x00000100; + } + + return 0; +} + +int32_t timerEnableRun(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) | 0x00000080; + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) | 0x00000080; + } + + return 0; +} + +int32_t timerDisableRun(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) & (~0x00000080); + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) & (~0x00000080); + } + + return 0; +} + +int32_t timerEnableINT(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) & (~0x00000020); + *timer_tcsr0_reg = (*timer_tcsr0_reg) | 0x00000040; + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) & (~0x00000020); + *timer_tcsr1_reg = (*timer_tcsr1_reg) | 0x00000040; + } + + + return 0; +} + +int32_t timerDisableINT(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) & (~0x00000040); + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) & (~0x00000040); + } + return 0; +} + +int32_t timerLoad(uint8_t timerNo, uint32_t count) +{ + if ( timerNo == 0 ) + { + *timer_tlr0_reg = count; + *timer_tcsr0_reg = (*timer_tcsr0_reg) | 0x00000020; + } + else + { + *timer_tlr1_reg = count; + *timer_tcsr1_reg = (*timer_tcsr1_reg) | 0x00000020; + } + + return 0; +} + + +int32_t timerAutoReloadEnable(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) | 0x00000010; + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) | 0x00000010; + } + + return 0; +} + +int32_t timerAutoReloadDisable(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) & (~0x00000010); + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) & (~0x00000010); + } + + + return 0; +} + +int32_t timerUpCount(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) & (~0x00000002); + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) & (~0x00000002); + } + + + return 0; +} + +int32_t timerDownCount(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) | 0x00000002; + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) | 0x00000002; + } + + return 0; +} + +int32_t timerGenerate(uint8_t timerNo) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) & (~0x00000001); + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) & (~0x00000001); + } + + return 0; +} + +int32_t timerCapture( uint8_t timerNo ) +{ + if ( timerNo == 0 ) + { + *timer_tcsr0_reg = (*timer_tcsr0_reg) | 0x00000001; + } + else + { + *timer_tcsr1_reg = (*timer_tcsr1_reg) | 0x00000001; + } + + return 0; +} + +uint32_t timerCounterRead( uint8_t timerNo ) +{ + if ( timerNo == 0 ) + { + return *timer_tcr0_reg; + } + else + { + return *timer_tcr1_reg; + } +} + + diff --git a/tb/sw/axi_timer/timer.h b/tb/sw/axi_timer/timer.h new file mode 100644 index 0000000..5ec502f --- /dev/null +++ b/tb/sw/axi_timer/timer.h @@ -0,0 +1,50 @@ + + +#ifndef _TIMER_H_ +#define _TIMER_H_ + + +#include + + + +#define TIMER_BASE 0x20000800U + + +#define TIMER_TCSR0 0x00U +#define TIMER_TLR0 0x04 +#define TIMER_TCR0 0x08 + +// #define TIMER_RSVD + +#define TIMER_TCSR1 0x10U +#define TIMER_TLR1 0x14U +#define TIMER_TCR1 0x18U + + +extern int32_t timerIsINT( uint8_t timerNo ); +extern int32_t timerClearINT( uint8_t timerNo ); +extern int32_t timerEnableRun( uint8_t timerNo ); +extern int32_t timerDisableRun( uint8_t timerNo ); +extern int32_t timerEnableINT( uint8_t timerNo ); +extern int32_t timerDisableINT( uint8_t timerNo ); +extern int32_t timerLoad( uint8_t timerNo, uint32_t count ); +extern int32_t timerAutoReloadEnable( uint8_t timerNo ); +extern int32_t timerAutoReloadDisable( uint8_t timerNo ); +extern int32_t timerUpCount( uint8_t timerNo ); +extern int32_t timerDownCount( uint8_t timerNo ); +extern int32_t timerGenerate( uint8_t timerNo ); +extern int32_t timerCapture( uint8_t timerNo ); +extern uint32_t timerCounterRead( uint8_t timerNo ); + + + + + + + + +#endif + + + diff --git a/tb/sw/axi_uart/uart.c b/tb/sw/axi_uart/uart.c new file mode 100644 index 0000000..652b634 --- /dev/null +++ b/tb/sw/axi_uart/uart.c @@ -0,0 +1,82 @@ + + +#include +#include "uart.h" + + +#ifndef UART_BASE +#error UART Base address not define!!! +#endif + + +volatile uint32_t *uart_rfifo = (uint32_t*)( UART_BASE + RX_FIFO ); +volatile uint32_t *uart_tfifo = (uint32_t*)( UART_BASE + TX_FIFO ); +volatile uint32_t *uart_status = (uint32_t*)( UART_BASE + STAT_REG ); +volatile uint32_t *uart_ctrl = (uint32_t*)( UART_BASE + CTRL_REG ); + + +int32_t uart_init() +{ + //reset rx & tx fifo, disable interrupt + (*uart_status) = 0x03; + (*uart_status) = 0x00; + + return 0; +} + + + +int32_t uart_sendByte( uint8_t data ) +{ + + //wait unitl tx fifo not full + while( ((*uart_status) & 0x08) != 0); + + uint64_t sent = (uint64_t)data << 32; + + #if(0) + (*(volatile uint64_t*)(UART_BASE)) = sent; + #else + (*(volatile uint64_t*)(0x60000000)) = sent; + #endif + + return 0; +} + + +uint8_t uart_recByte() +{ + //wait unitl rx fifo has data + while( ((*uart_status) & 0x01) == 0); + + return (uint8_t)(*uart_rfifo); +} + + + +int32_t print_uart(const char *str) +{ + const char *cur = &str[0]; + while (*cur != '\0') + { + uart_sendByte((uint8_t)*cur); + cur++; + } + + return 0; +} + + + + + + + + + + + + + + + diff --git a/tb/sw/axi_uart/uart.h b/tb/sw/axi_uart/uart.h new file mode 100644 index 0000000..cec36ba --- /dev/null +++ b/tb/sw/axi_uart/uart.h @@ -0,0 +1,26 @@ +#ifndef _UART_H_ +#define _UART_H_ + +#include + +#define UART_BASE 0x20600000U + + + +#define RX_FIFO 0x0000 +#define TX_FIFO 0x0004 +#define STAT_REG 0x0008 +#define CTRL_REG 0x000c + + +extern int32_t uart_init(); +extern int32_t uart_sendByte( uint8_t data ); +extern uint8_t uart_recByte(); +extern int32_t print_uart(const char *str); + + + + +#endif + + diff --git a/tb/sw/linker.lds b/tb/sw/linker.lds new file mode 100644 index 0000000..d6e3bb7 --- /dev/null +++ b/tb/sw/linker.lds @@ -0,0 +1,39 @@ +ENTRY(_prog_start) + +SECTIONS +{ + RAM_BASE = 0x80000000; + + . = RAM_BASE; + + .text.init : { *(.text.init) } + + .text : ALIGN(0x100) { + _TEXT_START_ = .; + *(.text) + _TEXT_END_ = .; + } + + .data : ALIGN(0x100) { + _DATA_START_ = .; + *(.data) + _DATA_END_ = .; + } + + PROVIDE(_data = ADDR(.data)); + PROVIDE(_data_lma = LOADADDR(.data)); + PROVIDE(_edata = .); + + .bss : ALIGN(0x100) { + _BSS_START_ = .; + *(.bss) + _BSS_END_ = .; + } + + .rodata : ALIGN(0x100) { + _RODATA_START_ = .; + *(.rodata) + *(.rodata*) + _RODATA_END_ = .; + } +} diff --git a/tb/sw/src/main.c b/tb/sw/src/main.c new file mode 100644 index 0000000..09cf493 --- /dev/null +++ b/tb/sw/src/main.c @@ -0,0 +1,38 @@ + +#include +#include "uart.h" +#include "gpio.h" +#include "timer.h" + +int main() +{ + // uart_init(); + + print_uart("Hello World, RocketChip is now Waking Up!\r\n"); + + // gpio_write( 0xfffffffa ); + + uint8_t i = 0; + uint32_t data = 0; + volatile uint32_t* reg = (uint32_t*)(0x80002000); + + for ( i = 0; i < 255; i++ ) + { + *(reg+i) = data; + data ++; + } + + + + while(1) + { + ; + } + return 0; + +} + +void handle_trap(void) +{ + +} \ No newline at end of file diff --git a/tb/sw/src/startup.S b/tb/sw/src/startup.S new file mode 100644 index 0000000..76b1b6b --- /dev/null +++ b/tb/sw/src/startup.S @@ -0,0 +1,156 @@ + + .section .text.init + .globl _prog_start +_prog_start: + + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + li t0, 0xffff + csrc mie, t0 + + li t0, 0xa + csrc mstatus, t0 + + + # csrwi satp,0 + # li t0,-1 + # csrw pmpaddr0,t0 + # li t0,31 + # csrw pmpcfg0,t0 + # csrwi medeleg,0 + # csrwi mideleg,0 + # li t0, 1 + # slli t0, t0, 31 + # csrw mtvec,t0 + # csrwi mie, 0 + # csrwi mstatus,0 + + li sp, 0x80001000 + + + # li t1, 0x80000200 + # li t2, -1 + # sd t2, 0(t1) + + # li t1,0x80000000 + # jr t1 + + la t0, trap_entry + csrw mtvec, t0 + + + + call main + + li gp, 1; + ecall + +trap_entry: + addi sp, sp, -136 + + sw x1, 1* 4(sp) + sw x2, 2* 4(sp) + sw x3, 3* 4(sp) + sw x4, 4* 4(sp) + sw x5, 5* 4(sp) + sw x6, 6* 4(sp) + sw x7, 7* 4(sp) + sw x8, 8* 4(sp) + sw x9, 9* 4(sp) + sw x10, 10*4(sp) + sw x11, 11*4(sp) + sw x12, 12*4(sp) + sw x13, 13*4(sp) + sw x14, 14*4(sp) + sw x15, 15*4(sp) + sw x16, 16*4(sp) + sw x17, 17*4(sp) + sw x18, 18*4(sp) + sw x19, 19*4(sp) + sw x20, 20*4(sp) + sw x21, 21*4(sp) + sw x22, 22*4(sp) + sw x23, 23*4(sp) + sw x24, 24*4(sp) + sw x25, 25*4(sp) + sw x26, 26*4(sp) + sw x27, 27*4(sp) + sw x28, 28*4(sp) + sw x29, 29*4(sp) + sw x30, 30*4(sp) + sw x31, 31*4(sp) + + csrr a0, mcause + csrr a1, mepc + mv a2, sp + jal handle_trap + # csrw mepc, a0 + + + # li t0, MSTATUS_MPP + # csrs mstatus, t0 + + lw x1, 1 *4(sp) + lw x2, 2 *4(sp) + lw x3, 3 *4(sp) + lw x4, 4 *4(sp) + lw x5, 5 *4(sp) + lw x6, 6 *4(sp) + lw x7, 7 *4(sp) + lw x8, 8 *4(sp) + lw x9, 9 *4(sp) + lw x10, 10*4(sp) + lw x11, 11*4(sp) + lw x12, 12*4(sp) + lw x13, 13*4(sp) + lw x14, 14*4(sp) + lw x15, 15*4(sp) + lw x16, 16*4(sp) + lw x17, 17*4(sp) + lw x18, 18*4(sp) + lw x19, 19*4(sp) + lw x20, 20*4(sp) + lw x21, 21*4(sp) + lw x22, 22*4(sp) + lw x23, 23*4(sp) + lw x24, 24*4(sp) + lw x25, 25*4(sp) + lw x26, 26*4(sp) + lw x27, 27*4(sp) + lw x28, 28*4(sp) + lw x29, 29*4(sp) + lw x30, 30*4(sp) + lw x31, 31*4(sp) + + addi sp, sp, 136 + mret \ No newline at end of file diff --git a/tb/vtb/SimTop.v b/tb/vtb/SimTop.v new file mode 100644 index 0000000..7f2c540 --- /dev/null +++ b/tb/vtb/SimTop.v @@ -0,0 +1,431 @@ + + + + +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + +`timescale 1 ns / 1 ps + + + + +module SimTop ( + + output success, + output fail, + + input CLK, + input RSTn + + +); + + + wire mem_axi4_0_aw_ready; + wire mem_axi4_0_aw_valid; + wire [3:0] mem_axi4_0_aw_bits_id; + wire [31:0] mem_axi4_0_aw_bits_addr; + wire [7:0] mem_axi4_0_aw_bits_len; + wire [2:0] mem_axi4_0_aw_bits_size; + wire [1:0] mem_axi4_0_aw_bits_burst; + wire mem_axi4_0_aw_bits_lock; + wire [3:0] mem_axi4_0_aw_bits_cache; + wire [2:0] mem_axi4_0_aw_bits_prot; + wire [3:0] mem_axi4_0_aw_bits_qos; + wire mem_axi4_0_w_ready; + wire mem_axi4_0_w_valid; + wire [31:0] mem_axi4_0_w_bits_data; + wire [3:0] mem_axi4_0_w_bits_strb; + wire mem_axi4_0_w_bits_last; + wire mem_axi4_0_b_ready; + wire mem_axi4_0_b_valid; + wire [3:0] mem_axi4_0_b_bits_id; + wire [1:0] mem_axi4_0_b_bits_resp; + wire mem_axi4_0_ar_ready; + wire mem_axi4_0_ar_valid; + wire [3:0] mem_axi4_0_ar_bits_id; + wire [31:0] mem_axi4_0_ar_bits_addr; + wire [7:0] mem_axi4_0_ar_bits_len; + wire [2:0] mem_axi4_0_ar_bits_size; + wire [1:0] mem_axi4_0_ar_bits_burst; + wire mem_axi4_0_ar_bits_lock; + wire [3:0] mem_axi4_0_ar_bits_cache; + wire [2:0] mem_axi4_0_ar_bits_prot; + wire [3:0] mem_axi4_0_ar_bits_qos; + wire mem_axi4_0_r_ready; + wire mem_axi4_0_r_valid; + wire [3:0] mem_axi4_0_r_bits_id; + wire [31:0] mem_axi4_0_r_bits_data; + wire [1:0] mem_axi4_0_r_bits_resp; + wire mem_axi4_0_r_bits_last; + + wire mmio_axi4_0_aw_ready; + wire mmio_axi4_0_aw_valid; + wire [3:0] mmio_axi4_0_aw_bits_id; + wire [30:0] mmio_axi4_0_aw_bits_addr; + wire [7:0] mmio_axi4_0_aw_bits_len; + wire [2:0] mmio_axi4_0_aw_bits_size; + wire [1:0] mmio_axi4_0_aw_bits_burst; + wire mmio_axi4_0_aw_bits_lock; + wire [3:0] mmio_axi4_0_aw_bits_cache; + wire [2:0] mmio_axi4_0_aw_bits_prot; + wire [3:0] mmio_axi4_0_aw_bits_qos; + wire mmio_axi4_0_w_ready; + wire mmio_axi4_0_w_valid; + wire [31:0] mmio_axi4_0_w_bits_data; + wire [3:0] mmio_axi4_0_w_bits_strb; + wire mmio_axi4_0_w_bits_last; + wire mmio_axi4_0_b_ready; + wire mmio_axi4_0_b_valid; + wire [3:0] mmio_axi4_0_b_bits_id; + wire [1:0] mmio_axi4_0_b_bits_resp; + wire mmio_axi4_0_ar_ready; + wire mmio_axi4_0_ar_valid; + wire [3:0] mmio_axi4_0_ar_bits_id; + wire [30:0] mmio_axi4_0_ar_bits_addr; + wire [7:0] mmio_axi4_0_ar_bits_len; + wire [2:0] mmio_axi4_0_ar_bits_size; + wire [1:0] mmio_axi4_0_ar_bits_burst; + wire mmio_axi4_0_ar_bits_lock; + wire [3:0] mmio_axi4_0_ar_bits_cache; + wire [2:0] mmio_axi4_0_ar_bits_prot; + wire [3:0] mmio_axi4_0_ar_bits_qos; + wire mmio_axi4_0_r_ready; + wire mmio_axi4_0_r_valid; + wire [3:0] mmio_axi4_0_r_bits_id; + wire [31:0] mmio_axi4_0_r_bits_data; + wire [1:0] mmio_axi4_0_r_bits_resp; + wire mmio_axi4_0_r_bits_last; + + + + wire Mdi_I; + wire Mdc_O; + wire Mdo_O; + wire Mdo_OE; + wire mtx_clk; + wire [3:0] MTxD; + wire MTxEn; + wire MTxErr; + wire mrx_clk; + wire [3:0] MRxD; + wire MRxDV; + wire MRxErr; + wire MColl; + wire MCrs; + wire Mdio_IO; + + assign Mdio_IO = Mdo_OE ? Mdo_O : 1'bz; + assign Mdi_I = Mdio_IO; + +wire dmactive; + + +ExampleRocketSystem i_rocket( + .clock(CLK), + .reset(~RSTn), + + .resetctrl_hartIsInReset_0(~RSTn), + .debug_clock(CLK), + .debug_reset(~RSTn), + .debug_systemjtag_jtag_TCK(1'b0), + .debug_systemjtag_jtag_TMS(1'b0), + .debug_systemjtag_jtag_TDI(1'b0), + .debug_systemjtag_jtag_TDO_data(), + .debug_systemjtag_jtag_TDO_driven(), + .debug_systemjtag_reset(~RSTn), + .debug_systemjtag_mfr_id(11'b0), + .debug_systemjtag_part_number(16'b0), + .debug_systemjtag_version(4'b0), + .debug_ndreset(), + .debug_dmactive(dmactive), + .debug_dmactiveAck(dmactive), + + .mem_axi4_0_aw_ready (mem_axi4_0_aw_ready), + .mem_axi4_0_aw_valid (mem_axi4_0_aw_valid), + .mem_axi4_0_aw_bits_id (mem_axi4_0_aw_bits_id), + .mem_axi4_0_aw_bits_addr (mem_axi4_0_aw_bits_addr), + .mem_axi4_0_aw_bits_len (mem_axi4_0_aw_bits_len), + .mem_axi4_0_aw_bits_size (mem_axi4_0_aw_bits_size), + .mem_axi4_0_aw_bits_burst(mem_axi4_0_aw_bits_burst), + .mem_axi4_0_aw_bits_lock (mem_axi4_0_aw_bits_lock), + .mem_axi4_0_aw_bits_cache(mem_axi4_0_aw_bits_cache), + .mem_axi4_0_aw_bits_prot (mem_axi4_0_aw_bits_prot), + .mem_axi4_0_aw_bits_qos (mem_axi4_0_aw_bits_qos), + .mem_axi4_0_w_ready (mem_axi4_0_w_ready), + .mem_axi4_0_w_valid (mem_axi4_0_w_valid), + .mem_axi4_0_w_bits_data (mem_axi4_0_w_bits_data), + .mem_axi4_0_w_bits_strb (mem_axi4_0_w_bits_strb), + .mem_axi4_0_w_bits_last (mem_axi4_0_w_bits_last), + .mem_axi4_0_b_ready (mem_axi4_0_b_ready), + .mem_axi4_0_b_valid (mem_axi4_0_b_valid), + .mem_axi4_0_b_bits_id (mem_axi4_0_b_bits_id), + .mem_axi4_0_b_bits_resp (mem_axi4_0_b_bits_resp), + .mem_axi4_0_ar_ready (mem_axi4_0_ar_ready), + .mem_axi4_0_ar_valid (mem_axi4_0_ar_valid), + .mem_axi4_0_ar_bits_id (mem_axi4_0_ar_bits_id), + .mem_axi4_0_ar_bits_addr (mem_axi4_0_ar_bits_addr), + .mem_axi4_0_ar_bits_len (mem_axi4_0_ar_bits_len), + .mem_axi4_0_ar_bits_size (mem_axi4_0_ar_bits_size), + .mem_axi4_0_ar_bits_burst(mem_axi4_0_ar_bits_burst), + .mem_axi4_0_ar_bits_lock (mem_axi4_0_ar_bits_lock), + .mem_axi4_0_ar_bits_cache(mem_axi4_0_ar_bits_cache), + .mem_axi4_0_ar_bits_prot (mem_axi4_0_ar_bits_prot), + .mem_axi4_0_ar_bits_qos (mem_axi4_0_ar_bits_qos), + .mem_axi4_0_r_ready (mem_axi4_0_r_ready), + .mem_axi4_0_r_valid (mem_axi4_0_r_valid), + .mem_axi4_0_r_bits_id (mem_axi4_0_r_bits_id), + .mem_axi4_0_r_bits_data (mem_axi4_0_r_bits_data), + .mem_axi4_0_r_bits_resp (mem_axi4_0_r_bits_resp), + .mem_axi4_0_r_bits_last (mem_axi4_0_r_bits_last), + + .mmio_axi4_0_aw_ready (mmio_axi4_0_aw_ready), + .mmio_axi4_0_aw_valid (mmio_axi4_0_aw_valid), + .mmio_axi4_0_aw_bits_id (mmio_axi4_0_aw_bits_id), + .mmio_axi4_0_aw_bits_addr (mmio_axi4_0_aw_bits_addr), + .mmio_axi4_0_aw_bits_len (mmio_axi4_0_aw_bits_len), + .mmio_axi4_0_aw_bits_size (mmio_axi4_0_aw_bits_size), + .mmio_axi4_0_aw_bits_burst(mmio_axi4_0_aw_bits_burst), + .mmio_axi4_0_aw_bits_lock (mmio_axi4_0_aw_bits_lock), + .mmio_axi4_0_aw_bits_cache(mmio_axi4_0_aw_bits_cache), + .mmio_axi4_0_aw_bits_prot (mmio_axi4_0_aw_bits_prot), + .mmio_axi4_0_aw_bits_qos (mmio_axi4_0_aw_bits_qos), + .mmio_axi4_0_w_ready (mmio_axi4_0_w_ready), + .mmio_axi4_0_w_valid (mmio_axi4_0_w_valid), + .mmio_axi4_0_w_bits_data (mmio_axi4_0_w_bits_data), + .mmio_axi4_0_w_bits_strb (mmio_axi4_0_w_bits_strb), + .mmio_axi4_0_w_bits_last (mmio_axi4_0_w_bits_last), + .mmio_axi4_0_b_ready (mmio_axi4_0_b_ready), + .mmio_axi4_0_b_valid (mmio_axi4_0_b_valid), + .mmio_axi4_0_b_bits_id (mmio_axi4_0_b_bits_id), + .mmio_axi4_0_b_bits_resp (mmio_axi4_0_b_bits_resp), + .mmio_axi4_0_ar_ready (mmio_axi4_0_ar_ready), + .mmio_axi4_0_ar_valid (mmio_axi4_0_ar_valid), + .mmio_axi4_0_ar_bits_id (mmio_axi4_0_ar_bits_id), + .mmio_axi4_0_ar_bits_addr (mmio_axi4_0_ar_bits_addr), + .mmio_axi4_0_ar_bits_len (mmio_axi4_0_ar_bits_len), + .mmio_axi4_0_ar_bits_size (mmio_axi4_0_ar_bits_size), + .mmio_axi4_0_ar_bits_burst(mmio_axi4_0_ar_bits_burst), + .mmio_axi4_0_ar_bits_lock (mmio_axi4_0_ar_bits_lock), + .mmio_axi4_0_ar_bits_cache(mmio_axi4_0_ar_bits_cache), + .mmio_axi4_0_ar_bits_prot (mmio_axi4_0_ar_bits_prot), + .mmio_axi4_0_ar_bits_qos (mmio_axi4_0_ar_bits_qos), + .mmio_axi4_0_r_ready (mmio_axi4_0_r_ready), + .mmio_axi4_0_r_valid (mmio_axi4_0_r_valid), + .mmio_axi4_0_r_bits_id (mmio_axi4_0_r_bits_id), + .mmio_axi4_0_r_bits_data (mmio_axi4_0_r_bits_data), + .mmio_axi4_0_r_bits_resp (mmio_axi4_0_r_bits_resp), + .mmio_axi4_0_r_bits_last (mmio_axi4_0_r_bits_last), + + + .interrupts(2'b0), + + .macIO_mdi(Mdi_I), + .macIO_mdc(Mdc_O), + .macIO_mdo(Mdo_O), + .macIO_mdoEn(Mdo_OE), + .macIO_mtx_clk_pad_i(mtx_clk), + .macIO_mtxd_pad_o(MTxD), + .macIO_mtxen_pad_o(MTxEn), + .macIO_mtxerr_pad_o(MTxErr), + .macIO_mrx_clk_pad_i(mrx_clk), + .macIO_mrxd_pad_i(MRxD), + .macIO_mrxdv_pad_i(MRxDV), + .macIO_mrxerr_pad_i(MRxErr), + .macIO_mcoll_pad_i(MColl), + .macIO_mcrs_pad_i(MCrs) +); + + + +integer phy_log_file_desc; + +// eth_phy s_phy// This PHY model simulate simplified Intel LXT971A PHY +// ( + +// .m_rst_n_i(RSTn), +// .mtx_clk_o(mtx_clk), +// .mtxd_i(MTxD), +// .mtxen_i(MTxEn), +// .mtxerr_i(MTxErr), + +// .mrx_clk_o(mrx_clk), +// .mrxd_o(MRxD), +// .mrxdv_o(MRxDV), +// .mrxerr_o(MRxErr), +// .mcoll_o(MColl), +// .mcrs_o(MCrs), + +// .mdc_i(Mdc_O), +// .md_io(Mdio_IO), + +// // SYSTEM +// .phy_log(phy_log_file_desc) +// ); + +// initial +// begin +// phy_log_file_desc = $fopen("./log/eth_tb_phy.log"); + +// $display(phy_log_file_desc, "================ PHY Module Testbench access log ================"); +// $display(phy_log_file_desc, " "); +// end + + + +axi_full_slv_sram # ( .DW(32), .AW(18) ) s_axi_full_slv_sram +( + + .MEM_AWID (mem_axi4_0_aw_bits_id), + .MEM_BID (mem_axi4_0_b_bits_id), + .MEM_ARID (mem_axi4_0_ar_bits_id), + .MEM_RID (mem_axi4_0_r_bits_id), + + .MEM_AWADDR (mem_axi4_0_aw_bits_addr), + .MEM_AWLEN (mem_axi4_0_aw_bits_len), + .MEM_AWSIZE (mem_axi4_0_aw_bits_size), + .MEM_AWBURST(mem_axi4_0_aw_bits_burst), + .MEM_AWVALID(mem_axi4_0_aw_valid), + .MEM_AWREADY(mem_axi4_0_aw_ready), + .MEM_WDATA (mem_axi4_0_w_bits_data), + .MEM_WSTRB (mem_axi4_0_w_bits_strb), + .MEM_WLAST (mem_axi4_0_w_bits_last), + .MEM_WVALID (mem_axi4_0_w_valid), + .MEM_WREADY (mem_axi4_0_w_ready), + .MEM_BRESP (mem_axi4_0_b_bits_resp), + .MEM_BVALID (mem_axi4_0_b_valid), + .MEM_BREADY (mem_axi4_0_b_ready), + .MEM_ARADDR (mem_axi4_0_ar_bits_addr), + .MEM_ARLEN (mem_axi4_0_ar_bits_len), + .MEM_ARSIZE (mem_axi4_0_ar_bits_size), + .MEM_ARBURST(mem_axi4_0_ar_bits_burst), + .MEM_ARVALID(mem_axi4_0_ar_valid), + .MEM_ARREADY(mem_axi4_0_ar_ready), + .MEM_RDATA (mem_axi4_0_r_bits_data), + .MEM_RRESP (mem_axi4_0_r_bits_resp), + .MEM_RLAST (mem_axi4_0_r_bits_last), + .MEM_RVALID (mem_axi4_0_r_valid), + .MEM_RREADY (mem_axi4_0_r_ready), + + .CLK (CLK), + .RSTn (RSTn) +); + +wire debugger_success; + +debuger i_debuger( + .success(debugger_success), + .DEBUGER_AWID (mmio_axi4_0_aw_bits_id), + .DEBUGER_BID (mmio_axi4_0_b_bits_id), + .DEBUGER_ARID (mmio_axi4_0_ar_bits_id), + .DEBUGER_RID (mmio_axi4_0_r_bits_id), + + .DEBUGER_AWADDR (mmio_axi4_0_aw_bits_addr), + .DEBUGER_AWVALID(mmio_axi4_0_aw_valid), + .DEBUGER_AWREADY(mmio_axi4_0_aw_ready), + + .DEBUGER_WDATA (mmio_axi4_0_w_bits_data), + .DEBUGER_WSTRB (mmio_axi4_0_w_bits_strb), + .DEBUGER_WVALID(mmio_axi4_0_w_valid), + .DEBUGER_WREADY(mmio_axi4_0_w_ready), + + .DEBUGER_BRESP (mmio_axi4_0_b_bits_rsp), + .DEBUGER_BVALID(mmio_axi4_0_b_valid), + .DEBUGER_BREADY(mmio_axi4_0_b_ready), + + .DEBUGER_ARADDR (mmio_axi4_0_ar_bits_addr), + .DEBUGER_ARVALID(mmio_axi4_0_ar_valid), + .DEBUGER_ARREADY(mmio_axi4_0_ar_ready), + + .DEBUGER_RDATA (mmio_axi4_0_r_bits_data), + .DEBUGER_RRESP (mmio_axi4_0_r_bits_rsp), + .DEBUGER_RVALID(mmio_axi4_0_r_valid), + .DEBUGER_RREADY(mmio_axi4_0_r_ready), + + .CLK(CLK), + .RSTn(RSTn) + +); + + + + + + + + + + + + +assign success = debugger_success; + + + + +string testName; + +`define MEM s_axi_full_slv_sram.i_sram.ram +reg [7:0] mem [0:200000]; + +localparam DP = 2**18; +integer i, by; +initial begin + +#20 + + if ( $value$plusargs("%s",testName) ) begin + $display("%s",testName); + $readmemh(testName, mem); + + end + else begin + $display("%s",testName); + $error("Failed to read Files!"); + end + + + for ( i = 0; i < DP; i = i + 1 ) begin + for ( by = 0; by < 4; by = by + 1 ) begin + if ( | mem[i*4+by] ) begin + `MEM[i][8*by +: 8] = mem[i*4+by]; + end + else begin + `MEM[i][8*by +: 8] = 8'h0; + end + end + end + + $display("%x",`MEM[0]); + $display("%x",`MEM[1]); + $display("%x",`MEM[2]); + $display("%x",`MEM[3]); + +end + + + + + +endmodule + + + + + + diff --git a/tb/vtb/axi_full_slv_sram.v b/tb/vtb/axi_full_slv_sram.v new file mode 100644 index 0000000..ad9ffdc --- /dev/null +++ b/tb/vtb/axi_full_slv_sram.v @@ -0,0 +1,291 @@ + + + +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + + +`timescale 1 ns / 1 ps + + + + +module axi_full_slv_sram # +( + parameter DW = 32, + parameter AW = 14 +) +( + + input [3:0] MEM_AWID, + output [3:0] MEM_BID, + input [3:0] MEM_ARID, + output [3:0] MEM_RID, + + + input [31:0] MEM_AWADDR, + input [7:0] MEM_AWLEN, + input [2:0] MEM_AWSIZE, + input [1:0] MEM_AWBURST, + input MEM_AWVALID, + output MEM_AWREADY, + + + input [DW-1:0] MEM_WDATA, + input [DW/8-1:0] MEM_WSTRB, + input MEM_WLAST, + input MEM_WVALID, + output MEM_WREADY, + + output [1:0] MEM_BRESP, + output MEM_BVALID, + input MEM_BREADY, + + input [31:0] MEM_ARADDR, + input [7:0] MEM_ARLEN, + input [2:0] MEM_ARSIZE, + input [1:0] MEM_ARBURST, + input MEM_ARVALID, + output MEM_ARREADY, + + output [DW-1:0] MEM_RDATA, + output [1:0] MEM_RRESP, + output MEM_RLAST, + output MEM_RVALID, + input MEM_RREADY, + + input CLK, + input RSTn +); + + localparam ADDR_LSB = $clog2(DW/8); + + + + gen_dffren # (.DW(4)) awid_dffren (.dnxt(MEM_AWID), .qout(MEM_BID), .en(MEM_AWVALID & MEM_AWREADY), .CLK(CLK), .RSTn(RSTn)); + gen_dffren # (.DW(4)) arid_dffren (.dnxt(MEM_ARID), .qout(MEM_RID), .en(MEM_ARVALID & MEM_ARREADY), .CLK(CLK), .RSTn(RSTn)); + + + + + wire [31:0] aw_wrap_size; + wire [31:0] ar_wrap_size; + wire aw_wrap_en, ar_wrap_en; + + wire axi_awready_set, axi_awready_rst, axi_awready_qout; + wire axi_awv_awr_flag_set, axi_awv_awr_flag_rst, axi_awv_awr_flag_qout; + wire [31:0] axi_awaddr_dnxta; + wire [31:0] axi_awaddr_dnxtb; + wire [31:0] axi_awaddr_qout; + wire axi_awaddr_ena, axi_awaddr_enb; + wire axi_awburst_en; + wire [1:0] axi_awburst_dnxt; + wire [1:0] axi_awburst_qout; + wire axi_awlen_en; + wire [7:0] axi_awlen_dnxt; + wire [7:0] axi_awlen_qout; + wire [7:0] axi_awlen_cnt_dnxta; + wire [7:0] axi_awlen_cnt_dnxtb; + wire [7:0] axi_awlen_cnt_qout; + wire axi_awlen_cnt_ena, axi_awlen_cnt_enb; + wire axi_wready_set, axi_wready_rst, axi_wready_qout; + wire axi_bvalid_set, axi_bvalid_rst, axi_bvalid_qout; + wire axi_arready_set, axi_arready_rst, axi_arready_qout; + wire axi_arv_arr_flag_set, axi_arv_arr_flag_rst, axi_arv_arr_flag_qout; + wire [31:0] axi_araddr_dnxta; + wire [31:0] axi_araddr_dnxtb; + wire [31:0] axi_araddr_qout; + wire axi_araddr_ena, axi_araddr_enb, axi_arburst_en; + wire [1:0] axi_arburst_dnxt; + wire [1:0] axi_arburst_qout; + wire axi_arlen_en; + wire [7:0] axi_arlen_dnxt; + wire [7:0] axi_arlen_qout; + wire [7:0] axi_arlen_cnt_dnxta; + wire [7:0] axi_arlen_cnt_dnxtb; + wire [7:0] axi_arlen_cnt_qout; + wire axi_arlen_cnt_ena, axi_arlen_cnt_enb; + wire axi_rvalid_set, axi_rvalid_rst, axi_rvalid_qout; + wire axi_rlast_set, axi_rlast_rst, axi_rlast_qout; + + + assign MEM_AWREADY = axi_awready_qout; + assign MEM_WREADY = axi_wready_qout; + assign MEM_BRESP = 2'b00; + assign MEM_BVALID = axi_bvalid_qout; + assign MEM_ARREADY = axi_arready_qout; + assign MEM_RRESP = 2'b00; + assign MEM_RLAST = axi_rlast_qout; + assign MEM_RVALID = axi_rvalid_qout; + + + + assign axi_awready_set = (~axi_awready_qout & MEM_AWVALID & ~axi_awv_awr_flag_qout & ~axi_arv_arr_flag_qout); + assign axi_awready_rst = ~(~axi_awready_qout & MEM_AWVALID & ~axi_awv_awr_flag_qout & ~axi_arv_arr_flag_qout) & ~(MEM_WLAST & axi_wready_qout); + gen_rsffr axi_awready_rsffr (.set_in(axi_awready_set), .rst_in(axi_awready_rst), .qout(axi_awready_qout), .CLK(CLK), .RSTn(RSTn)); + + assign axi_awv_awr_flag_set = (~axi_awready_qout & MEM_AWVALID & ~axi_awv_awr_flag_qout & ~axi_arv_arr_flag_qout); + assign axi_awv_awr_flag_rst = ( axi_awready_qout | ~MEM_AWVALID | axi_awv_awr_flag_qout | axi_arv_arr_flag_qout) & (MEM_WLAST & axi_wready_qout); + gen_rsffr axi_awv_awr_flag_rsffr (.set_in(axi_awv_awr_flag_set), .rst_in(axi_awv_awr_flag_rst), .qout(axi_awv_awr_flag_qout), .CLK(CLK), .RSTn(RSTn)); + + assign axi_awaddr_dnxta = MEM_AWADDR; + assign axi_awaddr_dnxtb = ( {32{axi_awburst_qout == 2'b00}} & axi_awaddr_qout ) + | + ( {32{axi_awburst_qout == 2'b01}} & axi_awaddr_qout + (1< + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +`timescale 1 ns / 1 ps + + + +module debuger ( + output success, + + input [3:0] DEBUGER_AWID, + output [3:0] DEBUGER_BID, + input [3:0] DEBUGER_ARID, + output [3:0] DEBUGER_RID, + + input [31:0] DEBUGER_AWADDR, + input DEBUGER_AWVALID, + output DEBUGER_AWREADY, + + input [31:0] DEBUGER_WDATA, + input [3:0] DEBUGER_WSTRB, + input DEBUGER_WVALID, + output DEBUGER_WREADY, + + output [1:0] DEBUGER_BRESP, + output DEBUGER_BVALID, + input DEBUGER_BREADY, + + input [31:0] DEBUGER_ARADDR, + input DEBUGER_ARVALID, + output DEBUGER_ARREADY, + + output [31:0] DEBUGER_RDATA, + output [1:0] DEBUGER_RRESP, + output DEBUGER_RVALID, + input DEBUGER_RREADY, + + input CLK, + input RSTn + +); + + + + gen_dffren # (.DW(4)) awid_dffren (.dnxt(DEBUGER_AWID), .qout(DEBUGER_BID), .en(DEBUGER_AWVALID & DEBUGER_AWREADY), .CLK(CLK), .RSTn(RSTn)); + gen_dffren # (.DW(4)) arid_dffren (.dnxt(DEBUGER_ARID), .qout(DEBUGER_RID), .en(DEBUGER_ARVALID & DEBUGER_ARREADY), .CLK(CLK), .RSTn(RSTn)); + + assign DEBUGER_AWREADY = debuger_awready_qout; + assign DEBUGER_WREADY = debuger_wready_qout; + assign DEBUGER_BRESP = 2'b0; + assign DEBUGER_BVALID = debuger_bvalid_qout; + assign DEBUGER_ARREADY = debuger_arready_qout; + assign DEBUGER_RDATA = 32'b0; + assign DEBUGER_RRESP = 2'b0; + assign DEBUGER_RVALID = debuger_rvalid_qout; + + wire debuger_awready_set, debuger_awready_rst, debuger_awready_qout; + wire aw_en_set, aw_en_rst, aw_en_qout; + wire debuger_wready_set, debuger_wready_rst, debuger_wready_qout; + + + assign debuger_awready_set = ~debuger_awready_qout & DEBUGER_AWVALID & DEBUGER_WVALID; + assign debuger_awready_rst = ~debuger_awready_set & (DEBUGER_BREADY & debuger_bvalid_qout); + + + assign debuger_wready_set = ~debuger_wready_qout & DEBUGER_WVALID & DEBUGER_AWVALID; + assign debuger_wready_rst = ~debuger_wready_set; + + gen_rsffr #(.DW(1)) debuger_awready_rsffr (.set_in(debuger_awready_set), .rst_in(debuger_awready_rst), .qout(debuger_awready_qout), .CLK(CLK), .RSTn(RSTn)); + gen_rsffr #(.DW(1)) debuger_wready_rsffr (.set_in(debuger_wready_set), .rst_in(debuger_wready_rst), .qout(debuger_wready_qout), .CLK(CLK), .RSTn(RSTn)); + + + + + + + + + + wire debuger_bvalid_set, debuger_bvalid_rst, debuger_bvalid_qout; + wire debuger_arready_set, debuger_arready_rst, debuger_arready_qout; + wire debuger_rvalid_set, debuger_rvalid_rst, debuger_rvalid_qout; + + assign debuger_bvalid_set = debuger_awready_qout && DEBUGER_AWVALID && ~debuger_bvalid_qout && debuger_wready_qout && DEBUGER_WVALID; + assign debuger_bvalid_rst = ~debuger_bvalid_set & (DEBUGER_BREADY && debuger_bvalid_qout); + assign debuger_arready_set = (~debuger_arready_qout && DEBUGER_ARVALID); + assign debuger_arready_rst = ~debuger_arready_set; + assign debuger_rvalid_set = (debuger_arready_qout & DEBUGER_ARVALID & ~debuger_rvalid_qout); + assign debuger_rvalid_rst = ~debuger_rvalid_set & (debuger_rvalid_qout & DEBUGER_RREADY); + + gen_rsffr #(.DW(1)) debuger_bvalid_rsffr (.set_in(debuger_bvalid_set), .rst_in(debuger_bvalid_rst), .qout(debuger_bvalid_qout), .CLK(CLK), .RSTn(RSTn)); + gen_rsffr #(.DW(1)) debuger_arready_rsffr (.set_in(debuger_arready_set), .rst_in(debuger_arready_rst), .qout(debuger_arready_qout), .CLK(CLK), .RSTn(RSTn)); + gen_rsffr #(.DW(1)) debuger_rvalid_rsffr (.set_in(debuger_rvalid_set), .rst_in(debuger_rvalid_rst), .qout(debuger_rvalid_qout), .CLK(CLK), .RSTn(RSTn)); + + + + + +`define UART_TX 32'h60000000 +`define TIMER 32'h60000008 +`define COTRL 32'h60000010 +`define COTRL_COREMARK 32'h60000020 + + +reg [63:0] cycle_cnt; +reg timer_start; + +reg success_reg = 1'b0; +assign success = success_reg; + +always @(posedge CLK or negedge RSTn) begin + if (~RSTn) begin + cycle_cnt <= 0; + timer_start <= 1'b0; + end + else begin + if ( (DEBUGER_AWADDR == `TIMER) & DEBUGER_AWVALID & DEBUGER_AWREADY & DEBUGER_WVALID & DEBUGER_WREADY & (DEBUGER_WDATA == 32'd1)) begin + timer_start <= 1'b1; + end + if ( (DEBUGER_AWADDR == `TIMER) & DEBUGER_AWVALID & DEBUGER_WVALID & (DEBUGER_WDATA == 32'd0)) begin + timer_start <= 1'b0; + end + if (timer_start) begin + cycle_cnt <= cycle_cnt + 1; + end + else begin + cycle_cnt <= cycle_cnt; + end + end + + +end + + + + + + + +always @(posedge CLK) begin + + if ( (DEBUGER_AWADDR == `UART_TX) & DEBUGER_AWVALID & DEBUGER_AWREADY & DEBUGER_WVALID & DEBUGER_WREADY) begin + $write("%c", DEBUGER_WDATA[7:0]); + end + + +end + + + +integer file; +always @(posedge CLK ) begin + + if ( (DEBUGER_AWADDR == `COTRL) & DEBUGER_AWVALID & DEBUGER_AWREADY & DEBUGER_WVALID & DEBUGER_WREADY & (DEBUGER_WDATA == 32'd1)) begin + $display("cycle_cnt = %d", cycle_cnt); + $display( "The DMIPS/MHz is %f", 1000000.0/(cycle_cnt/500.0)/1757.0 ); + + + file = $fopen("./dhrystone.json", "w"); + + $fwrite(file, "{\n \"schemaVersion\": 1, \n \"label\": \"\", \n \"message\": \"%f\", \n \"color\": \"ff69b4\" \n}", 1000000.0/(cycle_cnt/500.0)/1757.0 ); + $fclose(file); + + success_reg <= 1'b1; + end + + if ( (DEBUGER_AWADDR == `COTRL_COREMARK) & DEBUGER_AWVALID & DEBUGER_AWREADY & DEBUGER_WVALID & DEBUGER_WREADY & (DEBUGER_WDATA == 32'd1)) begin + $display("Total ticks : %d", cycle_cnt); + $display("CoreMark 1.0 : %f",1*1*1000000.0/cycle_cnt); + + + file = $fopen("./coremark.json", "w"); + + $fwrite(file, "{\n \"schemaVersion\": 1, \n \"label\": \"\", \n \"message\": \"%f\", \n \"color\": \"368fb4\" \n}", 1*1*1000000.0/cycle_cnt ); + $fclose(file); + + success_reg <= 1'b1; + + end + +end + + + + +endmodule + + + + + + + diff --git a/tb/vtb/eth_phy.v b/tb/vtb/eth_phy.v new file mode 100644 index 0000000..2fe39a5 --- /dev/null +++ b/tb/vtb/eth_phy.v @@ -0,0 +1,1426 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: eth_phy.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/project,ethmac //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is available in the README.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.7 2002/10/18 13:58:22 tadejm +// Some code changed due to bug fixes. +// +// Revision 1.6 2002/10/09 13:16:51 tadejm +// Just back-up; not completed testbench and some testcases are not +// wotking properly yet. +// +// Revision 1.5 2002/09/18 17:55:08 tadej +// Bug repaired in eth_phy device +// +// Revision 1.3 2002/09/13 14:50:15 mohor +// Bug in MIIM fixed. +// +// Revision 1.2 2002/09/13 12:29:14 mohor +// Headers changed. +// +// Revision 1.1 2002/09/13 11:57:20 mohor +// New testbench. Thanks to Tadej M - "The Spammer". +// +// +// + + +`include "eth_phy_defines.v" +`include "tb_eth_defines.v" +module eth_phy // This PHY model simulate simplified Intel LXT971A PHY +( + // COMMON + m_rst_n_i, + + // MAC TX + mtx_clk_o, + mtxd_i, + mtxen_i, + mtxerr_i, + + // MAC RX + mrx_clk_o, + mrxd_o, + mrxdv_o, + mrxerr_o, + + mcoll_o, + mcrs_o, + + // MIIM + mdc_i, + md_io, + + // SYSTEM + phy_log +); + +////////////////////////////////////////////////////////////////////// +// +// Input/output signals +// +////////////////////////////////////////////////////////////////////// + +// MAC miscellaneous signals +input m_rst_n_i; +// MAC TX signals +output mtx_clk_o; +input [3:0] mtxd_i; +input mtxen_i; +input mtxerr_i; +// MAC RX signals +output mrx_clk_o; +output [3:0] mrxd_o; +output mrxdv_o; +output mrxerr_o; +// MAC common signals +output mcoll_o; +output mcrs_o; +// MAC management signals +input mdc_i; +inout md_io; +// SYSTEM +input [31:0] phy_log; + + +////////////////////////////////////////////////////////////////////// +// +// PHY management (MIIM) REGISTER definitions +// +////////////////////////////////////////////////////////////////////// +// +// Supported registers: +// +// Addr | Register Name +//-------------------------------------------------------------------- +// 0 | Control reg. | +// 1 | Status reg. #1 |--> normal operation +// 2 | PHY ID reg. 1 | +// 3 | PHY ID reg. 2 | +//---------------------- +// Addr | Data MEMORY |--> for testing +// +//-------------------------------------------------------------------- +// +// Control register +reg control_bit15; // self clearing bit +reg [14:10] control_bit14_10; +reg control_bit9; // self clearing bit +reg [8:0] control_bit8_0; +// Status register +wire [15:9] status_bit15_9 = `SUPPORTED_SPEED_AND_PORT; +wire status_bit8 = `EXTENDED_STATUS; +wire status_bit7 = 1'b0; // reserved +reg [6:0] status_bit6_0; +// PHY ID register 1 +wire [15:0] phy_id1 = `PHY_ID1; +// PHY ID register 2 +wire [15:0] phy_id2 = {`PHY_ID2, `MAN_MODEL_NUM, `MAN_REVISION_NUM}; +//-------------------------------------------------------------------- +// +// Data MEMORY +reg [15:0] data_mem [0:31]; // 32 locations of 16-bit data width +// +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////// +// +// PHY clocks - RX & TX +// +////////////////////////////////////////////////////////////////////// + +reg mtx_clk_o; +reg mrx_clk_o; + +// random generator for a RX period when link is down +real rx_link_down_halfperiod; + +always@(status_bit6_0[2]) +begin + if (!status_bit6_0[2]) // Link is down + begin + #1 rx_link_down_halfperiod = ({$random} % 243) + 13; + `ifdef VERBOSE + #1 $fdisplay(phy_log, " (%0t)(%m)MAC RX clock is %f MHz while ethernet link is down!", + $time, (1000/(rx_link_down_halfperiod*2)) ); + `endif + end +end + +`ifdef VERBOSE +always@(status_bit6_0[2]) +begin + if (!status_bit6_0[2]) // Link is down + #1 $fdisplay(phy_log, " (%0t)(%m)Ethernet link is down!", $time); + else + #1 $fdisplay(phy_log, " (%0t)(%m)Ethernet link is up!", $time); +end +`endif + +// speed selection signal eth_speed: 1'b1 - 100 Mbps, 1'b0 - 10 Mbps +wire eth_speed; + +assign eth_speed = ( (control_bit14_10[13]) && !((`LED_CFG1) && (`LED_CFG2)) ); + +`ifdef VERBOSE +always@(eth_speed) +begin + if (eth_speed) + #1 $fdisplay(phy_log, " (%0t)(%m)PHY configured to 100 Mbps!", $time); + else + #1 $fdisplay(phy_log, " (%0t)(%m)PHY configured tp 10 Mbps!", $time); +end +`endif + +// different clock calculation between RX and TX, so that there is alsways a litle difference +/*initial +begin + set_mrx_equal_mtx = 1; // default +end*/ + +always +begin + mtx_clk_o = 0; + #7; + forever + begin + if (eth_speed) // 100 Mbps - 25 MHz, 40 ns + begin + #20 mtx_clk_o = ~mtx_clk_o; + end + else // 10 Mbps - 2.5 MHz, 400 ns + begin + #200 mtx_clk_o = ~mtx_clk_o; + end + end +end + +always +begin + // EQUAL mrx_clk to mtx_clk + mrx_clk_o = 0; + #7; + forever + begin + if (eth_speed) // 100 Mbps - 25 MHz, 40 ns + begin + #20 mrx_clk_o = ~mrx_clk_o; + end + else // 10 Mbps - 2.5 MHz, 400 ns + begin + #200 mrx_clk_o = ~mrx_clk_o; + end + end +end + + +////////////////////////////////////////////////////////////////////// +// +// PHY management (MIIM) interface +// +////////////////////////////////////////////////////////////////////// +reg respond_to_all_phy_addr; // PHY will respond to all phy addresses +reg no_preamble; // PHY responds to frames without preamble + +integer md_transfer_cnt; // counter countes the value of whole data transfer +reg md_transfer_cnt_reset; // for reseting the counter +reg md_io_reg; // registered input +reg md_io_output; // registered output +reg md_io_rd_wr; // op-code latched (read or write) +reg md_io_enable; // output enable +reg [4:0] phy_address; // address of PHY device +reg [4:0] reg_address; // address of a register +reg md_get_phy_address; // for shifting PHY address in +reg md_get_reg_address; // for shifting register address in +reg [15:0] reg_data_in; // data to be written in a register +reg md_get_reg_data_in; // for shifting data in +reg md_put_reg_data_in; // for storing data into a selected register +reg [15:0] reg_data_out; // data to be read from a register +reg md_put_reg_data_out; // for registering data from a selected register + +wire [15:0] register_bus_in; // data bus to a selected register +reg [15:0] register_bus_out; // data bus from a selected register + +initial +begin + md_io_enable = 1'b0; + respond_to_all_phy_addr = 1'b0; + no_preamble = 1'b0; +end + +// tristate output +assign md_io = (m_rst_n_i && md_io_enable) ? md_io_output : 1'bz ; + +// registering input +always@(posedge mdc_i or negedge m_rst_n_i) +begin + if (!m_rst_n_i) + md_io_reg <= 0; + else + md_io_reg <= md_io; +end + +// getting (shifting) PHY address, Register address and Data in +// putting Data out and shifting +always@(posedge mdc_i or negedge m_rst_n_i) +begin + if (!m_rst_n_i) + begin + phy_address <= 0; + reg_address <= 0; + reg_data_in <= 0; + reg_data_out <= 0; + md_io_output <= 0; + end + else + begin + if (md_get_phy_address) + begin + phy_address[4:1] <= phy_address[3:0]; // correct address is `ETH_PHY_ADDR + phy_address[0] <= md_io; + end + if (md_get_reg_address) + begin + reg_address[4:1] <= reg_address[3:0]; + reg_address[0] <= md_io; + end + if (md_get_reg_data_in) + begin + reg_data_in[15:1] <= reg_data_in[14:0]; + reg_data_in[0] <= md_io; + end + if (md_put_reg_data_out) + begin + reg_data_out <= register_bus_out; + end + if (md_io_enable) + begin + md_io_output <= reg_data_out[15]; + reg_data_out[15:1] <= reg_data_out[14:0]; + reg_data_out[0] <= 1'b0; + end + end +end + +assign register_bus_in = reg_data_in; // md_put_reg_data_in - allows writing to a selected register + +// counter for transfer to and from MIIM +always@(posedge mdc_i or negedge m_rst_n_i) +begin + if (!m_rst_n_i) + begin + if (no_preamble) + md_transfer_cnt <= 33; + else + md_transfer_cnt <= 1; + end + else + begin + if (md_transfer_cnt_reset) + begin + if (no_preamble) + md_transfer_cnt <= 33; + else + md_transfer_cnt <= 1; + end + else if (md_transfer_cnt < 64) + begin + md_transfer_cnt <= md_transfer_cnt + 1'b1; + end + else + begin + if (no_preamble) + md_transfer_cnt <= 33; + else + md_transfer_cnt <= 1; + end + end +end + +// MIIM transfer control +// always@(m_rst_n_i or md_transfer_cnt or md_io_reg or md_io_rd_wr or +// phy_address or respond_to_all_phy_addr or no_preamble) +// begin +// #1; +// while ((m_rst_n_i) && (md_transfer_cnt <= 64)) +// begin +// // reset the signal - put registered data in the register (when write) +// // check preamble +// if (md_transfer_cnt < 33) +// begin +// #4 md_put_reg_data_in = 1'b0; +// if (md_io_reg !== 1'b1) +// begin +// #1 md_transfer_cnt_reset = 1'b1; +// end +// else +// begin +// #1 md_transfer_cnt_reset = 1'b0; +// end +// end + +// // check start bits +// else if (md_transfer_cnt == 33) +// begin +// if (no_preamble) +// begin +// #4 md_put_reg_data_in = 1'b0; +// if (md_io_reg === 1'b0) +// begin +// #1 md_transfer_cnt_reset = 1'b0; +// end +// else +// begin +// #1 md_transfer_cnt_reset = 1'b1; +// //if ((md_io_reg !== 1'bz) && (md_io_reg !== 1'b1)) +// if (md_io_reg !== 1'bz) +// begin +// // ERROR - start ! +// `ifdef VERBOSE +// $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong first start bit (without preamble)", $time); +// `endif +// #10 $stop; +// end +// end +// end +// else // with preamble +// begin +// #4 ; +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m)MIIM - 32-bit preamble received", $time); +// `endif +// // check start bit only if md_transfer_cnt_reset is inactive, because if +// // preamble suppression was changed start bit should not be checked +// if ((md_io_reg !== 1'b0) && (md_transfer_cnt_reset == 1'b0)) +// begin +// // ERROR - start ! +// `ifdef VERBOSE +// $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong first start bit", $time); +// `endif +// #10 $stop; +// end +// end +// end + +// else if (md_transfer_cnt == 34) +// begin +// #4; +// if (md_io_reg !== 1'b1) +// begin +// // ERROR - start ! +// #1; +// `ifdef VERBOSE +// if (no_preamble) +// $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong second start bit (without preamble)", $time); +// else +// $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong second start bit", $time); +// `endif +// #10 $stop; +// end +// else +// begin +// `ifdef VERBOSE +// if (no_preamble) +// #1 $fdisplay(phy_log, " (%0t)(%m)MIIM - 2 start bits received (without preamble)", $time); +// else +// #1 $fdisplay(phy_log, " (%0t)(%m)MIIM - 2 start bits received", $time); +// `endif +// end +// end + +// // register the op-code (rd / wr) +// else if (md_transfer_cnt == 35) +// begin +// #4; +// if (md_io_reg === 1'b1) +// begin +// #1 md_io_rd_wr = 1'b1; +// end +// else +// begin +// #1 md_io_rd_wr = 1'b0; +// end +// end + +// else if (md_transfer_cnt == 36) +// begin +// #4; +// if ((md_io_reg === 1'b0) && (md_io_rd_wr == 1'b1)) +// begin +// #1 md_io_rd_wr = 1'b1; // reading from PHY registers +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m)MIIM - op-code for READING from registers", $time); +// `endif +// end +// else if ((md_io_reg === 1'b1) && (md_io_rd_wr == 1'b0)) +// begin +// #1 md_io_rd_wr = 1'b0; // writing to PHY registers +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m)MIIM - op-code for WRITING to registers", $time); +// `endif +// end +// else +// begin +// // ERROR - wrong opcode ! +// `ifdef VERBOSE +// #1 $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong OP-CODE", $time); +// `endif +// #10 $stop; +// end +// // set the signal - get PHY address +// begin +// #1 md_get_phy_address = 1'b1; +// end +// end + +// // reset the signal - get PHY address +// else if (md_transfer_cnt == 41) +// begin +// #4 md_get_phy_address = 1'b0; +// // set the signal - get register address +// #1 md_get_reg_address = 1'b1; +// end + +// // reset the signal - get register address +// // set the signal - put register data to output register +// else if (md_transfer_cnt == 46) +// begin +// #4 md_get_reg_address = 1'b0; +// #1 md_put_reg_data_out = 1'b1; +// end + +// // reset the signal - put register data to output register +// // set the signal - enable md_io as output when read +// else if (md_transfer_cnt == 47) +// begin +// #4 md_put_reg_data_out = 1'b0; +// if (md_io_rd_wr) //read +// begin +// if (md_io_reg !== 1'bz) +// begin +// // ERROR - turn around ! +// `ifdef VERBOSE +// #1 $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong turn-around cycle before reading data out", $time); +// `endif +// #10 $stop; +// end +// if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address +// begin +// #1 md_io_enable = 1'b1; +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m)MIIM - received correct PHY ADDRESS: %x", $time, phy_address); +// `endif +// end +// else +// begin +// `ifdef VERBOSE +// #1 $fdisplay(phy_log, "*W (%0t)(%m)MIIM - received different PHY ADDRESS: %x", $time, phy_address); +// `endif +// end +// end +// else // write +// begin +// #1 md_io_enable = 1'b0; +// // check turn around cycle when write on clock 47 +// if (md_io_reg !== 1'b1) +// begin +// // ERROR - turn around ! +// `ifdef VERBOSE +// #1 $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong 1. turn-around cycle before writing data in", +// $time); +// `endif +// #10 $stop; +// end +// end +// end + +// // set the signal - get register data in when write +// else if (md_transfer_cnt == 48) +// begin +// #4; +// if (!md_io_rd_wr) // write +// begin +// #1 md_get_reg_data_in = 1'b1; +// // check turn around cycle when write on clock 48 +// if (md_io_reg !== 1'b0) +// begin +// // ERROR - turn around ! +// `ifdef VERBOSE +// #1 $fdisplay(phy_log, "*E (%0t)(%m)MIIM - wrong 2. turn-around cycle before writing data in", +// $time); +// `endif +// #10 $stop; +// end +// end +// else // read +// begin +// #1 md_get_reg_data_in = 1'b0; +// end +// end + +// // reset the signal - enable md_io as output when read +// // reset the signal - get register data in when write +// // set the signal - put registered data in the register when write +// else if (md_transfer_cnt == 64) +// begin +// #1 md_io_enable = 1'b0; +// #4 md_get_reg_data_in = 1'b0; +// if (!md_io_rd_wr) // write +// begin +// if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address +// begin +// #1 md_put_reg_data_in = 1'b1; +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m)MIIM - received correct PHY ADDRESS: %x", $time, phy_address); +// $fdisplay(phy_log, " (%0t)(%m)MIIM - WRITING to register %x COMPLETED!", $time, reg_address); +// `endif +// end +// else +// begin +// `ifdef VERBOSE +// #1 $fdisplay(phy_log, "*W (%0t)(%m)MIIM - received different PHY ADDRESS: %x", $time, phy_address); +// $fdisplay(phy_log, "*W (%0t)(%m)MIIM - NO WRITING to register %x !", $time, reg_address); +// `endif +// end +// end +// else // read +// begin +// `ifdef VERBOSE +// if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address +// #1 $fdisplay(phy_log, " (%0t)(%m)MIIM - READING from register %x COMPLETED!", +// $time, reg_address); +// else +// #1 $fdisplay(phy_log, "*W (%0t)(%m)MIIM - NO READING from register %x !", $time, reg_address); +// `endif +// end +// end + +// wait for one clock period +// @(posedge mdc_i) +// #1; +// end +// end + +//==================================================================== +// +// PHY management (MIIM) REGISTERS +// +//==================================================================== +// +// Supported registers (normal operation): +// +// Addr | Register Name +//-------------------------------------------------------------------- +// 0 | Control reg. +// 1 | Status reg. #1 +// 2 | PHY ID reg. 1 +// 3 | PHY ID reg. 2 +//---------------------- +// Addr | Data MEMORY |--> for testing +// +//-------------------------------------------------------------------- +// +// Control register +// reg control_bit15; // self clearing bit +// reg [14:10] control_bit14_10; +// reg control_bit9; // self clearing bit +// reg [8:0] control_bit8_0; +// Status register +// wire [15:9] status_bit15_9 = `SUPPORTED_SPEED_AND_PORT; +// wire status_bit8 = `EXTENDED_STATUS; +// wire status_bit7 = 1'b0; // reserved +// reg [6:0] status_bit6_0 = `DEFAULT_STATUS; +// PHY ID register 1 +// wire [15:0] phy_id1 = `PHY_ID1; +// PHY ID register 2 +// wire [15:0] phy_id2 = {`PHY_ID2, `MAN_MODEL_NUM, `MAN_REVISION_NUM}; +//-------------------------------------------------------------------- +// +// Data MEMORY +// reg [15:0] data_mem [0:31]; // 32 locations of 16-bit data width +// +//==================================================================== + +////////////////////////////////////////////////////////////////////// +// +// PHY management (MIIM) REGISTER control +// +////////////////////////////////////////////////////////////////////// + +// wholy writable registers for walking ONE's on data, phy and reg. addresses +reg registers_addr_data_test_operation; + +// Non writable status registers +initial // always +begin + #1 status_bit6_0[6] = no_preamble; + status_bit6_0[5] = 1'b0; + status_bit6_0[3] = 1'b1; + status_bit6_0[0] = 1'b1; +end +always@(posedge mrx_clk_o) +begin + status_bit6_0[4] <= #1 1'b0; + status_bit6_0[1] <= #1 1'b0; +end +initial +begin + status_bit6_0[2] = 1'b1; + registers_addr_data_test_operation = 0; +end + +// Reading from a selected registers +always@(reg_address or registers_addr_data_test_operation or md_put_reg_data_out or + control_bit15 or control_bit14_10 or control_bit9 or control_bit8_0 or + status_bit15_9 or status_bit8 or status_bit7 or status_bit6_0 or + phy_id1 or phy_id2) +begin + if (registers_addr_data_test_operation) // test operation + begin + if (md_put_reg_data_out) // read enable + begin + register_bus_out = #1 data_mem[reg_address]; + end + end + else // normal operation + begin + if (md_put_reg_data_out) // read enable + begin + case (reg_address) + 5'h0: register_bus_out = #1 {control_bit15, control_bit14_10, control_bit9, control_bit8_0}; + 5'h1: register_bus_out = #1 {status_bit15_9, status_bit8, status_bit7, status_bit6_0}; + 5'h2: register_bus_out = #1 phy_id1; + 5'h3: register_bus_out = #1 phy_id2; + default: register_bus_out = #1 16'hDEAD; + endcase + end + end +end + +// Self clear control signals +reg self_clear_d0; +reg self_clear_d1; +reg self_clear_d2; +reg self_clear_d3; +// Self clearing control +always@(posedge mdc_i or negedge m_rst_n_i) +begin + if (!m_rst_n_i) + begin + self_clear_d0 <= #1 0; + self_clear_d1 <= #1 0; + self_clear_d2 <= #1 0; + self_clear_d3 <= #1 0; + end + else + begin + self_clear_d0 <= #1 md_put_reg_data_in; + self_clear_d1 <= #1 self_clear_d0; + self_clear_d2 <= #1 self_clear_d1; + self_clear_d3 <= #1 self_clear_d2; + end +end + +// Writing to a selected register +always@(posedge mdc_i or negedge m_rst_n_i) +begin + if ((!m_rst_n_i) || (control_bit15)) + begin + if (!registers_addr_data_test_operation) // normal operation + begin + control_bit15 <= #1 0; + control_bit14_10 <= #1 {1'b0, (`LED_CFG1 || `LED_CFG2), `LED_CFG1, 2'b0}; + control_bit9 <= #1 0; + control_bit8_0 <= #1 {`LED_CFG3, 8'b0}; + end + end + else + begin + if (registers_addr_data_test_operation) // test operation + begin + if (md_put_reg_data_in) + begin + data_mem[reg_address] <= #1 register_bus_in[15:0]; + end + end + else // normal operation + begin + // bits that are normaly written + if (md_put_reg_data_in) + begin + case (reg_address) + 5'h0: + begin + control_bit14_10 <= #1 register_bus_in[14:10]; + control_bit8_0 <= #1 register_bus_in[8:0]; + end + default: + begin + end + endcase + end + // self cleared bits written + if ((md_put_reg_data_in) && (reg_address == 5'h0)) + begin + control_bit15 <= #1 register_bus_in[15]; + control_bit9 <= #1 register_bus_in[9]; + end + else if (self_clear_d3) // self cleared bits cleared + begin + control_bit15 <= #1 1'b0; + control_bit9 <= #1 1'b0; + end + end + end +end + +////////////////////////////////////////////////////////////////////// +// +// PHY <-> MAC control (RX and TX clocks are at the begining) +// +////////////////////////////////////////////////////////////////////// + +// CARRIER SENSE & COLLISION + +// MAC common signals +reg mcoll_o; +reg mcrs_o; +// Internal signals controling Carrier sense & Collision + // MAC common signals generated when appropriate transfer +reg mcrs_rx; +reg mcrs_tx; + // delayed mtxen_i signal for generating delayed tx carrier sense +reg mtxen_d1; +reg mtxen_d2; +reg mtxen_d3; +reg mtxen_d4; +reg mtxen_d5; +reg mtxen_d6; + // collision signal set or rest within task for controling collision +reg task_mcoll; + // carrier sense signal set or rest within task for controling carrier sense +reg task_mcrs; +reg task_mcrs_lost; + // do not generate collision in half duplex - not normal operation +reg no_collision_in_half_duplex; + // generate collision in full-duplex mode also - not normal operation +reg collision_in_full_duplex; + // do not generate carrier sense in half duplex mode - not normal operation +reg no_carrier_sense_in_tx_half_duplex; +reg no_carrier_sense_in_rx_half_duplex; + // generate carrier sense during TX in full-duplex mode also - not normal operation +reg carrier_sense_in_tx_full_duplex; + // do not generate carrier sense during RX in full-duplex mode - not normal operation +reg no_carrier_sense_in_rx_full_duplex; + // on RX: delay after carrier sense signal; on TX: carrier sense delayed (delay is one clock period) +reg real_carrier_sense; + +initial +begin + mcrs_rx = 0; + mcrs_tx = 0; + task_mcoll = 0; + task_mcrs = 0; + task_mcrs_lost = 0; + no_collision_in_half_duplex = 0; + collision_in_full_duplex = 0; + no_carrier_sense_in_tx_half_duplex = 0; + no_carrier_sense_in_rx_half_duplex = 0; + carrier_sense_in_tx_full_duplex = 0; + no_carrier_sense_in_rx_full_duplex = 0; + real_carrier_sense = 0; +end + +// Collision +always@(m_rst_n_i or control_bit8_0 or collision_in_full_duplex or + mcrs_rx or mcrs_tx or task_mcoll or no_collision_in_half_duplex + ) +begin + if (!m_rst_n_i) + mcoll_o = 0; + else + begin + if (control_bit8_0[8]) // full duplex + begin + if (collision_in_full_duplex) // collision is usually not asserted in full duplex + begin + mcoll_o = ((mcrs_rx && mcrs_tx) || task_mcoll); + `ifdef VERBOSE + if (mcrs_rx && mcrs_tx) + $fdisplay(phy_log, " (%0t)(%m) Collision set in FullDuplex!", $time); + if (task_mcoll) + $fdisplay(phy_log, " (%0t)(%m) Collision set in FullDuplex from TASK!", $time); + `endif + end + else + begin + mcoll_o = task_mcoll; + `ifdef VERBOSE + if (task_mcoll) + $fdisplay(phy_log, " (%0t)(%m) Collision set in FullDuplex from TASK!", $time); + `endif + end + end + else // half duplex + begin + mcoll_o = ((mcrs_rx && mcrs_tx && !no_collision_in_half_duplex) || + task_mcoll); + `ifdef VERBOSE + if (mcrs_rx && mcrs_tx) + $fdisplay(phy_log, " (%0t)(%m) Collision set in HalfDuplex!", $time); + if (task_mcoll) + $fdisplay(phy_log, " (%0t)(%m) Collision set in HalfDuplex from TASK!", $time); + `endif + end + end +end + +// Carrier sense +always@(m_rst_n_i or control_bit8_0 or carrier_sense_in_tx_full_duplex or + no_carrier_sense_in_rx_full_duplex or + no_carrier_sense_in_tx_half_duplex or + no_carrier_sense_in_rx_half_duplex or + mcrs_rx or mcrs_tx or task_mcrs or task_mcrs_lost + ) +begin + if (!m_rst_n_i) + mcrs_o = 0; + else + begin + if (control_bit8_0[8]) // full duplex + begin + if (carrier_sense_in_tx_full_duplex) // carrier sense is usually not asserted during TX in full duplex + mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_full_duplex) || + mcrs_tx || task_mcrs) && !task_mcrs_lost; + else + mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_full_duplex) || + task_mcrs) && !task_mcrs_lost; + end + else // half duplex + begin + mcrs_o = ((mcrs_rx && !no_carrier_sense_in_rx_half_duplex) || + (mcrs_tx && !no_carrier_sense_in_tx_half_duplex) || + task_mcrs) && !task_mcrs_lost; + end + end +end + +// MAC TX CONTROL (RECEIVING AT PHY) + +// storage memory for TX data received from MAC +reg [7:0] tx_mem [0:4194303]; // 4194304 locations (22 address lines) of 8-bit data width +reg [31:0] tx_mem_addr_in; // address for storing to TX memory +reg [7:0] tx_mem_data_in; // data for storing to TX memory +reg [31:0] tx_cnt; // counts nibbles + +// control data of a TX packet for upper layer of testbench +reg tx_preamble_ok; +reg tx_sfd_ok; +// if there is a drible nibble, then tx packet is not byte aligned! +reg tx_byte_aligned_ok; +// complete length of TX packet (Bytes) received (without preamble and SFD) +reg [31:0] tx_len; +// complete length of TX packet (Bytes) received (without preamble and SFD) untill MTxErr signal was set first +reg [31:0] tx_len_err; + +// TX control +always@(posedge mtx_clk_o) +begin + // storing data and basic checking of frame + if (!m_rst_n_i) + begin + tx_cnt <= 0; + tx_preamble_ok <= 0; + tx_sfd_ok <= 0; + tx_len <= 0; + tx_len_err <= 0; + end + else + begin + if (!mtxen_i) + begin + tx_cnt <= 0; + end + else + begin + // tx nibble counter + tx_cnt <= tx_cnt + 1; + // set initial values and check first preamble nibble + if (tx_cnt == 0) + begin + `ifdef VERBOSE + $fdisplay(phy_log, " (%0t)(%m) TX frame started with tx_en set!", $time); + `endif + if (mtxd_i == 4'h5) + tx_preamble_ok <= 1; + else + tx_preamble_ok <= 0; + tx_sfd_ok <= 0; + tx_byte_aligned_ok <= 0; + tx_len <= 0; + tx_len_err <= 0; +// tx_mem_addr_in <= 0; + end + + // check preamble + if ((tx_cnt > 0) && (tx_cnt <= 13)) + begin + if ((tx_preamble_ok != 1) || (mtxd_i != 4'h5)) + tx_preamble_ok <= 0; + end + // check SFD + if (tx_cnt == 14) + begin + `ifdef VERBOSE + if (tx_preamble_ok == 1) + $fdisplay(phy_log, " (%0t)(%m) TX frame preamble OK!", $time); + else + $fdisplay(phy_log, "*E (%0t)(%m) TX frame preamble NOT OK!", $time); + `endif + if (mtxd_i == 4'h5) + tx_sfd_ok <= 1; + else + tx_sfd_ok <= 0; + end + if (tx_cnt == 15) + begin + if ((tx_sfd_ok != 1) || (mtxd_i != 4'hD)) + tx_sfd_ok <= 0; + end + + // control for storing addresses, type/length, data and FCS to TX memory + if (tx_cnt > 15) + begin + if (tx_cnt == 16) + begin + `ifdef VERBOSE + if (tx_sfd_ok == 1) + $fdisplay(phy_log, " (%0t)(%m) TX frame SFD OK!", $time); + else + $fdisplay(phy_log, "*E (%0t)(%m) TX frame SFD NOT OK!", $time); + `endif + end + + if (tx_cnt[0] == 0) + begin + tx_mem_data_in[3:0] <= mtxd_i; // storing LSB nibble + tx_byte_aligned_ok <= 0; // if transfer will stop after this, then there was drible nibble + end + else + begin + tx_mem[tx_mem_addr_in[21:0]] <= {mtxd_i, tx_mem_data_in[3:0]}; // storing data into tx memory + tx_len <= tx_len + 1; // enlarge byte length counter + tx_byte_aligned_ok <= 1; // if transfer will stop after this, then transfer is byte alligned + tx_mem_addr_in <= tx_mem_addr_in + 1'b1; + end + + if (mtxerr_i) + tx_len_err <= tx_len; + end + end + end + + // generating CARRIER SENSE for TX with or without delay + if (!m_rst_n_i) + begin + mcrs_tx <= 0; + mtxen_d1 <= 0; + mtxen_d2 <= 0; + mtxen_d3 <= 0; + mtxen_d4 <= 0; + mtxen_d5 <= 0; + mtxen_d6 <= 0; + end + else + begin + mtxen_d1 <= mtxen_i; + mtxen_d2 <= mtxen_d1; + mtxen_d3 <= mtxen_d2; + mtxen_d4 <= mtxen_d3; + mtxen_d5 <= mtxen_d4; + mtxen_d6 <= mtxen_d5; + if (real_carrier_sense) + mcrs_tx <= mtxen_d6; + else + mcrs_tx <= mtxen_i; + end +end + +`ifdef VERBOSE +reg frame_started; + +initial +begin + frame_started = 0; +end +always@(posedge mtxen_i) +begin + frame_started <= 1; +end +always@(negedge mtxen_i) +begin + if (frame_started) + begin + $fdisplay(phy_log, " (%0t)(%m) TX frame ended with tx_en reset!", $time); + frame_started <= 0; + end +end + +always@(posedge mrxerr_o) +begin + $fdisplay(phy_log, " (%0t)(%m) RX frame ERROR signal was set!", $time); +end +`endif + +////////////////////////////////////////////////////////////////////// +// +// Tasks for PHY <-> MAC transactions +// +////////////////////////////////////////////////////////////////////// + +initial +begin + tx_mem_addr_in = 0; +end + +// setting the address of tx_mem, to set the starting point of tx packet +// task set_tx_mem_addr; +// input [31:0] tx_mem_address; +// begin +// #1 tx_mem_addr_in = tx_mem_address; +// end +// endtask // set_tx_mem_addr + +// storage memory for RX data to be transmited to MAC +reg [7:0] rx_mem [0:4194303]; // 4194304 locations (22 address lines) of 8-bit data width + +// MAC RX signals +reg [3:0] mrxd_o; +reg mrxdv_o; +reg mrxerr_o; + +initial +begin + mrxd_o = 0; + mrxdv_o = 0; + mrxerr_o = 0; + mcrs_rx = 0; +end + +// task send_rx_packet; +// input [(8*8)-1:0] preamble_data; // preamble data to be sent - correct is 64'h0055_5555_5555_5555 +// input [3:0] preamble_len; // length of preamble in bytes - max is 4'h8, correct is 4'h7 +// input [7:0] sfd_data; // SFD data to be sent - correct is 8'hD5 +// input [31:0] start_addr; // start address +// input [31:0] len; // length of frame in Bytes (without preamble and SFD) +// input plus_drible_nibble; // if length is longer for one nibble +// integer rx_cnt; +// reg [31:0] rx_mem_addr_in; // address for reading from RX memory +// reg [7:0] rx_mem_data_out; // data for reading from RX memory +// begin +// @(posedge mrx_clk_o); +// // generating CARRIER SENSE for TX with or without delay +// if (real_carrier_sense) +// #1 mcrs_rx = 1; +// else +// #1 mcrs_rx = 0; +// @(posedge mrx_clk_o); +// #1 mcrs_rx = 1; +// #1 mrxdv_o = 1; +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m) RX frame started with rx_dv set!", $time); +// `endif +// // set initial rx memory address +// rx_mem_addr_in = start_addr; + +// // send preamble +// for (rx_cnt = 0; (rx_cnt < (preamble_len << 1)) && (rx_cnt < 16); rx_cnt = rx_cnt + 1) +// begin +// #1 mrxd_o = preamble_data[3:0]; +// #1 preamble_data = preamble_data >> 4; +// @(posedge mrx_clk_o); +// end + +// // send SFD +// for (rx_cnt = 0; rx_cnt < 2; rx_cnt = rx_cnt + 1) +// begin +// #1 mrxd_o = sfd_data[3:0]; +// #1 sfd_data = sfd_data >> 4; +// @(posedge mrx_clk_o); +// end +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m) RX frame preamble and SFD sent!", $time); +// `endif +// // send packet's addresses, type/length, data and FCS +// for (rx_cnt = 0; rx_cnt < len; rx_cnt = rx_cnt + 1) +// begin +// #1; +// rx_mem_data_out = rx_mem[rx_mem_addr_in[21:0]]; +// mrxd_o = rx_mem_data_out[3:0]; +// @(posedge mrx_clk_o); +// #1; +// mrxd_o = rx_mem_data_out[7:4]; +// rx_mem_addr_in = rx_mem_addr_in + 1; +// @(posedge mrx_clk_o); +// #1; +// end +// if (plus_drible_nibble) +// begin +// rx_mem_data_out = rx_mem[rx_mem_addr_in[21:0]]; +// mrxd_o = rx_mem_data_out[3:0]; +// @(posedge mrx_clk_o); +// end +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m) RX frame addresses, type/length, data and FCS sent!", $time); +// `endif +// #1 mcrs_rx = 0; +// #1 mrxdv_o = 0; +// @(posedge mrx_clk_o); +// `ifdef VERBOSE +// $fdisplay(phy_log, " (%0t)(%m) RX frame ended with rx_dv reset!", $time); +// `endif +// end +// endtask // send_rx_packet + + + +// task GetDataOnMRxD; +// input [15:0] Len; +// input [31:0] TransferType; +// integer tt; + +// begin +// @ (posedge mrx_clk_o); +// #1 mrxdv_o=1'b1; + +// for(tt=0; tt<15; tt=tt+1) +// begin +// mrxd_o=4'h5; // preamble +// @ (posedge mrx_clk_o); +// #1; +// end + +// mrxd_o=4'hd; // SFD + +// for(tt=1; tt<(Len+1); tt=tt+1) +// begin +// @ (posedge mrx_clk_o); +// #1; +// if(TransferType == `UNICAST_XFR && tt == 1) +// mrxd_o = 4'h0; // Unicast transfer +// else if(TransferType == `BROADCAST_XFR && tt < 7) +// mrxd_o = 4'hf; +// else +// mrxd_o = tt[3:0]; // Multicast transfer + +// @ (posedge mrx_clk_o); +// #1; + +// if(TransferType == `BROADCAST_XFR && tt == 6) +// mrxd_o = 4'he; +// else + +// if(TransferType == `BROADCAST_XFR && tt < 7) +// mrxd_o = 4'hf; +// else +// mrxd_o = tt[7:4]; +// end + +// @ (posedge mrx_clk_o); +// #1; +// mrxdv_o = 1'b0; +// end +// endtask // GetDataOnMRxD + + +// ////////////////////////////////////////////////////////////////////// +// // +// // Tastks for controling PHY statuses and rx error +// // +// ////////////////////////////////////////////////////////////////////// + +// // Link control tasks +// task link_up_down; +// input test_op; +// begin +// #1 status_bit6_0[2] = test_op; // 1 - link up; 0 - link down +// end +// endtask + +// // RX error +// task rx_err; +// input test_op; +// begin +// #1 mrxerr_o = test_op; // 1 - RX error set; 0 - RX error reset +// end +// endtask + +// ////////////////////////////////////////////////////////////////////// +// // +// // Tastks for controling PHY carrier sense and collision +// // +// ////////////////////////////////////////////////////////////////////// + +// // Collision +// task collision; +// input test_op; +// begin +// #1 task_mcoll = test_op; +// end +// endtask + +// // Carrier sense +// task carrier_sense; +// input test_op; +// begin +// #1 task_mcrs = test_op; +// end +// endtask + +// // Carrier sense lost - higher priority than Carrier sense task +// task carrier_sense_lost; +// input test_op; +// begin +// #1 task_mcrs_lost = test_op; +// end +// endtask + +// // No collision detection in half duplex +// task no_collision_hd_detect; +// input test_op; +// begin +// #1 no_collision_in_half_duplex = test_op; +// end +// endtask + +// // Collision detection in full duplex also +// task collision_fd_detect; +// input test_op; +// begin +// #1 collision_in_full_duplex = test_op; +// end +// endtask + +// // No carrier sense detection at TX in half duplex +// task no_carrier_sense_tx_hd_detect; +// input test_op; +// begin +// #1 no_carrier_sense_in_tx_half_duplex = test_op; +// end +// endtask + +// // No carrier sense detection at RX in half duplex +// task no_carrier_sense_rx_hd_detect; +// input test_op; +// begin +// #1 no_carrier_sense_in_rx_half_duplex = test_op; +// end +// endtask + +// // Carrier sense detection at TX in full duplex also +// task carrier_sense_tx_fd_detect; +// input test_op; +// begin +// #1 carrier_sense_in_tx_full_duplex = test_op; +// end +// endtask + +// // No carrier sense detection at RX in full duplex +// task no_carrier_sense_rx_fd_detect; +// input test_op; +// begin +// #1 no_carrier_sense_in_rx_full_duplex = test_op; +// end +// endtask + +// // Set real delay on carrier sense signal (and therefor collision signal) +// task carrier_sense_real_delay; +// input test_op; +// begin +// #1 real_carrier_sense = test_op; +// end +// endtask + +// ////////////////////////////////////////////////////////////////////// +// // +// // Tastks for controling PHY management test operation +// // +// ////////////////////////////////////////////////////////////////////// + +// // Set registers to test operation and respond to all phy addresses +// task test_regs; +// input test_op; +// begin +// #1 registers_addr_data_test_operation = test_op; +// respond_to_all_phy_addr = test_op; +// end +// endtask + +// // Clears data memory for testing the MII +// task clear_test_regs; +// integer i; +// begin +// for (i = 0; i < 32; i = i + 1) +// begin +// #1 data_mem[i] = 16'h0; +// end +// end +// endtask + +// // Accept frames with preamble suppresed +// task preamble_suppresed; +// input test_op; +// begin +// no_preamble = test_op; +// md_transfer_cnt_reset = 1'b1; +// @(posedge mdc_i); +// md_transfer_cnt_reset = 1'b0; +// end +// endtask + + + + + +endmodule + diff --git a/tb/vtb/eth_phy_defines.v b/tb/vtb/eth_phy_defines.v new file mode 100644 index 0000000..7e9fdda --- /dev/null +++ b/tb/vtb/eth_phy_defines.v @@ -0,0 +1,90 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name: eth_phy_defines.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/project,ethmac //// +//// //// +//// Author(s): //// +//// - Tadej Markovic, tadej@opencores.org //// +//// //// +//// All additional information is available in the README.txt //// +//// file. //// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2002, Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.1 2002/09/13 11:57:20 mohor +// New testbench. Thanks to Tadej M - "The Spammer". +// +// +// + +// Address of PHY device (LXT971A) +`define ETH_PHY_ADDR 5'h01 + +// LED/Configuration pins on PHY device - see the specification, page 26, table 8 +// Initial set of bits 13, 12 and 8 of Control Register +`define LED_CFG1 1'b0 +`define LED_CFG2 1'b0 +`define LED_CFG3 1'b1 + +// Supported speeds and physical ports - see the specification, page 67, table 41 +// Set bits 15 to 9 of Status Register +`define SUPPORTED_SPEED_AND_PORT 7'h3F + +// Extended status register (address 15) +// Set bit 8 of Status Register +`define EXTENDED_STATUS 1'b0 + +// Default status bits - see the specification, page 67, table 41 +// Set bits 6 to 0 of Status Register +`define DEFAULT_STATUS 7'h09 + +// PHY ID 1 number - see the specification, page 68, table 42 +// Set bits of Phy Id Register 1 +`define PHY_ID1 16'h0013 + +// PHY ID 2 number - see the specification, page 68, table 43 +// Set bits 15 to 10 of Phy Id Register 2 +`define PHY_ID2 6'h1E + +// Manufacturer MODEL number - see the specification, page 68, table 43 +// Set bits 9 to 4 of Phy Id Register 2 +`define MAN_MODEL_NUM 6'h0E + +// Manufacturer REVISION number - see the specification, page 68, table 43 +// Set bits 3 to 0 of Phy Id Register 2 +`define MAN_REVISION_NUM 4'h2 + + + + diff --git a/tb/vtb/gen_dffr.v b/tb/vtb/gen_dffr.v new file mode 100644 index 0000000..9b7c189 --- /dev/null +++ b/tb/vtb/gen_dffr.v @@ -0,0 +1,57 @@ + + +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +`timescale 1 ns / 1 ps + +module gen_dffr # ( + parameter DW = 32, + parameter rstValue = {DW{1'b0}} +) +( + + input [DW-1:0] dnxt, + output [DW-1:0] qout, + + input CLK, + input RSTn +); + +reg [DW-1:0] qout_r; + +always @(posedge CLK or negedge RSTn) begin + if ( ~RSTn ) + qout_r <= #1 rstValue; + else + qout_r <= #1 dnxt; +end + +assign qout = qout_r; + +endmodule + + + + + + + + + + + + diff --git a/tb/vtb/gen_dffren.v b/tb/vtb/gen_dffren.v new file mode 100644 index 0000000..3278ae3 --- /dev/null +++ b/tb/vtb/gen_dffren.v @@ -0,0 +1,62 @@ + + + +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +`timescale 1 ns / 1 ps + + +module gen_dffren # ( + parameter DW = 32, + parameter rstValue = {DW{1'b0}} +) +( + + input [DW-1:0] dnxt, + output [DW-1:0] qout, + input en, + + input CLK, + input RSTn +); + + + +wire [DW-1:0] dffren_dnxt; +wire [DW-1:0] dffren_qout; + + +gen_dffr # ( .DW(DW), .rstValue(rstValue) ) dffren +( + .dnxt(dffren_dnxt), + .qout(dffren_qout), + + .CLK(CLK), + .RSTn(RSTn) +); + + +assign dffren_dnxt = en ? dnxt : dffren_qout; +assign qout = dffren_qout; + + +endmodule + + + + + diff --git a/tb/vtb/gen_dpdffren.v b/tb/vtb/gen_dpdffren.v new file mode 100644 index 0000000..2d6549b --- /dev/null +++ b/tb/vtb/gen_dpdffren.v @@ -0,0 +1,69 @@ + + +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + + + +`timescale 1 ns / 1 ps + + +module gen_dpdffren #( + parameter DW = 32, + parameter rstValue = {DW{1'b0}} +) +( + + input [DW-1:0] dnxta, + input ena, + + input [DW-1:0] dnxtb, + input enb, + + output [DW-1:0] qout, + + input CLK, + input RSTn +); + +wire en; +wire [DW-1:0] dnxt; + + + +assign en = ena | enb; +assign dnxt = {DW{ena}} & dnxta + | + {DW{(~ena)&enb}} & dnxtb; + + +gen_dffren # ( .DW(DW), .rstValue(rstValue) ) dffren +( + + .dnxt(dnxt), + .qout(qout), + .en(en), + + .CLK(CLK), + .RSTn(RSTn) +); + + + + +endmodule + + diff --git a/tb/vtb/gen_rsffr.v b/tb/vtb/gen_rsffr.v new file mode 100644 index 0000000..0f958be --- /dev/null +++ b/tb/vtb/gen_rsffr.v @@ -0,0 +1,70 @@ + + +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +`timescale 1 ns / 1 ps + +module gen_rsffr # ( + parameter DW = 1, + parameter rstValue = {DW{1'b0}} +) +( + + input [DW-1:0] set_in, + input [DW-1:0] rst_in, + + output [DW-1:0] qout, + + input CLK, + input RSTn +); + +reg [DW-1:0] qout_r; + +generate + for ( genvar i = 0; i < DW; i = i + 1 ) begin + + always @(posedge CLK or negedge RSTn) begin + if ( ~RSTn ) begin + qout_r[i] <= #1 rstValue[i]; + end + else begin + qout_r[i] <= #1 qout_r[i]; + if ( set_in[i] ) begin + qout_r[i] <= #1 1'b1; + end + if ( rst_in[i] ) begin + qout_r[i] <= #1 1'b0; + end + end + end + end +endgenerate + +assign qout = qout_r; + +endmodule + + + + + + + + + + diff --git a/tb/vtb/gen_slffr.v b/tb/vtb/gen_slffr.v new file mode 100644 index 0000000..91898bc --- /dev/null +++ b/tb/vtb/gen_slffr.v @@ -0,0 +1,54 @@ + + + + +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +`timescale 1 ns / 1 ps + +module gen_slffr # ( + parameter DW = 1, + parameter rstValue = 1'b0 +) +( + + input [DW-1:0] set_in, + input [DW-1:0] rst_in, + + output [DW-1:0] qout, + + input CLK, + input RSTn +); + + +wire [DW-1:0] rsffr_qout; +gen_rsffr # ( .DW(DW), .rstValue(rstValue)) rsffr ( .set_in(set_in), .rst_in(rst_in), .qout(rsffr_qout), .CLK(CLK), .RSTn(RSTn)); + + +assign qout = set_in | rsffr_qout; + +//ASSERT +always @( posedge CLK ) begin + if ( set_in & rst_in ) begin + $display("Assert Fail at gen_slff"); + $finish; + end +end + +endmodule + diff --git a/tb/vtb/gen_sram.v b/tb/vtb/gen_sram.v new file mode 100644 index 0000000..96f567d --- /dev/null +++ b/tb/vtb/gen_sram.v @@ -0,0 +1,97 @@ + + + + +/* + Copyright (c) 2020 - 2023 Wuhan University of Technology <295054118@whut.edu.cn> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +`timescale 1 ns / 1 ps + + + +module gen_sram # +( + parameter DW = 32, + parameter AW = 14 +) +( + + input [DW-1:0] data_w, + input [AW-1:0] addr_w, + input [(DW+7)/8-1:0] data_wstrb, + input en_w, + + + output [DW-1:0] data_r, + input [AW-1:0] addr_r, + input en_r, + + input CLK + +); + + localparam DP = 2**AW; + localparam DW_ZM = (DW+7)/8*8; + + reg [DW_ZM-1:0] ram[0:DP-1]; + reg [DW_ZM-1:0] data_r_reg; + wire [DW_ZM-1:0] data_w_zmask = {DW_ZM{1'b0}} | data_w; + + + generate + for ( genvar i = 0; i < (DW+7)/8; i = i + 1) begin + always @(posedge CLK) begin + if (en_w) begin + if (data_wstrb[i]) begin + ram[addr_w][i*8+:8] <= #1 data_w_zmask[i*8+:8] ; + end + end + + if (en_r) begin + data_r_reg[i*8+:8] <= #1 ram[addr_r][i*8+:8]; + end + end + + + end + endgenerate + + assign data_r = data_r_reg[DW-1:0]; + + +// integer i; +// initial begin +// for ( i = 0; i < DP; i = i + 1 ) begin +// ram[i] = {((DW+31)/32){$random}}; +// end + +// data_r_reg = {((DW+31)/32){$random}}; +// end + + +endmodule + + + + + + + + + + + + diff --git a/tb/vtb/tb_eth_defines.v b/tb/vtb/tb_eth_defines.v new file mode 100644 index 0000000..e974b77 --- /dev/null +++ b/tb/vtb/tb_eth_defines.v @@ -0,0 +1,212 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// tb_eth_defines.v //// +//// //// +//// This file is part of the Ethernet IP core project //// +//// http://www.opencores.org/project,ethmac //// +//// //// +//// Author(s): //// +//// - Igor Mohor (igorM@opencores.org) //// +//// //// +//// All additional information is available in the Readme.txt //// +//// file. //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001, 2002 Authors //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +// +// CVS Revision History +// +// $Log: not supported by cvs2svn $ +// Revision 1.10 2002/11/19 20:27:46 mohor +// Temp version. +// +// Revision 1.9 2002/10/09 13:16:51 tadejm +// Just back-up; not completed testbench and some testcases are not +// wotking properly yet. +// +// Revision 1.8 2002/09/13 18:41:45 mohor +// Rearanged testcases +// +// Revision 1.7 2002/09/13 12:29:14 mohor +// Headers changed. +// +// Revision 1.6 2002/09/13 11:57:20 mohor +// New testbench. Thanks to Tadej M - "The Spammer". +// +// Revision 1.3 2002/07/19 13:57:53 mohor +// Testing environment also includes traffic cop, memory interface and host +// interface. +// +// Revision 1.2 2002/05/03 10:22:17 mohor +// TX_BUF_BASE changed. +// +// Revision 1.1 2002/03/19 12:53:54 mohor +// Some defines that are used in testbench only were moved to tb_eth_defines.v +// file. +// +// +// +// + + + +//`define VERBOSE // if log files of device modules are written + +`define MULTICAST_XFR 0 +`define UNICAST_XFR 1 +`define BROADCAST_XFR 2 +`define UNICAST_WRONG_XFR 3 + +`define ETH_BASE 32'hd0000000 +`define ETH_WIDTH 32'h800 +`define MEMORY_BASE 32'h2000 +`define MEMORY_WIDTH 32'h10000 +`define TX_BUF_BASE `MEMORY_BASE +`define RX_BUF_BASE `MEMORY_BASE + 32'h8000 +`define TX_BD_BASE `ETH_BASE + 32'h00000400 +`define RX_BD_BASE `ETH_BASE + 32'h00000600 + +/* Tx BD */ +`define ETH_TX_BD_READY 32'h8000 /* Tx BD Ready */ +`define ETH_TX_BD_IRQ 32'h4000 /* Tx BD IRQ Enable */ +`define ETH_TX_BD_WRAP 32'h2000 /* Tx BD Wrap (last BD) */ +`define ETH_TX_BD_PAD 32'h1000 /* Tx BD Pad Enable */ +`define ETH_TX_BD_CRC 32'h0800 /* Tx BD CRC Enable */ + +`define ETH_TX_BD_UNDERRUN 32'h0100 /* Tx BD Underrun Status */ +`define ETH_TX_BD_RETRY 32'h00F0 /* Tx BD Retry Status */ +`define ETH_TX_BD_RETLIM 32'h0008 /* Tx BD Retransmission Limit Status */ +`define ETH_TX_BD_LATECOL 32'h0004 /* Tx BD Late Collision Status */ +`define ETH_TX_BD_DEFER 32'h0002 /* Tx BD Defer Status */ +`define ETH_TX_BD_CARRIER 32'h0001 /* Tx BD Carrier Sense Lost Status */ + +/* Rx BD */ +`define ETH_RX_BD_EMPTY 32'h8000 /* Rx BD Empty */ +`define ETH_RX_BD_IRQ 32'h4000 /* Rx BD IRQ Enable */ +`define ETH_RX_BD_WRAP 32'h2000 /* Rx BD Wrap (last BD) */ + +`define ETH_RX_BD_MISS 32'h0080 /* Rx BD Miss Status */ +`define ETH_RX_BD_OVERRUN 32'h0040 /* Rx BD Overrun Status */ +`define ETH_RX_BD_INVSIMB 32'h0020 /* Rx BD Invalid Symbol Status */ +`define ETH_RX_BD_DRIBBLE 32'h0010 /* Rx BD Dribble Nibble Status */ +`define ETH_RX_BD_TOOLONG 32'h0008 /* Rx BD Too Long Status */ +`define ETH_RX_BD_SHORT 32'h0004 /* Rx BD Too Short Frame Status */ +`define ETH_RX_BD_CRCERR 32'h0002 /* Rx BD CRC Error Status */ +`define ETH_RX_BD_LATECOL 32'h0001 /* Rx BD Late Collision Status */ + + + +/* Register space */ +`define ETH_MODER `ETH_BASE + 32'h00 /* Mode Register */ +`define ETH_INT `ETH_BASE + 32'h04 /* Interrupt Source Register */ +`define ETH_INT_MASK `ETH_BASE + 32'h08 /* Interrupt Mask Register */ +`define ETH_IPGT `ETH_BASE + 32'h0C /* Back to Bak Inter Packet Gap Register */ +`define ETH_IPGR1 `ETH_BASE + 32'h10 /* Non Back to Back Inter Packet Gap Register 1 */ +`define ETH_IPGR2 `ETH_BASE + 32'h14 /* Non Back to Back Inter Packet Gap Register 2 */ +`define ETH_PACKETLEN `ETH_BASE + 32'h18 /* Packet Length Register (min. and max.) */ +`define ETH_COLLCONF `ETH_BASE + 32'h1C /* Collision and Retry Configuration Register */ +`define ETH_TX_BD_NUM `ETH_BASE + 32'h20 /* Transmit Buffer Descriptor Number Register */ +`define ETH_CTRLMODER `ETH_BASE + 32'h24 /* Control Module Mode Register */ +`define ETH_MIIMODER `ETH_BASE + 32'h28 /* MII Mode Register */ +`define ETH_MIICOMMAND `ETH_BASE + 32'h2C /* MII Command Register */ +`define ETH_MIIADDRESS `ETH_BASE + 32'h30 /* MII Address Register */ +`define ETH_MIITX_DATA `ETH_BASE + 32'h34 /* MII Transmit Data Register */ +`define ETH_MIIRX_DATA `ETH_BASE + 32'h38 /* MII Receive Data Register */ +`define ETH_MIISTATUS `ETH_BASE + 32'h3C /* MII Status Register */ +`define ETH_MAC_ADDR0 `ETH_BASE + 32'h40 /* MAC Individual Address Register 0 */ +`define ETH_MAC_ADDR1 `ETH_BASE + 32'h44 /* MAC Individual Address Register 1 */ +`define ETH_HASH_ADDR0 `ETH_BASE + 32'h48 /* Hash Register 0 */ +`define ETH_HASH_ADDR1 `ETH_BASE + 32'h4C /* Hash Register 1 */ +`define ETH_TX_CTRL `ETH_BASE + 32'h50 /* Tx Control Register */ + + +/* MODER Register */ +`define ETH_MODER_RXEN 32'h00000001 /* Receive Enable */ +`define ETH_MODER_TXEN 32'h00000002 /* Transmit Enable */ +`define ETH_MODER_NOPRE 32'h00000004 /* No Preamble */ +`define ETH_MODER_BRO 32'h00000008 /* Reject Broadcast */ +`define ETH_MODER_IAM 32'h00000010 /* Use Individual Hash */ +`define ETH_MODER_PRO 32'h00000020 /* Promiscuous (receive all) */ +`define ETH_MODER_IFG 32'h00000040 /* Min. IFG not required */ +`define ETH_MODER_LOOPBCK 32'h00000080 /* Loop Back */ +`define ETH_MODER_NOBCKOF 32'h00000100 /* No Backoff */ +`define ETH_MODER_EXDFREN 32'h00000200 /* Excess Defer */ +`define ETH_MODER_FULLD 32'h00000400 /* Full Duplex */ +`define ETH_MODER_RST 32'h00000800 /* Reset MAC */ +`define ETH_MODER_DLYCRCEN 32'h00001000 /* Delayed CRC Enable */ +`define ETH_MODER_CRCEN 32'h00002000 /* CRC Enable */ +`define ETH_MODER_HUGEN 32'h00004000 /* Huge Enable */ +`define ETH_MODER_PAD 32'h00008000 /* Pad Enable */ +`define ETH_MODER_RECSMALL 32'h00010000 /* Receive Small */ + +/* Interrupt Source Register */ +`define ETH_INT_TXB 32'h00000001 /* Transmit Buffer IRQ */ +`define ETH_INT_TXE 32'h00000002 /* Transmit Error IRQ */ +`define ETH_INT_RXB 32'h00000004 /* Receive Buffer IRQ */ +`define ETH_INT_RXE 32'h00000008 /* Receive Error IRQ */ +`define ETH_INT_BUSY 32'h00000010 /* Busy IRQ */ +`define ETH_INT_TXC 32'h00000020 /* Transmit Control Frame IRQ */ +`define ETH_INT_RXC 32'h00000040 /* Received Control Frame IRQ */ + +/* Interrupt Mask Register */ +`define ETH_INT_MASK_TXB 32'h00000001 /* Transmit Buffer IRQ Mask */ +`define ETH_INT_MASK_TXE 32'h00000002 /* Transmit Error IRQ Mask */ +`define ETH_INT_MASK_RXF 32'h00000004 /* Receive Frame IRQ Mask */ +`define ETH_INT_MASK_RXE 32'h00000008 /* Receive Error IRQ Mask */ +`define ETH_INT_MASK_BUSY 32'h00000010 /* Busy IRQ Mask */ +`define ETH_INT_MASK_TXC 32'h00000020 /* Transmit Control Frame IRQ Mask */ +`define ETH_INT_MASK_RXC 32'h00000040 /* Received Control Frame IRQ Mask */ + +/* Control Module Mode Register */ +`define ETH_CTRLMODER_PASSALL 32'h00000001 /* Pass Control Frames */ +`define ETH_CTRLMODER_RXFLOW 32'h00000002 /* Receive Control Flow Enable */ +`define ETH_CTRLMODER_TXFLOW 32'h00000004 /* Transmit Control Flow Enable */ + +/* MII Mode Register */ +`define ETH_MIIMODER_CLKDIV 32'h000000FF /* Clock Divider */ +`define ETH_MIIMODER_NOPRE 32'h00000100 /* No Preamble */ +`define ETH_MIIMODER_RST 32'h00000200 /* MIIM Reset */ + +/* MII Command Register */ +`define ETH_MIICOMMAND_SCANSTAT 32'h00000001 /* Scan Status */ +`define ETH_MIICOMMAND_RSTAT 32'h00000002 /* Read Status */ +`define ETH_MIICOMMAND_WCTRLDATA 32'h00000004 /* Write Control Data */ + +/* MII Address Register */ +`define ETH_MIIADDRESS_FIAD 32'h0000001F /* PHY Address */ +`define ETH_MIIADDRESS_RGAD 32'h00001F00 /* RGAD Address */ + +/* MII Status Register */ +`define ETH_MIISTATUS_LINKFAIL 0 /* Link Fail bit */ +`define ETH_MIISTATUS_BUSY 1 /* MII Busy bit */ +`define ETH_MIISTATUS_NVALID 2 /* Data in MII Status Register is invalid bit */ + +/* TX Control Register */ +`define ETH_TX_CTRL_TXPAUSERQ 32'h10000 /* Send PAUSE request */ + + +`define TIME $display(" Time: %0t", $time)