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

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 43 to Rev 44
    Reverse comparison

Rev 43 → Rev 44

/openrisc/trunk/orpsocv2/bench/sysc/include/Or1200MonitorSC.h
5,6 → 5,7
// Copyright (C) 2008 Embecosm Limited <info@embecosm.com>
 
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
// Contributor Julius Baxter <jb@orsoc.se>
 
// This file is part of the cycle accurate model of the OpenRISC 1000 based
// system-on-chip, ORPSoC, built using Verilator.
29,6 → 30,9
#ifndef OR1200_MONITOR_SC__H
#define OR1200_MONITOR_SC__H
 
#include <fstream>
#include <ctime>
 
#include "systemc.h"
 
#include "OrpsocAccess.h"
52,11 → 56,18
// Method to check instructions
void checkInstruction();
 
// Methods to setup and output state of processor to a file
void init_displayState(int argc,char *argv[]);
void displayState();
 
// The ports
sc_in<bool> clk;
 
private:
 
// Function to calculate performance of the sim
void perfSummary();
 
// Special NOP instructions
static const uint32_t NOP_NOP = 0x15000000; //!< Normal nop instruction
static const uint32_t NOP_EXIT = 0x15000001; //!< End of simulation
64,6 → 75,15
static const uint32_t NOP_PRINTF = 0x15000003; //!< Simprintf instruction
static const uint32_t NOP_PUTC = 0x15000004; //!< Putc instruction
 
// Variables for processor status output
ofstream statusFile;
int logging_enabled;
int exit_perf_summary_enabled;
int insn_count;
// Time measurement variables - for calculating performance of the sim
clock_t start;
 
//! The accessor for the Orpsoc instance
OrpsocAccess *accessor;
 
/openrisc/trunk/orpsocv2/bench/sysc/include/OrpsocAccess.h
35,6 → 35,8
class Vorpsoc_top;
class Vorpsoc_top_orpsoc_top;
class Vorpsoc_top_or1200_ctrl;
class Vorpsoc_top_or1200_except;
class Vorpsoc_top_or1200_sprs;
class Vorpsoc_top_or1200_dpram;
 
 
53,13 → 55,24
// Accessor functions
bool getWbFreeze ();
uint32_t getWbInsn ();
uint32_t getWbPC ();
bool getExceptFlushpipe ();
bool getExDslot ();
// Get a specific GPR from the register file
uint32_t getGpr (uint32_t regNum);
//SPR accessessors
uint32_t getSprSr ();
uint32_t getSprEpcr ();
uint32_t getSprEear ();
uint32_t getSprEsr ();
 
private:
 
// Pointers to modules with accessor functions
Vorpsoc_top_or1200_ctrl *or1200_ctrl;
Vorpsoc_top_or1200_dpram *rf_a;
Vorpsoc_top_or1200_ctrl *or1200_ctrl;
Vorpsoc_top_or1200_except *or1200_except;
Vorpsoc_top_or1200_sprs *or1200_sprs;
Vorpsoc_top_or1200_dpram *rf_a;
 
}; // OrpsocAccess ()
 
/openrisc/trunk/orpsocv2/bench/sysc/src/Or1200MonitorSC.cpp
5,6 → 5,7
// Copyright (C) 2008 Embecosm Limited <info@embecosm.com>
 
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
// Contributor Julius Baxter <jb@orsoc.se>
 
// This file is part of the cycle accurate model of the OpenRISC 1000 based
// system-on-chip, ORPSoC, built using Verilator.
28,8 → 29,12
 
#include <iostream>
#include <iomanip>
#include <fstream>
 
using namespace std;
 
#include "Or1200MonitorSC.h"
#include "OrpsocMain.h"
 
 
SC_HAS_PROCESS( Or1200MonitorSC );
47,6 → 52,14
SC_METHOD (checkInstruction);
sensitive << clk.pos();
dont_initialize();
 
SC_METHOD (displayState);
logging_enabled = 0; // Default is logging disabled
exit_perf_summary_enabled = 1; // Simulation exit performance summary is on by default. Turn off with "-q" on the cmd line
sensitive << clk.pos();
dont_initialize();
 
start = clock();
} // Or1200MonitorSC ()
 
78,6 → 91,8
ts = sc_time_stamp().to_seconds() * 1000000000.0;
std::cout << std::fixed << std::setprecision (2) << ts;
std::cout << " ns: Exiting (" << r3 << ")" << std::endl;
if (exit_perf_summary_enabled) perfSummary();
if (logging_enabled != 0) statusFile.close();
sc_stop();
break;
 
106,3 → 121,120
 
} // checkInstruction()
 
//! Method to setup the files for outputting the state of the processor
 
//! This function will setup the output file, if enabled.
 
void
Or1200MonitorSC::init_displayState(int argc, char *argv[])
{
 
string logfileDefault("vlt-executed.log");
string logfileNameString;
 
// Parse the command line options
int cmdline_name_found=0;
if (argc > 1)
{
// Search through the command line parameters for the "-log" option
for(int i=1; i < argc; i++)
{
if (strcmp(argv[i], "-log")==0)
{
logfileNameString = (argv[i+1]);
cmdline_name_found=1;
break;
}
}
// Search through the command line parameters for the "-q","--no-perf-summary" option
for(int i=1; i < argc; i++)
{
if ((strcmp(argv[i], "-q")==0)||(strcmp(argv[i], "--no-perf-summary")==0))
{
exit_perf_summary_enabled = 0;
break;
}
}
 
}
 
if(cmdline_name_found==0) // No -log option specified so don't turn on logging
return;
 
statusFile.open(logfileNameString.c_str(), ios::out ); // open file to write to it
 
if(statusFile.is_open())
{
// If we could open the file then turn on logging
logging_enabled = 1;
cout << "Processor execution logged to file: " << logfileNameString << endl;
}
 
return;
 
}
 
//! Method to output the state of the processor
 
//! This function will output to a file, if enabled, the status of the processor
//! For now, it's just the PPC and instruction.
 
void
Or1200MonitorSC::displayState()
{
uint32_t wbinsn;
// Calculate how many instructions we've actually calculated by ignoring cycles where we're frozen, delay slots and flushpipe cycles
if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
// Increment instruction counter
insn_count++;
 
if (logging_enabled == 0)
return; // If we didn't inialise a file, then just return.
 
// Output the state if we're not frozen and not flushing during a delay slot
if ((!accessor->getWbFreeze()) && !(accessor->getExceptFlushpipe() && accessor->getExDslot()))
{
// Print PC, instruction
statusFile << "\nEXECUTED("<< std::setfill(' ') << std::setw(11) << dec << insn_count << "): " << std::setfill('0') << hex << std::setw(8) << accessor->getWbPC() << ": " << hex << accessor->getWbInsn() << endl;
 
// Print general purpose register contents
for (int i=0; i<32; i++)
{
if ((i%4 == 0)&&(i>0)) statusFile << endl;
statusFile << std::setfill('0');
statusFile << "GPR" << dec << std::setw(2) << i << ": " << hex << std::setw(8) << (uint32_t) accessor->getGpr(i) << " ";
}
statusFile << endl;
 
statusFile << "SR : " << hex << std::setw(8) << (uint32_t) accessor->getSprSr() << " ";
statusFile << "EPCR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEpcr() << " ";
statusFile << "EEAR0: " << hex << std::setw(8) << (uint32_t) accessor->getSprEear() << " ";
statusFile << "ESR0 : " << hex << std::setw(8) << (uint32_t) accessor->getSprEsr() << endl;
 
}
 
return;
 
} // displayState()
 
//! Function to calculate the number of instructions performed and the time taken
void
Or1200MonitorSC::perfSummary()
{
double ts;
ts = sc_time_stamp().to_seconds() * 1000000000.0;
int cycles = ts / (BENCH_CLK_HALFPERIOD*2); // Number of clock cycles we had
 
clock_t finish = clock();
double elapsed_time = (double(finish)-double(start))/CLOCKS_PER_SEC;
// It took elapsed_time seconds to do insn_count instructions. Divide insn_count by the time to get instructions/second.
double ips = (insn_count/elapsed_time);
double mips = (insn_count/elapsed_time)/1000000;
std::cout << "Or1200Monitor: real time elapsed: " << elapsed_time << " seconds" << endl;
std::cout << "Or1200Monitor: simulated " << dec << cycles << " clock cycles, executed " << insn_count << " instructions" << endl;
std::cout << "Or1200Monitor: simulated insn/sec = " << ips << ", simulator mips = " << mips << endl;
return;
} // calculateMips()
 
/openrisc/trunk/orpsocv2/bench/sysc/src/TraceSC.cpp
49,18 → 49,27
 
// Setup the name of the VCD dump file
string dumpNameDefault("vlt-dump.vcd");
string dumpSuffix("-vlt.vcd");
string dumpDir("../results/"); // Note: hardcoded to store all VCDs in the ../results dir
string testNameString;
string vcdDumpFile;
if (argc > 1) // If we were passed a name on the command line, use it
 
// Search through the command line parameters for the "-vcd" option
int cmdline_name_found=0;
if (argc > 1)
{
for(int i=1; i<argc; i++)
{
testNameString = (argv[1]);
vcdDumpFile = dumpDir + testNameString + dumpSuffix;
if (strcmp(argv[i], "-vcd")==0)
{
testNameString = (argv[i+1]);
vcdDumpFile = testNameString;
cmdline_name_found=1;
break;
}
}
else // otherwise use our default VCD dump file name
vcdDumpFile = dumpDir + dumpNameDefault;
}
 
if(cmdline_name_found==0) // otherwise use our default VCD dump file name
vcdDumpFile = dumpNameDefault;
Verilated::traceEverOn (true);
/openrisc/trunk/orpsocv2/bench/sysc/src/OrpsocAccess.cpp
5,6 → 5,7
// Copyright (C) 2008 Embecosm Limited <info@embecosm.com>
 
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
// Contributor Julius Baxter <jb@orsoc.se>
 
// This file is part of the cycle accurate model of the OpenRISC 1000 based
// system-on-chip, ORPSoC, built using Verilator.
34,6 → 35,8
#include "Vorpsoc_top_or1200_top.h"
#include "Vorpsoc_top_or1200_cpu.h"
#include "Vorpsoc_top_or1200_ctrl.h"
#include "Vorpsoc_top_or1200_except.h"
#include "Vorpsoc_top_or1200_sprs.h"
#include "Vorpsoc_top_or1200_rf.h"
#include "Vorpsoc_top_or1200_dpram.h"
 
47,6 → 50,8
OrpsocAccess::OrpsocAccess (Vorpsoc_top *orpsoc_top)
{
or1200_ctrl = orpsoc_top->v->i_or1k->i_or1200_top->or1200_cpu->or1200_ctrl;
or1200_except = orpsoc_top->v->i_or1k->i_or1200_top->or1200_cpu->or1200_except;
or1200_sprs = orpsoc_top->v->i_or1k->i_or1200_top->or1200_cpu->or1200_sprs;
rf_a = orpsoc_top->v->i_or1k->i_or1200_top->or1200_cpu->or1200_rf->rf_a;
 
} // OrpsocAccess ()
63,7 → 68,39
 
} // getWbFreeze ()
 
//! Access for the except_flushpipe signal
 
//! @return The value of the or1200_except.except_flushpipe signal
 
bool
OrpsocAccess::getExceptFlushpipe ()
{
return or1200_except->except_flushpipe;
 
} // getExceptFlushpipe ()
 
//! Access for the ex_dslot signal
 
//! @return The value of the or1200_except.ex_dslot signalfac
 
bool
OrpsocAccess::getExDslot ()
{
return or1200_except->ex_dslot;
 
} // getExDslot ()
 
//! Access for the wb_pc register
 
//! @return The value of the or1200_except.wb_insn register
 
uint32_t
OrpsocAccess::getWbPC ()
{
return (or1200_except->get_wb_pc) ();
 
} // getWbPC ()
 
//! Access for the wb_insn register
 
//! @return The value of the or1200_ctrl.wb_insn register
90,3 → 127,49
return (rf_a->get_gpr) (regNum);
 
} // getGpr ()
 
 
//! Access for the sr register
 
//! @return The value of the or1200_sprs.sr register
 
uint32_t
OrpsocAccess::getSprSr ()
{
return (or1200_sprs->get_sr) ();
 
} // getSprSr ()
 
//! Access for the epcr register
 
//! @return The value of the or1200_sprs.epcr register
 
uint32_t
OrpsocAccess::getSprEpcr ()
{
return (or1200_sprs->get_epcr) ();
 
} // getSprEpcr ()
 
//! Access for the eear register
 
//! @return The value of the or1200_sprs.eear register
 
uint32_t
OrpsocAccess::getSprEear ()
{
return (or1200_sprs->get_eear) ();
 
} // getSprEear ()
 
//! Access for the esr register
 
//! @return The value of the or1200_sprs.esr register
 
uint32_t
OrpsocAccess::getSprEsr ()
{
return (or1200_sprs->get_esr) ();
 
} // getSprEsr ()
 
/openrisc/trunk/orpsocv2/bench/sysc/src/OrpsocMain.cpp
160,6 → 160,9
// Init the UART function
uart->initUart(25000000, 115200);
 
// Turn on logging by setting the "-log logfilename" option on the command line
monitor->init_displayState(argc, argv);
 
// Execute until we stop
sc_start ();
 
/openrisc/trunk/orpsocv2/bench/verilog/eth_stim.v
0,0 → 1,625
//////////////////////////////////////////////////////////////////////
//// ////
//// ORPSoC Testbench - Ethernet MAC Stimulus ////
//// ////
//// Description ////
//// Ethernet MAC stimulus tasks. Taken from the project ////
//// testbench in the ethmac core. ////
//// ////
//// To Do: ////
//// ////
//// ////
//// Author(s): ////
//// - Tadej Markovic, tadej@opencores.org ////
//// - Igor Mohor, igorM@opencores.org ////
//// - jb, jb@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
 
reg [15:0] rx_packet_length;
reg [7:0] st_data;
parameter Tp = 1;
initial
begin
 
repeat(30000) @(posedge eth_clk);
rx_packet_length = 16'd96; // Bytes
st_data = 8'h0F;
set_rx_packet(0, rx_packet_length, 1'b0, 48'h0012_3456_789a, 48'h0708_090A_0B0C, 16'h0D0E, st_data); // length without CRC
set_rx_addr_type(0, 48'h0102_0304_0506, 48'h0708_090A_0B0C, 16'h0D0E);
append_rx_crc(0, rx_packet_length, 1'b0, 1'b0);
 
// write to phy's control register for 10Mbps
#Tp eth_phy0.control_bit14_10 = 5'b00000; // bit 13 reset - speed 10
#Tp eth_phy0.control_bit8_0 = 9'h1_00; // bit 6 reset - (10/100), bit 8 set - FD
//#Tp eth_phy0.carrier_sense_tx_fd_detect(1); // Full duplex CRS detect normally off
 
/*
from eth_phy.v:
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
*/
#100000 eth_phy0.send_rx_packet(64'h0055_5555_5555_5555, 4'h7, 8'hD5, 0, rx_packet_length, 1'b0);
 
/* TODO: Some checking here that the packet's contents actually ended up in RAM correctly */
end
/*
TASKS for set and check RX packets:
-----------------------------------
set_rx_packet
(rxpnt[31:0], len[15:0], plus_nibble, d_addr[47:0], s_addr[47:0], type_len[15:0], start_data[7:0]);
check_rx_packet
(rxpnt_phy[31:0], rxpnt_wb[31:0], len[15:0], plus_nibble, successful_nibble, failure[31:0]);
*/
task set_rx_packet;
input [31:0] rxpnt; // pointer to place in in the phy rx buffer we'll start at
input [15:0] len;
input plus_dribble_nibble; // if length is longer for one nibble
input [47:0] eth_dest_addr;
input [47:0] eth_source_addr;
input [15:0] eth_type_len;
input [7:0] eth_start_data;
integer i, sd;
reg [47:0] dest_addr;
reg [47:0] source_addr;
reg [15:0] type_len;
reg [21:0] buffer;
reg delta_t;
begin
buffer = rxpnt[21:0];
dest_addr = eth_dest_addr;
source_addr = eth_source_addr;
type_len = eth_type_len;
sd = eth_start_data;
delta_t = 0;
for(i = 0; i < len; i = i + 1)
begin
if (i < 6)
begin
eth_phy0.rx_mem[buffer] = dest_addr[47:40];
dest_addr = dest_addr << 8;
end
else if (i < 12)
begin
eth_phy0.rx_mem[buffer] = source_addr[47:40];
source_addr = source_addr << 8;
end
else if (i < 14)
begin
eth_phy0.rx_mem[buffer] = type_len[15:8];
type_len = type_len << 8;
end
else
begin
eth_phy0.rx_mem[buffer] = sd[7:0];
sd = sd + 1;
end
buffer = buffer + 1;
end
delta_t = !delta_t;
if (plus_dribble_nibble)
eth_phy0.rx_mem[buffer] = {4'h0, 4'hD /*sd[3:0]*/};
delta_t = !delta_t;
end
endtask // set_rx_packet
 
 
 
 
task set_rx_addr_type;
input [31:0] rxpnt;
input [47:0] eth_dest_addr;
input [47:0] eth_source_addr;
input [15:0] eth_type_len;
integer i;
reg [47:0] dest_addr;
reg [47:0] source_addr;
reg [15:0] type_len;
reg [21:0] buffer;
reg delta_t;
begin
buffer = rxpnt[21:0];
dest_addr = eth_dest_addr;
source_addr = eth_source_addr;
type_len = eth_type_len;
delta_t = 0;
for(i = 0; i < 14; i = i + 1)
begin
if (i < 6)
begin
eth_phy0.rx_mem[buffer] = dest_addr[47:40];
dest_addr = dest_addr << 8;
end
else if (i < 12)
begin
eth_phy0.rx_mem[buffer] = source_addr[47:40];
source_addr = source_addr << 8;
end
else // if (i < 14)
begin
eth_phy0.rx_mem[buffer] = type_len[15:8];
type_len = type_len << 8;
end
buffer = buffer + 1;
end
delta_t = !delta_t;
end
endtask // set_rx_addr_type
 
/*
task check_rx_packet;
input [31:0] rxpnt_phy; // source
input [31:0] rxpnt_wb; // destination
input [15:0] len;
input plus_dribble_nibble; // if length is longer for one nibble
input successful_dribble_nibble; // if additional nibble is stored into memory
output [31:0] failure;
integer i, data_wb, data_phy;
reg [31:0] addr_wb, addr_phy;
reg [31:0] failure;
reg [21:0] buffer;
reg delta_t;
begin
addr_phy = rxpnt_phy;
addr_wb = rxpnt_wb;
delta_t = 0;
failure = 0;
 
// First write might not be word allign.
if(addr_wb[1:0] == 1)
begin
wb_slave.rd_mem(addr_wb[21:0] - 1, data_wb, 4'h7);
data_phy[31:24] = 0;
data_phy[23:16] = eth_phy0.rx_mem[addr_phy[21:0]];
data_phy[15: 8] = eth_phy0.rx_mem[addr_phy[21:0] + 1];
data_phy[ 7: 0] = eth_phy0.rx_mem[addr_phy[21:0] + 2];
i = 3;
if (data_phy[23:0] !== data_wb[23:0])
begin
//`TIME;
//$display(" addr_phy = %h, addr_wb = %h", rxpnt_phy, rxpnt_wb);
//$display("*E Wrong 1. word (3 bytes) of RX packet! phy = %h, wb = %h", data_phy[23:0], data_wb[23:0]);
failure = 1;
end
end
else if (addr_wb[1:0] == 2)
begin
wb_slave.rd_mem(addr_wb[21:0] - 2, data_wb, 4'h3);
data_phy[31:16] = 0;
data_phy[15: 8] = eth_phy0.rx_mem[addr_phy[21:0]];
data_phy[ 7: 0] = eth_phy0.rx_mem[addr_phy[21:0] + 1];
i = 2;
if (data_phy[15:0] !== data_wb[15:0])
begin
//`TIME;
//$display(" addr_phy = %h, addr_wb = %h", rxpnt_phy, rxpnt_wb);
//$display("*E Wrong 1. word (2 bytes) of RX packet! phy = %h, wb = %h", data_phy[15:0], data_wb[15:0]);
failure = 1;
end
end
else if (addr_wb[1:0] == 3)
begin
wb_slave.rd_mem(addr_wb[21:0] - 3, data_wb, 4'h1);
data_phy[31: 8] = 0;
data_phy[ 7: 0] = eth_phy0.rx_mem[addr_phy[21:0]];
i = 1;
if (data_phy[7:0] !== data_wb[7:0])
begin
//`TIME;
//$display(" addr_phy = %h, addr_wb = %h", rxpnt_phy, rxpnt_wb);
//$display("*E Wrong 1. word (1 byte) of RX packet! phy = %h, wb = %h", data_phy[7:0], data_wb[7:0]);
failure = 1;
end
end
else
i = 0;
delta_t = !delta_t;
 
for(i = i; i < (len - 4); i = i + 4) // Last 0-3 bytes are not checked
begin
wb_slave.rd_mem(addr_wb[21:0] + i, data_wb, 4'hF);
data_phy[31:24] = eth_phy0.rx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy0.rx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy0.rx_mem[addr_phy[21:0] + i + 2];
data_phy[ 7: 0] = eth_phy0.rx_mem[addr_phy[21:0] + i + 3];
if (data_phy[31:0] !== data_wb[31:0])
begin
//`TIME;
//if (i == 0)
// $display(" addr_phy = %h, addr_wb = %h", rxpnt_phy, rxpnt_wb);
//$display("*E Wrong %0d. word (4 bytes) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:0], data_wb[31:0]);
failure = failure + 1;
end
end
delta_t = !delta_t;
 
// Last word
if((len - i) == 3)
begin
wb_slave.rd_mem(addr_wb[21:0] + i, data_wb, 4'hF);
data_phy[31:24] = eth_phy0.rx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy0.rx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy0.rx_mem[addr_phy[21:0] + i + 2];
if (plus_dribble_nibble)
data_phy[ 7: 0] = eth_phy0.rx_mem[addr_phy[21:0] + i + 3];
else
data_phy[ 7: 0] = 0;
if (data_phy[31:8] !== data_wb[31:8])
begin
//`TIME;
//$display("*E Wrong %0d. word (3 bytes) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:8], data_wb[31:8]);
failure = failure + 1;
end
if (plus_dribble_nibble && successful_dribble_nibble)
begin
if (data_phy[3:0] !== data_wb[3:0])
begin
//`TIME;
//$display("*E Wrong dribble nibble in %0d. word (3 bytes) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
else if (plus_dribble_nibble && !successful_dribble_nibble)
begin
if (data_phy[3:0] === data_wb[3:0])
begin
//`TIME;
//$display("*E Wrong dribble nibble in %0d. word (3 bytes) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
end
else if((len - i) == 2)
begin
wb_slave.rd_mem(addr_wb[21:0] + i, data_wb, 4'hE);
data_phy[31:24] = eth_phy0.rx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy0.rx_mem[addr_phy[21:0] + i + 1];
if (plus_dribble_nibble)
data_phy[15: 8] = eth_phy0.rx_mem[addr_phy[21:0] + i + 2];
else
data_phy[15: 8] = 0;
data_phy[ 7: 0] = 0;
if (data_phy[31:16] !== data_wb[31:16])
begin
//`TIME;
//$display("*E Wrong %0d. word (2 bytes) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:16], data_wb[31:16]);
failure = failure + 1;
end
if (plus_dribble_nibble && successful_dribble_nibble)
begin
if (data_phy[11:8] !== data_wb[11:8])
begin
//`TIME;
//$display("*E Wrong dribble nibble in %0d. word (2 bytes) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
else if (plus_dribble_nibble && !successful_dribble_nibble)
begin
if (data_phy[11:8] === data_wb[11:8])
begin
//`TIME;
//$display("*E Wrong dribble nibble in %0d. word (2 bytes) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
end
else if((len - i) == 1)
begin
wb_slave.rd_mem(addr_wb[21:0] + i, data_wb, 4'hC);
data_phy[31:24] = eth_phy0.rx_mem[addr_phy[21:0] + i];
if (plus_dribble_nibble)
data_phy[23:16] = eth_phy0.rx_mem[addr_phy[21:0] + i + 1];
else
data_phy[23:16] = 0;
data_phy[15: 8] = 0;
data_phy[ 7: 0] = 0;
if (data_phy[31:24] !== data_wb[31:24])
begin
//`TIME;
//$display("*E Wrong %0d. word (1 byte) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:24], data_wb[31:24]);
failure = failure + 1;
end
if (plus_dribble_nibble && successful_dribble_nibble)
begin
if (data_phy[19:16] !== data_wb[19:16])
begin
//`TIME;
//$display("*E Wrong dribble nibble in %0d. word (1 byte) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
else if (plus_dribble_nibble && !successful_dribble_nibble)
begin
if (data_phy[19:16] === data_wb[19:16])
begin
//`TIME;
//$display("*E Wrong dribble nibble in %0d. word (1 byte) of RX packet!", ((i/4)+1));
failure = failure + 1;
end
end
end
else if((len - i) == 4)
begin
wb_slave.rd_mem(addr_wb[21:0] + i, data_wb, 4'hF);
data_phy[31:24] = eth_phy0.rx_mem[addr_phy[21:0] + i];
data_phy[23:16] = eth_phy0.rx_mem[addr_phy[21:0] + i + 1];
data_phy[15: 8] = eth_phy0.rx_mem[addr_phy[21:0] + i + 2];
data_phy[ 7: 0] = eth_phy0.rx_mem[addr_phy[21:0] + i + 3];
if (data_phy[31:0] !== data_wb[31:0])
begin
//`TIME;
//$display("*E Wrong %0d. word (4 bytes) of RX packet! phy = %h, wb = %h", ((i/4)+1), data_phy[31:0], data_wb[31:0]);
failure = failure + 1;
end
if (plus_dribble_nibble)
begin
wb_slave.rd_mem(addr_wb[21:0] + i + 4, data_wb, 4'h8);
data_phy[31:24] = eth_phy0.rx_mem[addr_phy[21:0] + i + 4];
if (successful_dribble_nibble)
begin
if (data_phy[27:24] !== data_wb[27:24])
begin
//`TIME;
//$display("*E Wrong dribble nibble in %0d. word (0 bytes) of RX packet!", ((i/4)+2));
failure = failure + 1;
end
end
else
begin
if (data_phy[27:24] === data_wb[27:24])
begin
//`TIME;
//$display("*E Wrong dribble nibble in %0d. word (0 bytes) of RX packet!", ((i/4)+2));
failure = failure + 1;
end
end
end
end
else
$display("(%0t)(%m) ERROR", $time);
delta_t = !delta_t;
end
endtask // check_rx_packet
*/
//////////////////////////////////////////////////////////////
// Ethernet CRC Basic tasks
//////////////////////////////////////////////////////////////
 
task append_rx_crc;
input [31:0] rxpnt_phy; // source
input [15:0] len; // length in bytes without CRC
input plus_dribble_nibble; // if length is longer for one nibble
input negated_crc; // if appended CRC is correct or not
reg [31:0] crc;
reg [7:0] tmp;
reg [31:0] addr_phy;
reg delta_t;
begin
addr_phy = rxpnt_phy + len;
delta_t = 0;
// calculate CRC from prepared packet
paralel_crc_phy_rx(rxpnt_phy, {16'h0, len}, plus_dribble_nibble, crc);
if (negated_crc)
crc = ~crc;
delta_t = !delta_t;
 
if (plus_dribble_nibble)
begin
tmp = eth_phy0.rx_mem[addr_phy];
eth_phy0.rx_mem[addr_phy] = {crc[27:24], tmp[3:0]};
eth_phy0.rx_mem[addr_phy + 1] = {crc[19:16], crc[31:28]};
eth_phy0.rx_mem[addr_phy + 2] = {crc[11:8], crc[23:20]};
eth_phy0.rx_mem[addr_phy + 3] = {crc[3:0], crc[15:12]};
eth_phy0.rx_mem[addr_phy + 4] = {4'h0, crc[7:4]};
end
else
begin
eth_phy0.rx_mem[addr_phy] = crc[31:24];
eth_phy0.rx_mem[addr_phy + 1] = crc[23:16];
eth_phy0.rx_mem[addr_phy + 2] = crc[15:8];
eth_phy0.rx_mem[addr_phy + 3] = crc[7:0];
end
end
endtask // append_rx_crc
 
task append_rx_crc_delayed;
input [31:0] rxpnt_phy; // source
input [15:0] len; // length in bytes without CRC
input plus_dribble_nibble; // if length is longer for one nibble
input negated_crc; // if appended CRC is correct or not
reg [31:0] crc;
reg [7:0] tmp;
reg [31:0] addr_phy;
reg delta_t;
begin
addr_phy = rxpnt_phy + len;
delta_t = 0;
// calculate CRC from prepared packet
paralel_crc_phy_rx(rxpnt_phy+4, {16'h0, len}-4, plus_dribble_nibble, crc);
if (negated_crc)
crc = ~crc;
delta_t = !delta_t;
 
if (plus_dribble_nibble)
begin
tmp = eth_phy0.rx_mem[addr_phy];
eth_phy0.rx_mem[addr_phy] = {crc[27:24], tmp[3:0]};
eth_phy0.rx_mem[addr_phy + 1] = {crc[19:16], crc[31:28]};
eth_phy0.rx_mem[addr_phy + 2] = {crc[11:8], crc[23:20]};
eth_phy0.rx_mem[addr_phy + 3] = {crc[3:0], crc[15:12]};
eth_phy0.rx_mem[addr_phy + 4] = {4'h0, crc[7:4]};
end
else
begin
eth_phy0.rx_mem[addr_phy] = crc[31:24];
eth_phy0.rx_mem[addr_phy + 1] = crc[23:16];
eth_phy0.rx_mem[addr_phy + 2] = crc[15:8];
eth_phy0.rx_mem[addr_phy + 3] = crc[7:0];
end
end
endtask // append_rx_crc_delayed
 
 
// paralel CRC calculating for PHY RX
task paralel_crc_phy_rx;
input [31:0] start_addr; // start address
input [31:0] len; // length of frame in Bytes without CRC length
input plus_dribble_nibble; // if length is longer for one nibble
output [31:0] crc_out;
reg [21:0] addr_cnt; // only 22 address lines
integer word_cnt;
integer nibble_cnt;
reg [31:0] load_reg;
reg delta_t;
reg [31:0] crc_next;
reg [31:0] crc;
reg crc_error;
reg [3:0] data_in;
integer i;
begin
#1 addr_cnt = start_addr[21:0];
word_cnt = 24; // 27; // start of the frame - nibble granularity (MSbit first)
crc = 32'hFFFF_FFFF; // INITIAL value
delta_t = 0;
// length must include 4 bytes of ZEROs, to generate CRC
// get number of nibbles from Byte length (2^1 = 2)
if (plus_dribble_nibble)
nibble_cnt = ((len + 4) << 1) + 1'b1; // one nibble longer
else
nibble_cnt = ((len + 4) << 1);
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
while (nibble_cnt > 0)
begin
// wait for delta time
delta_t = !delta_t;
// shift data in
 
if(nibble_cnt <= 8) // for additional 8 nibbles shift ZEROs in!
data_in[3:0] = 4'h0;
else
 
data_in[3:0] = {load_reg[word_cnt], load_reg[word_cnt+1], load_reg[word_cnt+2], load_reg[word_cnt+3]};
crc_next[0] = (data_in[0] ^ crc[28]);
crc_next[1] = (data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29]);
crc_next[2] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]);
crc_next[3] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]);
crc_next[4] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[0];
crc_next[5] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[1];
crc_next[6] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[ 2];
crc_next[7] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[3];
crc_next[8] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[4];
crc_next[9] = (data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30]) ^ crc[5];
crc_next[10] = (data_in[3] ^ data_in[2] ^ data_in[0] ^ crc[28] ^ crc[30] ^ crc[31]) ^ crc[6];
crc_next[11] = (data_in[3] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[31]) ^ crc[7];
crc_next[12] = (data_in[2] ^ data_in[1] ^ data_in[0] ^ crc[28] ^ crc[29] ^ crc[30]) ^ crc[8];
crc_next[13] = (data_in[3] ^ data_in[2] ^ data_in[1] ^ crc[29] ^ crc[30] ^ crc[31]) ^ crc[9];
crc_next[14] = (data_in[3] ^ data_in[2] ^ crc[30] ^ crc[31]) ^ crc[10];
crc_next[15] = (data_in[3] ^ crc[31]) ^ crc[11];
crc_next[16] = (data_in[0] ^ crc[28]) ^ crc[12];
crc_next[17] = (data_in[1] ^ crc[29]) ^ crc[13];
crc_next[18] = (data_in[2] ^ crc[30]) ^ crc[14];
crc_next[19] = (data_in[3] ^ crc[31]) ^ crc[15];
crc_next[20] = crc[16];
crc_next[21] = crc[17];
crc_next[22] = (data_in[0] ^ crc[28]) ^ crc[18];
crc_next[23] = (data_in[1] ^ data_in[0] ^ crc[29] ^ crc[28]) ^ crc[19];
crc_next[24] = (data_in[2] ^ data_in[1] ^ crc[30] ^ crc[29]) ^ crc[20];
crc_next[25] = (data_in[3] ^ data_in[2] ^ crc[31] ^ crc[30]) ^ crc[21];
crc_next[26] = (data_in[3] ^ data_in[0] ^ crc[31] ^ crc[28]) ^ crc[22];
crc_next[27] = (data_in[1] ^ crc[29]) ^ crc[23];
crc_next[28] = (data_in[2] ^ crc[30]) ^ crc[24];
crc_next[29] = (data_in[3] ^ crc[31]) ^ crc[25];
crc_next[30] = crc[26];
crc_next[31] = crc[27];
 
crc = crc_next;
crc_error = crc[31:0] != 32'hc704dd7b; // CRC not equal to magic number
case (nibble_cnt)
9: crc_out = {!crc[24], !crc[25], !crc[26], !crc[27], !crc[28], !crc[29], !crc[30], !crc[31],
!crc[16], !crc[17], !crc[18], !crc[19], !crc[20], !crc[21], !crc[22], !crc[23],
!crc[ 8], !crc[ 9], !crc[10], !crc[11], !crc[12], !crc[13], !crc[14], !crc[15],
!crc[ 0], !crc[ 1], !crc[ 2], !crc[ 3], !crc[ 4], !crc[ 5], !crc[ 6], !crc[ 7]};
default: crc_out = crc_out;
endcase
// wait for delta time
delta_t = !delta_t;
// increment address and load new data
if ((word_cnt+3) == 7)//4)
begin
// because of MAGIC NUMBER nibbles are swapped [3:0] -> [0:3]
load_reg[31:24] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[23:16] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[15: 8] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
load_reg[ 7: 0] = eth_phy0.rx_mem[addr_cnt];
addr_cnt = addr_cnt + 1;
end
// set new load bit position
if((word_cnt+3) == 31)
word_cnt = 16;
else if ((word_cnt+3) == 23)
word_cnt = 8;
else if ((word_cnt+3) == 15)
word_cnt = 0;
else if ((word_cnt+3) == 7)
word_cnt = 24;
else
word_cnt = word_cnt + 4;// - 4;
// decrement nibble counter
nibble_cnt = nibble_cnt - 1;
// wait for delta time
delta_t = !delta_t;
end // while
#1;
end
endtask // paralel_crc_phy_rx
/openrisc/trunk/orpsocv2/bench/verilog/eth_phy_defines.v
0,0 → 1,91
//////////////////////////////////////////////////////////////////////
//// ////
//// File name: eth_phy_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/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'h00 //Changed to 0 -jb
 
// 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
 
 
 
 
/openrisc/trunk/orpsocv2/bench/verilog/eth_phy.v
0,0 → 1,1481
//////////////////////////////////////////////////////////////////////
//// ////
//// File name: eth_phy.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/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 "timescale.v"
`include "eth_phy_defines.v"
 
// ORPSoCv2 testbench include
// Will enable verbose if eth test
`ifdef TEST_DEFINE_FILE
`include "test_define.v"
`endif
 
 
`define MULTICAST_XFR 0
`define UNICAST_XFR 1
`define BROADCAST_XFR 2
`define UNICAST_WRONG_XFR 3
 
 
//`define ETH_PHY_VERBOSE 1
 
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,
speed_o,
link_o,
duplex_o
);
 
//////////////////////////////////////////////////////////////////////
//
// 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;
// Sideband signals for SMII -- jb
output link_o;
output speed_o;
output duplex_o;
 
//////////////////////////////////////////////////////////////////////
//
// 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 ETH_PHY_VERBOSE
#1 $display( " (%0t)(%m)MAC RX clock is %f MHz while ethernet link is down!",
$time, (1000/(rx_link_down_halfperiod*2)) );
`endif
end
end
 
`ifdef ETH_PHY_VERBOSE
always@(status_bit6_0[2])
begin
if (!status_bit6_0[2]) // Link is down
#1 $display( " (%0t)(%m)Ethernet link is down!", $time);
else
#1 $display( " (%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 ETH_PHY_VERBOSE
always@(eth_speed)
begin
if (eth_speed)
#1 $display( " (%0t)(%m)PHY configured to 100 Mbps!", $time);
else
#1 $display( " (%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
// DIFFERENT mrx_clk than mtx_clk
/* mrx_clk_diff_than_mtx = 1;
#3;
forever
begin
if (status_bit6_0[2]) // Link is UP
begin
if (eth_speed) // 100 Mbps - 25 MHz, 40 ns
begin
//#(((1/0.025001)/2))
#19.99 mrx_clk_diff_than_mtx = ~mrx_clk_diff_than_mtx; // period is calculated from frequency in GHz
end
else // 10 Mbps - 2.5 MHz, 400 ns
begin
//#(((1/0.0024999)/2))
#200.01 mrx_clk_diff_than_mtx = ~mrx_clk_diff_than_mtx; // period is calculated from frequency in GHz
end
end
else // Link is down
begin
#(rx_link_down_halfperiod) mrx_clk_diff_than_mtx = ~mrx_clk_diff_than_mtx; // random frequency between 2 MHz and 40 MHz
end
end*/
// // set output mrx_clk
// if (set_mrx_equal_mtx)
// mrx_clk_o = mrx_clk_equal_to_mtx;
// else
// mrx_clk_o = mrx_clk_diff_than_mtx;
end
 
// set output mrx_clk
//assign mrx_clk_o = set_mrx_equal_mtx ? mrx_clk_equal_to_mtx : mrx_clk_diff_than_mtx ;
 
//////////////////////////////////////////////////////////////////////
//
// 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 #1 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 <= #1 0;
else
md_io_reg <= #1 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 #1 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 ETH_PHY_VERBOSE
$display( "*E (%0t)(%m)MIIM - wrong first start bit (without preamble)", $time);
`endif
#10 $stop;
end
end
end
else // with preamble
begin
#4 ;
`ifdef ETH_PHY_VERBOSE
$display( " (%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 ETH_PHY_VERBOSE
$display( "*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 ETH_PHY_VERBOSE
if (no_preamble)
$display( "*E (%0t)(%m)MIIM - wrong second start bit (without preamble)", $time);
else
$display( "*E (%0t)(%m)MIIM - wrong second start bit", $time);
`endif
#10 $stop;
end
else
begin
`ifdef ETH_PHY_VERBOSE
if (no_preamble)
#1 $display( " (%0t)(%m)MIIM - 2 start bits received (without preamble)", $time);
else
#1 $display( " (%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 ETH_PHY_VERBOSE
$display( " (%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 ETH_PHY_VERBOSE
$display( " (%0t)(%m)MIIM - op-code for WRITING to registers", $time);
`endif
end
else
begin
// ERROR - wrong opcode !
`ifdef ETH_PHY_VERBOSE
#1 $display( "*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 ETH_PHY_VERBOSE
#1 $display( "*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 ETH_PHY_VERBOSE
$display( " (%0t)(%m)MIIM - received correct PHY ADDRESS: %x", $time, phy_address);
`endif
end
else
begin
`ifdef ETH_PHY_VERBOSE
#1 $display( "*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 ETH_PHY_VERBOSE
#1 $display( "*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 ETH_PHY_VERBOSE
#1 $display( "*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 ETH_PHY_VERBOSE
$display( " (%0t)(%m)MIIM - received correct PHY ADDRESS: %x", $time, phy_address);
$display( " (%0t)(%m)MIIM - WRITING to register %x COMPLETED!", $time, reg_address);
`endif
end
else
begin
`ifdef ETH_PHY_VERBOSE
#1 $display( "*W (%0t)(%m)MIIM - received different PHY ADDRESS: %x", $time, phy_address);
$display( "*W (%0t)(%m)MIIM - NO WRITING to register %x !", $time, reg_address);
`endif
end
end
else // read
begin
`ifdef ETH_PHY_VERBOSE
if ((phy_address === `ETH_PHY_ADDR) || respond_to_all_phy_addr) // check the PHY address
#1 $display( " (%0t)(%m)MIIM - READING from register %x COMPLETED!",
$time, reg_address);
else
#1 $display( "*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 ETH_PHY_VERBOSE
if (mcrs_rx && mcrs_tx)
$display( " (%0t)(%m) Collision set in FullDuplex!", $time);
if (task_mcoll)
$display( " (%0t)(%m) Collision set in FullDuplex from TASK!", $time);
`endif
end
else
begin
mcoll_o = task_mcoll;
`ifdef ETH_PHY_VERBOSE
if (task_mcoll)
$display( " (%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 ETH_PHY_VERBOSE
if (mcrs_rx && mcrs_tx)
$display( " (%0t)(%m) Collision set in HalfDuplex!", $time);
if (task_mcoll)
$display( " (%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 ETH_PHY_VERBOSE
$display( " (%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 ETH_PHY_VERBOSE
if (tx_preamble_ok == 1)
$display( " (%0t)(%m) TX frame preamble OK!", $time);
else
$display( "*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 ETH_PHY_VERBOSE
if (tx_sfd_ok == 1)
$display( " (%0t)(%m) TX frame SFD OK!", $time);
else
$display( "*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 ETH_PHY_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
$display( " (%0t)(%m) TX frame ended with tx_en reset!", $time);
frame_started <= 0;
end
end
 
always@(posedge mrxerr_o)
begin
$display( " (%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 ETH_PHY_VERBOSE
$display( " (%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 ETH_PHY_VERBOSE
$display( " (%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 ETH_PHY_VERBOSE
$display( " (%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 ETH_PHY_VERBOSE
$display( " (%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
#1 no_preamble = test_op;
md_transfer_cnt_reset = 1'b1;
@(posedge mdc_i);
#1 md_transfer_cnt_reset = 1'b0;
end
endtask
 
 
 
// Sideband signals for external SMII converter --jb
assign link_o = status_bit6_0[2];
assign speed_o = eth_speed;
assign duplex_o = control_bit8_0[8];
 
 
 
 
endmodule
 
/openrisc/trunk/orpsocv2/bench/verilog/orpsoc_testbench_defines.v
43,6 → 43,11
`define CLOCK_PERIOD 40
`define CLOCK_RATE 25000000
 
// Period for 125MHz clock is 8ns
`define ETH_CLK_PERIOD 8
 
 
// The ORPSoC tests makefile should generate the test_define.v file in
// the sim/run directory.
`ifdef TEST_DEFINE_FILE
/openrisc/trunk/orpsocv2/bench/verilog/smii_phy.v
0,0 → 1,468
//////////////////////////////////////////////////////////////////////
//// ////
//// SMII Receiver/Decoder (usually at PHY end) ////
//// ////
//// Description ////
//// Low pin count serial MII ethernet interface ////
//// ////
//// To Do: ////
//// - ////
//// ////
//// Author(s): ////
//// - Michael Unneback, unneback@opencores.org ////
//// ORSoC AB michael.unneback@orsoc.se ////
//// - Julius Baxter, jb@orsoc.se ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
module smii_phy
(
// SMII
input smii_tx,
input smii_sync,
output smii_rx,
// MII
// TX
/* ALL I/Os swapped compared to SMII on MAC end MAC - jb */
output reg [3:0] ethphy_mii_tx_d,
output reg ethphy_mii_tx_en,
output reg ethphy_mii_tx_err,
input ethphy_mii_tx_clk,
// RX
input [3:0] ethphy_mii_rx_d,
input ethphy_mii_rx_dv,
input ethphy_mii_rx_err,
input ethphy_mii_rx_clk,
input ethphy_mii_mcoll,
input ethphy_mii_crs,
 
input fast_ethernet,
input duplex,
input link,
 
// internal
//input [10:1] state,
// clock and reset
input clk, /* Global reference clock for both SMII modules */
input rst_n
);
 
reg [3:0] rx_tmp;
reg jabber = 0;
 
reg mtx_clk_tmp, mrx_clk_tmp;
 
reg [3:0] tx_cnt;
reg [3:0] rx_cnt;
 
/**************************************************************************/
/* Counters */
/**************************************************************************/
 
/* Generate the state counter, based on incoming sync signal */
/* 10-bit shift register, indicating where we are */
reg [10:1] state_shiftreg;
 
always @(posedge clk)
begin
if (!rst_n)
begin
state_shiftreg <= 10'b0000000001;
end
else
begin
if (smii_sync) /* sync signal from MAC */
state_shiftreg <= 10'b0000000010;
else if (state_shiftreg[10])
state_shiftreg <= 10'b0000000001;
else
state_shiftreg[10:2] <= state_shiftreg[9:1];
end // else: !if(!rst_n)
end // always @ (posedge clk)
/* counter from 0 to 9, counting the 10-bit segments we'll transmit
via SMII*/
reg [3:0] segment_ctr;
 
always @(posedge clk)
begin
if(!rst_n)
segment_ctr <= 4'h0;
else
begin
if(fast_ethernet) /* If using 100Mbs, then each segment is
different, we don't count the repeats */
segment_ctr <= 4'h0;
else if (state_shiftreg[10])
if (segment_ctr == 4'h9) /* Wrap */
segment_ctr <= 4'h0;
else /* Increment */
segment_ctr <= segment_ctr + 1'b1;
end
end
/**************************************************************************/
/* RX path logic PHY->(MII->SMII)->MAC */
/**************************************************************************/
 
reg rx_nibble_sel, rx_byte_valid;
reg [7:0] rx_data_byte_rx_clk;
 
/* Receive the RX data from the PHY and serialise it */
/* If RX data valid goes high, then it's the beginning of a
proper data segment*/
always @(posedge ethphy_mii_rx_clk or negedge rst_n)
begin
if(!rst_n)
begin
rx_nibble_sel <= 0; /* start with low nibble receiving */
rx_data_byte_rx_clk <= 0;
rx_byte_valid <= 0;
end
else
begin
/* Half way through, and at the end of each 10-bit section
and whenever we should load a new segment (each time for
fast ethernet, else once every 10 times; whenever segment_ctr
is 0)*/
//if ((state_shiftreg[6] | state_shiftreg[10]) & (segment_ctr==4'h0))
// begin
/* Alternate the nibble we're selecting when RX_dv */
if(!ethphy_mii_rx_dv) /* data on rx line is not valid */
rx_nibble_sel <= 0;
else
rx_nibble_sel <= ~rx_nibble_sel;
 
if (!ethphy_mii_rx_dv & !rx_nibble_sel)
rx_byte_valid <= 0;
else if (rx_nibble_sel) /* sampled high nibble, byte OK*/
rx_byte_valid <= 1;
if (ethphy_mii_rx_dv & !rx_nibble_sel)
/* Sampling low nibble */
rx_data_byte_rx_clk[3:0] <= ethphy_mii_rx_d;
else if (ethphy_mii_rx_dv & rx_nibble_sel)
/* Sample high nibble */
rx_data_byte_rx_clk[7:4] <= ethphy_mii_rx_d;
//end // if ((state_shiftreg[4] | state_shiftreg[9]) & (segment_ctr==4'h0))
end // else: !if(!rst_n)
end // always @ (posedge clk)'
 
/* SMII domain RX signals */
reg [7:0] rx_data_byte;
reg rx_line_rx_dv; /* Reg for second bit of SMII RX sequence, RX_DV */
 
/* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */
wire [7:0] state_shiftreg_top_byte;
assign state_shiftreg_top_byte[7:0] = state_shiftreg[10:3];
/* Move RX's DV and data into SMII clk domain */
always @(posedge clk)
begin
if(!rst_n)
begin
rx_line_rx_dv <= 0;
end
else
begin
/* When we're at the beginning of a new 10-bit sequence and
the beginning of the 10-segment loop load the valid bit */
if(state_shiftreg[1] & (segment_ctr==4'h0))
begin
rx_line_rx_dv <= rx_byte_valid;
rx_data_byte <= rx_data_byte_rx_clk;
end
end // else: !if(!rst_n)
end // always @ (posedge clk)
/* Assign the rx line out */
assign smii_rx = state_shiftreg[1] ? ethphy_mii_crs : /* 1st bit is MII CRS */
/* next is RX_DV bit */
state_shiftreg[2] ? ((rx_byte_valid & (segment_ctr==4'h0)) |
rx_line_rx_dv) :
/* Depending on RX_DV, output the status byte or data byte */
rx_line_rx_dv ? |(state_shiftreg_top_byte & rx_data_byte) :
/* Output status byte */
|(state_shiftreg_top_byte &
/* Status seq.: CRS, DV, ER, Speed, Duplex, Link, Jabber, UPV, FCD, 1 */
{1'b1,1'b0,1'b1,jabber,link,duplex,fast_ethernet,ethphy_mii_rx_err});
 
/**************************************************************************/
/* TX path logic MAC->(SMII->MII)->PHY */
/**************************************************************************/
 
/* We ignore the data when TX_EN bit is not high -
it's only used in MAC to MAC comms*/
 
 
/* Register the sequence appropriately as it comes in */
reg tx_er_seqbit_scratch;
reg tx_en_seqbit_scratch;
reg [7:0] tx_data_byte_scratch;
 
reg [1:0] tx_byte_to_phy; /* PHY sourced TX_CLK domain */
wire tx_fifo_empty;
wire tx_fifo_full;
wire [7:0] tx_fifo_q_dat;
wire tx_fifo_q_err;
reg tx_fifo_pop;
 
/* Signal to tell us an appropriate time to copy the values out of the
temp regs we put the incoming TX line into when we've received a
sequence off the SMII TX line that has TX_EN high */
wire tx_seqbits_copy;
assign tx_seqbits_copy = ((((!fast_ethernet) & (segment_ctr==4'h1)) |
((fast_ethernet) & (state_shiftreg[1])))
& tx_en_seqbit_scratch);
 
always @(posedge clk)
begin
if (!rst_n)
begin
tx_er_seqbit_scratch <= 0;
tx_en_seqbit_scratch <= 0;
tx_data_byte_scratch <= 0;
end
else
begin
if (segment_ctr==4'h0)
begin
if(state_shiftreg[1])
tx_er_seqbit_scratch <= smii_tx;
if(state_shiftreg[2])
tx_en_seqbit_scratch <= smii_tx;
/* Preserve all but current bit of interest, as indicated
by state vector bit (reversed, becuase we get MSbit
first) and OR in the current smii_tx line value at this
position*/
if((|state_shiftreg[10:3]) & tx_en_seqbit_scratch)
tx_data_byte_scratch <= (tx_data_byte_scratch & ~state_shiftreg_top_byte) |
({8{smii_tx}} & state_shiftreg_top_byte);
end // if (segment_ctr==4'h0)
 
/* If we've just received a sequence with TX_EN then put
these values in the proper regs at the appropriate time,
depending on the speed , ready for transmission to the PHY */
if (tx_seqbits_copy)
begin
/* Now clear the tx_en scratch bit so we don't do
this again */
tx_en_seqbit_scratch <= 0;
end // if (tx_seqbits_copy)
end
end // always @ (posedge clk)
 
 
/* In the event we have a valid byte frame then get it to the
PHY as quickly as possible - this is TX_CLK domain */
always @(posedge ethphy_mii_tx_clk or negedge rst_n)
begin
if(!rst_n)
begin
tx_byte_to_phy <= 0;
tx_fifo_pop <= 1'b0;
/* Output MII registers to the PHY */
ethphy_mii_tx_d <= 0;
ethphy_mii_tx_en <= 0;
ethphy_mii_tx_err <= 0;
end
else
begin
if(!tx_fifo_empty) /* A byte ready to go to the MAC */
begin
if(tx_byte_to_phy == 2'b00)
begin
/* Pop */
tx_fifo_pop <= 1;
tx_byte_to_phy <= 2'b01;
end
end
 
/* FIFO control loop */
if (tx_byte_to_phy == 2'b01) /* Output bits 3-0 (bottom nibble ) */
begin
ethphy_mii_tx_d <= tx_fifo_q_dat[3:0];
ethphy_mii_tx_en <= 1;
ethphy_mii_tx_err <= tx_fifo_q_err;
tx_fifo_pop <= 0;
tx_byte_to_phy <= 2'b10;
end
else if (tx_byte_to_phy == 2'b10) /* Output bits 7-4 (top nibble) */
begin
ethphy_mii_tx_d <= tx_fifo_q_dat[7:4];
if(!tx_fifo_empty) /* Check if more in FIFO */
begin
tx_fifo_pop <= 1; /* Pop again */
tx_byte_to_phy <= 2'b01;
end
else /* Finish up */
begin
tx_byte_to_phy <= 2'b11;
end
end
else if (tx_byte_to_phy == 2'b11) /* De-assert TX_EN */
begin
ethphy_mii_tx_en <= 0;
tx_byte_to_phy <= 2'b00;
end
end // else: !if(!rst_n)
end // always @ (posedge ethphy_mii_tx_clk or negedge rst_n)
 
/* A fifo, storing TX bytes coming from the SMII interface */
generic_fifo #(9, 64) tx_fifo
(
// Outputs
.psh_full (tx_fifo_full),
.pop_q ({tx_fifo_q_err,tx_fifo_q_dat}),
.pop_empty (tx_fifo_empty),
// Inputs
.async_rst_n (rst_n),
.psh_clk (clk),
.psh_we (tx_seqbits_copy),
.psh_d ({tx_er_seqbit_scratch,tx_data_byte_scratch}),
.pop_clk (),
.pop_re (tx_fifo_pop));
//assign mcoll = mcrs & mtxen;
endmodule // smii_top
 
 
 
/* Generic fifo - this is bad, should probably be done some other way */
module generic_fifo (async_rst_n, psh_clk, psh_we, psh_d, psh_full, pop_clk, pop_re, pop_q, pop_empty);
 
parameter dw = 8;
parameter size = 64;
 
/* Asynch. reset, active low */
input async_rst_n;
/* Push side signals */
input psh_clk;
input psh_we;
input [dw-1:0] psh_d;
output psh_full;
/* Pop side signals */
input pop_clk;
input pop_re;
output reg [dw-1:0] pop_q;
output pop_empty;
/* Actual FIFO memory */
reg [dw-1:0] fifo_mem [0:size-1];
 
/* Poorly defined pointer logic -- will need to be changed if the size paramter is too big - Verilog needs some log base 2 thing */
reg [7:0] ptr; /* Only 8 bits, so max size of 255 of fifo! */
 
 
/* FIFO full signal for push side */
assign psh_full = (ptr == size-1) ? 1 : 0;
/* FIFO empty signal for pop side */
assign pop_empty = (ptr == 0) ? 1 : 0;
 
/* This will work if pushing side is a lot faster than popping side */
reg pop_re_psh_clk;
wire pop_re_risingedge_psh_clk; /* Signal to help push side see when
there's been a pop_re rising edge,
sampled on push clock */
 
/* Detect edge of signal in pop domain for psh domain */
assign pop_re_risingedge_psh_clk = (pop_re & !pop_re_psh_clk);
 
 
integer i;
always @(posedge psh_clk or negedge async_rst_n)
begin
if (!async_rst_n)
begin
ptr <= 0;
 
 
for (i=0;i<size;i=i+1) fifo_mem[i] <= 0;
 
pop_re_psh_clk <= 0;
end
else
begin
pop_re_psh_clk <= pop_re; /* Register pop command in psh domain */
if (psh_we) /* Push into FIFO */
begin
if (!pop_re_psh_clk) /* If no pop at the same time, simple */
begin
fifo_mem[ptr] <= psh_d;
ptr <= ptr + 1'b1;
end
else /* Pop at same edge */
begin
/* Shift fifo contents */
for(i=1;i<size;i=i+1)
fifo_mem[i-1] <= fifo_mem[i];
fifo_mem[size-1] <= 0;
pop_q <= fifo_mem[0];
fifo_mem[ptr] <= psh_d;
/* ptr remains unchanged */
end // else: !if!(pop_re_psh_clk)
end // if (psh_we)
else /* No push, see if there's a pop */
begin
if (pop_re_risingedge_psh_clk) /* Detected a pop */
begin
for(i=1;i<size;i=i+1)
fifo_mem[i-1] <= fifo_mem[i];
fifo_mem[size-1] <= 0;
pop_q <= fifo_mem[0];
ptr <= ptr - 1'b1;
end
end // else: !if(psh_we)
end // else: !if(!async_rst_n)
end // always @ (posedge psh_clk or negedge async_rst_n)
endmodule // generic_fifo
 
/openrisc/trunk/orpsocv2/bench/verilog/orpsoc_testbench.v
149,9 → 149,9
`ifdef USE_ETHERNET
// Ethernet ports
.eth_md_pad_io (eth_md_io[1:1]),
.eth_mdc_pad_o (eth_mdc_o[1:1]),
.eth_sync_pad_o (eth_sync_o[1:1]),
.eth_tx_pad_o (eth_tx_o[1:1]),
.eth_mdc_pad_o (eth_mdc_o[1:1]),
.eth_rx_pad_i (eth_rx_i[1:1]),
.eth_clk_pad_i (eth_clk_i),
`endif // `ifdef USE_ETHERNET
225,7 → 225,90
 
`endif // !`ifdef USE_SDRAM
 
`ifdef USE_ETHERNET
 
reg eth_clk;
initial
eth_clk <= 0;
 
always
#(8/2) eth_clk <= ~eth_clk; // 125 Mhz clock
 
assign eth_clk_i = eth_clk;
wire [3:0] ethphy_mii_tx_d;
wire ethphy_mii_tx_en;
wire ethphy_mii_tx_err;
wire mcoll_o;
wire mcrs_o;
wire md_io;
wire mrx_clk_o;
wire [3:0] mrxd_o;
wire mrxdv_o;
wire mrxerr_o;
wire mtx_clk_o;
wire smii_rx;
wire fast_ethernet, duplex, link;
 
/* Converts SMII back to MII */
smii_phy smii_phyend
(
// Outputs
.smii_rx (eth_rx_i[1:1]), /* SMII RX */
.ethphy_mii_tx_d (ethphy_mii_tx_d[3:0]), /* MII TX */
.ethphy_mii_tx_en (ethphy_mii_tx_en), /* MII TX */
.ethphy_mii_tx_err (ethphy_mii_tx_err), /* MII TX */
// Inputs
.smii_tx (eth_tx_o[1:1]), /* SMII TX */
.smii_sync (eth_sync_o[1:1]), /* SMII SYNC */
.ethphy_mii_tx_clk (mtx_clk_o), /* MII TX */
.ethphy_mii_rx_d (mrxd_o[3:0]), /* MII RX */
.ethphy_mii_rx_dv (mrxdv_o), /* MII RX */
.ethphy_mii_rx_err (mrxerr_o), /* MII RX */
.ethphy_mii_rx_clk (mrx_clk_o), /* MII RX */
.ethphy_mii_mcoll (),
.ethphy_mii_crs (mcrs_o),
.fast_ethernet (fast_ethernet),
.duplex (duplex),
.link (link),
.clk (eth_clk_i),
.rst_n (rst_i));
 
`ifdef ENABLE_ETH_STIM
/* Generates an RX packet */
`include "eth_stim.v"
`endif
 
eth_phy eth_phy0
(
// Outputs
.mtx_clk_o (mtx_clk_o),
.mrx_clk_o (mrx_clk_o),
.mrxd_o (mrxd_o[3:0]),
.mrxdv_o (mrxdv_o),
.mrxerr_o (mrxerr_o),
.mcoll_o (mcoll_o),
.mcrs_o (mcrs_o),
// Sideband outputs for smii converter --jb
.link_o (link),
.speed_o (fast_ethernet),
.duplex_o (duplex),
// Inouts
.md_io (eth_md_io[1:1]),
// Inputs
.m_rst_n_i (rst_i),
.mtxd_i (ethphy_mii_tx_d[3:0]),
.mtxen_i (ethphy_mii_tx_en),
.mtxerr_i (ethphy_mii_tx_err),
.mdc_i (eth_mdc_o[1:1]));
`endif // `ifdef USE_ETHERNET
 
initial
begin
$display("\nStarting RTL simulation of %s test\n", `TEST_NAME_STRING);
/openrisc/trunk/orpsocv2/bench/verilog/mt48lc16m16a2.v
37,7 → 37,7
*
**************************************************************************/
 
`timescale 1ns / 1ps
`include "timescale.v"
 
module mt48lc16m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
/openrisc/trunk/orpsocv2/rtl/verilog/components/smii/smii_sync.v
43,7 → 43,7
// SMII sync
output sync,
// internal
output reg [10:1] state, // Changed for verilator -- jb
output reg [10:1] state,
// clock amd reset
input clk,
input rst
52,7 → 52,7
// sync shall go high every 10:th cycle
always @ (posedge clk or posedge rst)
if (rst)
state <= 10'b1000000000;
state <= 10'b0000000001;
else
state <= {state[9:1],state[10]};
 
/openrisc/trunk/orpsocv2/rtl/verilog/components/smii/smii_txrx.v
66,7 → 66,7
output reg link,
`endif
// internal
input [10:1] state, // Change bit size declaration order, was [1:10], not verilator compatible: %Error: Unsupported: MSB < LSB of bit range: 1<10
input [10:1] state,
// clock and reset
input clk,
input rst
112,14 → 112,27
/////////////////////////////////////////////////
// Transmit
 
/* Timing scheme:
On the first clock of segment 0 (so each segment when 100Mb/s,
fast ethernet, or every 10 segments for 10Mb/s ethernet) we
deteremine if that segment is data or not, depending on what is
in the tx_data_reg_valid register. If the MAC wants to transmit
something, we overwrite the previously sent values when they're
no longer needed. Once the first nibble is sent, we can then
overwrite it, and same for the second - so we generate the TX
clock when state is 5, and sample the new nibble on the next
clock, same with the second nibble, that is clocked when state
is 9, and sampled when it is 10, so it gets overwritten when
we've finished putting it on the serial line.*/
always @ (posedge clk or posedge rst)
if (rst)
mtx_clk_tmp <= 1'b0;
else
if ((state[10] | state[5]) & (tx_cnt == 4'd0))
if ((state[5] | state[9]) & (tx_cnt == 4'd0))
mtx_clk_tmp <= 1'b1;
else if (state[2] | state[7])
else if (state[6] | state[10])
mtx_clk_tmp <= 1'b0;
 
`ifdef ACTEL
141,26 → 154,32
a0 <= 1'b0;
end
else
if ((state[4] | state[9]) & (tx_cnt == 4'd0))
if ((state[6] | state[10]) & (tx_cnt == 4'd0))
begin
/* Toggale a0 when MII TX_EN goes high */
if (!mtxen)
a0 <= 1'b0;
else
a0 <= ~a0;
 
/* byte will be valid when MII TX_EN
is high from the MAC */
if (!mtxen & !a0)
tx_data_reg_valid <= 1'b0;
else if (a0)
tx_data_reg_valid <= 1'b1;
 
/* Sample the nibble */
if (mtxen & !a0)
//tx_data_reg[0:3] <= {mtxd[0],mtxd[1],mtxd[2],mtxd[3]};
tx_data_reg[3:0] <= {mtxd[3],mtxd[2],mtxd[1],mtxd[0]}; // Changed for verilator -- jb
tx_data_reg[3:0] <= mtxd;
else if (mtxen & a0)
//tx_data_reg[4:7] <= {mtxd[0],mtxd[1],mtxd[2],mtxd[3]};
tx_data_reg[7:4] <= {mtxd[3],mtxd[2],mtxd[1],mtxd[0]}; // Changed for verilator -- jb
tx_data_reg[7:4] <= mtxd;
end // if ((state[4] | state[9]) & (tx_cnt == 4'd0))
 
// state flag
/* Determine if we output a data byte or the inter-frame sequence
with status information */
always @ (posedge clk or posedge rst)
if (rst)
state_data <= 1'b0;
167,11 → 186,18
else
if (state[1] & (tx_cnt == 4'd0))
state_data <= tx_data_reg_valid;
 
/* A wire hooked up from bit 0 with the last byte of the state counter/shiftreg */
wire [7:0] state_data_byte;
assign state_data_byte[7:0] = state[10:3];
/* Assign the SMII TX wire */
/* First bit always TX_ERR, then depending on the next bit, TX_EN, output
either the inter-frame status byte or a data byte */
assign tx = state[1] ? mtxerr :
state[2] ? ((tx_data_reg_valid & (tx_cnt == 4'd0)) | state_data) :
state_data ? |(state[10:2] & tx_data_reg) : // changed bit select order to 10:2 -- jb
|(state[10:2] & {mtxerr,speed,duplex,link,jabber,3'b111}); // changed bit select order to 10:2 -- jb
state_data ? |(state_data_byte & tx_data_reg) :
|(state_data_byte & {3'b111,jabber,link,duplex,speed,mtxerr});
 
/////////////////////////////////////////////////
// Receive
199,20 → 225,33
end
else
begin
/* Continually shift rx into rx_tmp bit 2, and shift rx_tmp along */
rx_tmp[2:0] <= {rx,rx_tmp[2:1]};
 
/* We appear to be beginning our sampling when state bit 3 is set */
if (state[3])
mcrs <= rx;
/* rx_tmp[3] is used as the RX_DV bit*/
if (state[4])
rx_tmp[3] <= rx;
if (rx_tmp[3]) //rxdv
 
if (rx_tmp[3]) //If data byte valid, and when we've got the first nibble, output it */
begin
/* At this stage we've got the first 3 bits of the bottom
nibble - we can sample the rx line directly to get the
4th, and we'll also indicate that this byte is valid by
raising the MII RX data valid (dv) line. */
if (state[8])
{mrxdv,mrxd} <= #1 {rx_tmp[3],rx,rx_tmp[2:0]};
/* High nibble, we have 3 bits and the final one is on
the line - put it out for the MAC to read.*/
else if (state[2])
mrxd <= #1 {rx,rx_tmp[2:0]};
end
else
begin
/* Not a data byte, it's the inter-frame status byte */
if (state[5])
mrxerr <= #1 rx;
if (state[6])
248,6 → 287,7
assign #1 mrx_clk = mrx_clk_tmp;
`endif
assign mcoll = mcrs & mtxen;
assign mcoll = mcrs & mtxen & !duplex;
endmodule // smii_top
/openrisc/trunk/orpsocv2/rtl/verilog/components/or1200r2/or1200_sprs.v
155,9 → 155,9
input [width-1:0] dat_i; // SPR write data
input [`OR1200_ALUOP_WIDTH-1:0] alu_op; // ALU operation
input [`OR1200_BRANCHOP_WIDTH-1:0] branch_op; // Branch operation
input [width-1:0] epcr; // EPCR0
input [width-1:0] eear; // EEAR0
input [`OR1200_SR_WIDTH-1:0] esr; // ESR0
input [width-1:0] epcr /* verilator public */; // EPCR0
input [width-1:0] eear /* verilator public */; // EEAR0
input [`OR1200_SR_WIDTH-1:0] esr /* verilator public */; // ESR0
input except_started; // Exception was started
output [width-1:0] to_wbmux; // For l.mfspr
output epcr_we; // EPCR0 write enable
166,7 → 166,7
output pc_we; // PC write enable
output sr_we; // Write enable SR
output [`OR1200_SR_WIDTH-1:0] to_sr; // Data to SR
output [`OR1200_SR_WIDTH-1:0] sr; // SR
output [`OR1200_SR_WIDTH-1:0] sr /* verilator public */; // SR
input [31:0] spr_dat_cfgr; // Data from CFGR
input [31:0] spr_dat_rf; // Data from RF
input [31:0] spr_dat_npc; // Data from NPC
404,6 → 404,33
always @(sr_reg or sr_reg_bit_eph_muxed)
sr = {sr_reg[`OR1200_SR_WIDTH-1], sr_reg_bit_eph_muxed, sr_reg[`OR1200_SR_WIDTH-3:0]};
 
`ifdef verilator
// Function to access various sprs (for Verilator). Have to hide this from
// simulator, since functions with no inputs are not allowed in IEEE
// 1364-2001.
 
function [31:0] get_sr;
// verilator public
get_sr = sr;
endfunction // get_sr
 
function [31:0] get_epcr;
// verilator public
get_epcr = epcr;
endfunction // get_epcr
 
function [31:0] get_eear;
// verilator public
get_eear = eear;
endfunction // get_eear
 
function [31:0] get_esr;
// verilator public
get_esr = esr;
endfunction // get_esr
 
`endif
 
//
// MTSPR/MFSPR interface
//
/openrisc/trunk/orpsocv2/rtl/verilog/components/or1200r2/or1200_except.v
228,7 → 228,7
reg [`OR1200_EXCEPT_WIDTH-1:0] except_type;
reg [31:0] id_pc;
reg [31:0] ex_pc;
reg [31:0] wb_pc;
reg [31:0] wb_pc /* verilator public */;
reg [31:0] epcr;
reg [31:0] eear;
reg [`OR1200_SR_WIDTH-1:0] esr;
237,12 → 237,12
reg [`OR1200_EXCEPTFSM_WIDTH-1:0] state;
reg extend_flush;
reg extend_flush_last;
reg ex_dslot;
reg ex_dslot /* verilator public */;
reg delayed1_ex_dslot;
reg delayed2_ex_dslot;
wire except_started;
wire [12:0] except_trig;
wire except_flushpipe;
wire except_flushpipe /* verilator public */;
reg [2:0] delayed_iee;
reg [2:0] delayed_tee;
wire int_pending;
294,6 → 294,18
sig_syscall & du_dsr[`OR1200_DU_DSR_SCE] & ~ex_freeze
};
 
`ifdef verilator
// Function to access wb_pc (for Verilator). Have to hide this from
// simulator, since functions with no inputs are not allowed in IEEE
// 1364-2001.
function [31:0] get_wb_pc;
// verilator public
get_wb_pc = wb_pc;
endfunction // get_wb_pc
 
`endif
 
 
//
// PC and Exception flags pipelines
//
/openrisc/trunk/orpsocv2/rtl/verilog/components/or1200r2/or1200_dpram.v
86,7 → 86,7
//
// Generic RAM's registers and wires
//
reg [dw-1:0] mem [(1<<aw)-1:0]; // RAM content
reg [dw-1:0] mem [(1<<aw)-1:0] /* verilator public */; // RAM content
reg [aw-1:0] addr_a_reg; // RAM address registered
 
 
96,22 → 96,7
// verilator public
input [aw-1:0] gpr_no;
 
get_gpr = { mem[gpr_no*32 + 31], mem[gpr_no*32 + 30],
mem[gpr_no*32 + 29], mem[gpr_no*32 + 28],
mem[gpr_no*32 + 27], mem[gpr_no*32 + 26],
mem[gpr_no*32 + 25], mem[gpr_no*32 + 24],
mem[gpr_no*32 + 23], mem[gpr_no*32 + 22],
mem[gpr_no*32 + 21], mem[gpr_no*32 + 20],
mem[gpr_no*32 + 19], mem[gpr_no*32 + 18],
mem[gpr_no*32 + 17], mem[gpr_no*32 + 16],
mem[gpr_no*32 + 15], mem[gpr_no*32 + 14],
mem[gpr_no*32 + 13], mem[gpr_no*32 + 12],
mem[gpr_no*32 + 11], mem[gpr_no*32 + 10],
mem[gpr_no*32 + 9], mem[gpr_no*32 + 8],
mem[gpr_no*32 + 7], mem[gpr_no*32 + 6],
mem[gpr_no*32 + 5], mem[gpr_no*32 + 4],
mem[gpr_no*32 + 3], mem[gpr_no*32 + 2],
mem[gpr_no*32 + 1], mem[gpr_no*32 + 0] };
get_gpr = mem[gpr_no];
endfunction // get_gpr
/openrisc/trunk/orpsocv2/rtl/verilog/components/uart16550/uart_top.v
141,204 → 141,204
`include "uart_defines.v"
 
module uart_top (
wb_clk_i,
// Wishbone signals
wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_sel_i,
int_o, // interrupt request
wb_clk_i,
// Wishbone signals
wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_sel_i,
int_o, // interrupt request
 
// UART signals
// serial input/output
stx_pad_o, srx_pad_i,
// UART signals
// serial input/output
stx_pad_o, srx_pad_i,
 
// modem signals
rts_pad_o, cts_pad_i, dtr_pad_o, dsr_pad_i, ri_pad_i, dcd_pad_i
// modem signals
rts_pad_o, cts_pad_i, dtr_pad_o, dsr_pad_i, ri_pad_i, dcd_pad_i
`ifdef UART_HAS_BAUDRATE_OUTPUT
, baud_o
, baud_o
`endif
);
);
 
parameter uart_data_width = `UART_DATA_WIDTH;
parameter uart_addr_width = `UART_ADDR_WIDTH;
parameter uart_data_width = `UART_DATA_WIDTH;
parameter uart_addr_width = `UART_ADDR_WIDTH;
 
input wb_clk_i;
input wb_clk_i;
 
// WISHBONE interface
input wb_rst_i;
input [uart_addr_width-1:0] wb_adr_i;
input [uart_data_width-1:0] wb_dat_i;
output [uart_data_width-1:0] wb_dat_o;
input wb_we_i;
input wb_stb_i;
input wb_cyc_i;
input [3:0] wb_sel_i;
output wb_ack_o;
output int_o;
// WISHBONE interface
input wb_rst_i;
input [uart_addr_width-1:0] wb_adr_i;
input [uart_data_width-1:0] wb_dat_i;
output [uart_data_width-1:0] wb_dat_o;
input wb_we_i;
input wb_stb_i;
input wb_cyc_i;
input [3:0] wb_sel_i;
output wb_ack_o;
output int_o;
 
// UART signals
input srx_pad_i;
output stx_pad_o;
output rts_pad_o;
input cts_pad_i;
output dtr_pad_o;
input dsr_pad_i;
input ri_pad_i;
input dcd_pad_i;
// UART signals
input srx_pad_i;
output stx_pad_o;
output rts_pad_o;
input cts_pad_i;
output dtr_pad_o;
input dsr_pad_i;
input ri_pad_i;
input dcd_pad_i;
 
// optional baudrate output
// optional baudrate output
`ifdef UART_HAS_BAUDRATE_OUTPUT
output baud_o;
output baud_o;
`endif
 
 
wire stx_pad_o;
wire rts_pad_o;
wire dtr_pad_o;
wire stx_pad_o;
wire rts_pad_o;
wire dtr_pad_o;
 
wire [uart_addr_width-1:0] wb_adr_i;
wire [uart_data_width-1:0] wb_dat_i;
wire [uart_data_width-1:0] wb_dat_o;
wire [uart_addr_width-1:0] wb_adr_i;
wire [uart_data_width-1:0] wb_dat_i;
wire [uart_data_width-1:0] wb_dat_o;
 
wire [7:0] wb_dat8_i; // 8-bit internal data input
wire [7:0] wb_dat8_o; // 8-bit internal data output
wire [31:0] wb_dat32_o; // debug interface 32-bit output
wire [3:0] wb_sel_i; // WISHBONE select signal
wire [uart_addr_width-1:0] wb_adr_int;
wire we_o; // Write enable for registers
wire re_o; // Read enable for registers
//
// MODULE INSTANCES
//
wire [7:0] wb_dat8_i; // 8-bit internal data input
wire [7:0] wb_dat8_o; // 8-bit internal data output
wire [31:0] wb_dat32_o; // debug interface 32-bit output
wire [3:0] wb_sel_i; // WISHBONE select signal
wire [uart_addr_width-1:0] wb_adr_int;
wire we_o; // Write enable for registers
wire re_o; // Read enable for registers
//
// MODULE INSTANCES
//
 
`ifdef DATA_BUS_WIDTH_8
`else
// debug interface wires
wire [3:0] ier;
wire [3:0] iir;
wire [1:0] fcr;
wire [4:0] mcr;
wire [7:0] lcr;
wire [7:0] msr;
wire [7:0] lsr;
wire [`UART_FIFO_COUNTER_W-1:0] rf_count;
wire [`UART_FIFO_COUNTER_W-1:0] tf_count;
wire [2:0] tstate;
wire [3:0] rstate;
// debug interface wires
wire [3:0] ier;
wire [3:0] iir;
wire [1:0] fcr;
wire [4:0] mcr;
wire [7:0] lcr;
wire [7:0] msr;
wire [7:0] lsr;
wire [`UART_FIFO_COUNTER_W-1:0] rf_count;
wire [`UART_FIFO_COUNTER_W-1:0] tf_count;
wire [2:0] tstate;
wire [3:0] rstate;
`endif
 
`ifdef DATA_BUS_WIDTH_8
//// WISHBONE interface module
uart_wb wb_interface(
.clk( wb_clk_i ),
.wb_rst_i( wb_rst_i ),
.wb_dat_i(wb_dat_i),
.wb_dat_o(wb_dat_o),
.wb_dat8_i(wb_dat8_i),
.wb_dat8_o(wb_dat8_o),
.wb_dat32_o(32'b0),
.wb_sel_i(4'b0),
.wb_we_i( wb_we_i ),
.wb_stb_i( wb_stb_i ),
.wb_cyc_i( wb_cyc_i ),
.wb_ack_o( wb_ack_o ),
.wb_adr_i(wb_adr_i),
.wb_adr_int(wb_adr_int),
.we_o( we_o ),
.re_o(re_o)
);
//// WISHBONE interface module
uart_wb wb_interface(
.clk( wb_clk_i ),
.wb_rst_i( wb_rst_i ),
.wb_dat_i(wb_dat_i),
.wb_dat_o(wb_dat_o),
.wb_dat8_i(wb_dat8_i),
.wb_dat8_o(wb_dat8_o),
.wb_dat32_o(32'b0),
.wb_sel_i(4'b0),
.wb_we_i( wb_we_i ),
.wb_stb_i( wb_stb_i ),
.wb_cyc_i( wb_cyc_i ),
.wb_ack_o( wb_ack_o ),
.wb_adr_i(wb_adr_i),
.wb_adr_int(wb_adr_int),
.we_o( we_o ),
.re_o(re_o)
);
`else
uart_wb wb_interface(
.clk( wb_clk_i ),
.wb_rst_i( wb_rst_i ),
.wb_dat_i(wb_dat_i),
.wb_dat_o(wb_dat_o),
.wb_dat8_i(wb_dat8_i),
.wb_dat8_o(wb_dat8_o),
.wb_sel_i(wb_sel_i),
.wb_dat32_o(wb_dat32_o),
.wb_we_i( wb_we_i ),
.wb_stb_i( wb_stb_i ),
.wb_cyc_i( wb_cyc_i ),
.wb_ack_o( wb_ack_o ),
.wb_adr_i(wb_adr_i),
.wb_adr_int(wb_adr_int),
.we_o( we_o ),
.re_o(re_o)
);
uart_wb wb_interface(
.clk( wb_clk_i ),
.wb_rst_i( wb_rst_i ),
.wb_dat_i(wb_dat_i),
.wb_dat_o(wb_dat_o),
.wb_dat8_i(wb_dat8_i),
.wb_dat8_o(wb_dat8_o),
.wb_sel_i(wb_sel_i),
.wb_dat32_o(wb_dat32_o),
.wb_we_i( wb_we_i ),
.wb_stb_i( wb_stb_i ),
.wb_cyc_i( wb_cyc_i ),
.wb_ack_o( wb_ack_o ),
.wb_adr_i(wb_adr_i),
.wb_adr_int(wb_adr_int),
.we_o( we_o ),
.re_o(re_o)
);
`endif
 
// Registers
uart_regs regs(
.clk( wb_clk_i ),
.wb_rst_i( wb_rst_i ),
.wb_addr_i( wb_adr_int ),
.wb_dat_i( wb_dat8_i ),
.wb_dat_o( wb_dat8_o ),
.wb_we_i( we_o ),
.wb_re_i(re_o),
.modem_inputs( {cts_pad_i, dsr_pad_i,
ri_pad_i, dcd_pad_i} ),
.stx_pad_o( stx_pad_o ),
.srx_pad_i( srx_pad_i ),
// Registers
uart_regs regs(
.clk( wb_clk_i ),
.wb_rst_i( wb_rst_i ),
.wb_addr_i( wb_adr_int ),
.wb_dat_i( wb_dat8_i ),
.wb_dat_o( wb_dat8_o ),
.wb_we_i( we_o ),
.wb_re_i(re_o),
.modem_inputs( {cts_pad_i, dsr_pad_i,
ri_pad_i, dcd_pad_i} ),
.stx_pad_o( stx_pad_o ),
.srx_pad_i( srx_pad_i ),
`ifdef DATA_BUS_WIDTH_8
`else
// debug interface signals enabled
.ier(ier),
.iir(iir),
.fcr(fcr),
.mcr(mcr),
.lcr(lcr),
.msr(msr),
.lsr(lsr),
.rf_count(rf_count),
.tf_count(tf_count),
.tstate(tstate),
.rstate(rstate),
// debug interface signals enabled
.ier(ier),
.iir(iir),
.fcr(fcr),
.mcr(mcr),
.lcr(lcr),
.msr(msr),
.lsr(lsr),
.rf_count(rf_count),
.tf_count(tf_count),
.tstate(tstate),
.rstate(rstate),
`endif
.rts_pad_o( rts_pad_o ),
.dtr_pad_o( dtr_pad_o ),
.int_o( int_o )
.rts_pad_o( rts_pad_o ),
.dtr_pad_o( dtr_pad_o ),
.int_o( int_o )
`ifdef UART_HAS_BAUDRATE_OUTPUT
, .baud_o(baud_o)
, .baud_o(baud_o)
`endif
 
);
);
 
`ifdef DATA_BUS_WIDTH_8
`else
uart_debug_if dbg(/*AUTOINST*/
// Outputs
.wb_dat32_o (wb_dat32_o[31:0]),
// Inputs
.wb_adr_i (wb_adr_int[`UART_ADDR_WIDTH-1:0]),
.ier (ier[3:0]),
.iir (iir[3:0]),
.fcr (fcr[1:0]),
.mcr (mcr[4:0]),
.lcr (lcr[7:0]),
.msr (msr[7:0]),
.lsr (lsr[7:0]),
.rf_count (rf_count[`UART_FIFO_COUNTER_W-1:0]),
.tf_count (tf_count[`UART_FIFO_COUNTER_W-1:0]),
.tstate (tstate[2:0]),
.rstate (rstate[3:0]));
uart_debug_if dbg(/*AUTOINST*/
// Outputs
.wb_dat32_o (wb_dat32_o[31:0]),
// Inputs
.wb_adr_i (wb_adr_int[`UART_ADDR_WIDTH-1:0]),
.ier (ier[3:0]),
.iir (iir[3:0]),
.fcr (fcr[1:0]),
.mcr (mcr[4:0]),
.lcr (lcr[7:0]),
.msr (msr[7:0]),
.lsr (lsr[7:0]),
.rf_count (rf_count[`UART_FIFO_COUNTER_W-1:0]),
.tf_count (tf_count[`UART_FIFO_COUNTER_W-1:0]),
.tstate (tstate[2:0]),
.rstate (rstate[3:0]));
`endif
 
initial
begin
initial
begin
`ifdef UART16550_SIM_OUTPUT
`ifdef DATA_BUS_WIDTH_8
$display("(%m) UART INFO: Data bus width is 8. No Debug interface.\n");
$display("(%m) UART INFO: Data bus width is 8. No Debug interface.\n");
`else
$display("(%m) UART INFO: Data bus width is 32. Debug Interface present.\n");
$display("(%m) UART INFO: Data bus width is 32. Debug Interface present.\n");
`endif
`ifdef UART_HAS_BAUDRATE_OUTPUT
$display("(%m) UART INFO: Has baudrate output\n");
$display("(%m) UART INFO: Has baudrate output\n");
`else
$display("(%m) UART INFO: Doesn't have baudrate output\n");
$display("(%m) UART INFO: Doesn't have baudrate output\n");
`endif
`endif
end
end
 
endmodule // uart_top
 
/openrisc/trunk/orpsocv2/rtl/verilog/orpsoc_top.v
1,4 → 1,46
//module ref_design_top
//////////////////////////////////////////////////////////////////////
//// ////
//// orpsoc_top.v ////
//// ////
//// This file is part of the ORPSoCv2 project ////
//// http://opencores.org/openrisc/?orpsocv2 ////
//// ////
//// This is the top level RTL file for ORPSoCv2 ////
//// ////
//// Author(s): ////
//// - Michael Unneback, unneback@opencores.org ////
//// ORSoC AB michael.unneback@orsoc.se ////
//// - Julius Baxter, julius.baxter@orsoc.se ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2008, 2009 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
 
module orpsoc_top
(
output spi_sd_sclk_pad_o ,
24,7 → 66,7
output spi_flash_w_n_pad_o ,
output spi_flash_hold_n_pad_o,
`endif // `ifdef USE_SDRAM
`ifdef USE_ETHERNET
`ifdef USE_ETHERNET_IO
output [1:1] eth_sync_pad_o,
output [1:1] eth_tx_pad_o,
input [1:1] eth_rx_pad_i,
31,7 → 73,7
input eth_clk_pad_i,
inout [1:1] eth_md_pad_io,
output [1:1] eth_mdc_pad_o,
`endif // `ifdef USE_ETHERNET
`endif // `ifdef USE_ETHERNET_IO
output spi1_mosi_pad_o,
input spi1_miso_pad_i,
output spi1_ss_pad_o ,
349,7 → 391,7
assign pic_ints[7] = 1'b0;
assign pic_ints[6] = 1'b0;
assign pic_ints[5] = 1'b0;
assign pic_ints[4] = 1'b0;
assign pic_ints[4] = eth_int[1]; /* IRQ4, just like in Linux. Added jb 090716 */
assign pic_ints[3] = 1'b0;
assign pic_ints[2] = uart0_irq;
assign pic_ints[1] = 1'b0;
550,8 → 592,7
wire m1rxerr;
wire m1coll;
wire m1crs;
//wire [1:10] state;
wire [10:1] state; // Changed for verilator -- jb
wire [10:1] state;
wire sync;
wire [1:1] rx, tx;
wire [1:1] mdc_o, md_i, md_o, md_oe;
602,6 → 643,8
.md_padoe_o(md_oe[1]),
.int_o(eth_int[1])
);
 
`ifdef USE_ETHERNET_IO
iobuftri iobuftri1
(
.i(md_o[1]),
632,6 → 675,7
.clk(eth_clk),
.rst(wb_rst)
);
 
obufdff obufdff_sync1
(
.d(sync),
653,6 → 697,8
.clk(eth_clk),
.rst(wb_rst)
);
`endif // `ifdef USE_ETHERNET_IO
 
`else // !`ifdef USE_ETHERNET
// If ethernet core is disabled, still ack anyone who tries
// to access its config port. This allows linux to boot in
/openrisc/trunk/orpsocv2/sim/bin/Makefile
201,22 → 201,37
# SystemC cycle-accurate model compilation
#
# A new addition to ORPSoC v2 is the cycle-accurate model. The primary enabler
# behind this is verilator, which processes the RTL sources and generates a c++
# description of the system. This c++ description is then compiled with a
# behind this is verilator, which processes the RTL source and generates a c++
# description of the system. This c++ description is then compiled, with a
# SystemC wrapper. Finally a top-level SystemC testbench instantiates the
# model, as well as any other modules - in this case a reset generation, UART
# model, and other useful modules - in this case a reset generation, UART
# decoder, and monitor module are included at the top level. These additional
# modules and models are written in SystemC and compiled all together with the
# cycle-accurate ORPSoC model to create the simulation executable. Finally this
# executable is run and should be a cycle-representation of the system. VCDs
# can be generated if enabled. The compiled mentioned above is all done with
# the GNU c++ compiler, g++.
# The compilation process is a little more tricky than a typical even-driven
# modules and models are written in SystemC. Finally, everything is linked with
# the cycle-accurate ORPSoC model to create the simulation executable. This
# executable is the cycle-representation of the system.
#
# VCDs can be generated if the model is made with VCD=1 specified on the
# command line. Specify a dump file with the "-vcd" option at runtime, eg:
# "./Vorpsoc_top -vcd dump.vcd"
# Note that this slows down the simulation.
#
# Logging of the processor's execution can be done by specifying a log file
# on the command line at runtime, eg: "./Vorpsoc_top -log or1200_exec.log"
# Note that this slows down the simulation.
#
# There are performance metrics printed at the conclusion of simulations. To
# disable these launch the executable with either the -q or --no-perf-summary
# options. eg: "./Vorpsoc_top -q"
#
# The compilation is all done with the GNU c++ compiler, g++.
#
# The compilation process is a little more complicated than the event-driven
# simulator. It proceeds basically by generating the makefiles for compiling
# the design with verilator, running these makes which produces a library
# containing the cycle-accurate ORPSoC design, compiling the additional
# top-level, and testbench, systemC models into a library, and then linking it
# all together into the simulation executable.
#
# The major advantage of the cycle-accurate model is that it is quicker, in
# terms of simulated cycles/second, when compared with event-driven simulators.
# It is, of course, less accurate in that it cannot model propegation delays.
223,16 → 238,16
# However this is usually not an issue for simulating a design which is known
# to synthesize and run OK. It is very useful for running complex software,
# such as the linux kernel and real-time OS applications, which generally
# require long simulation times.
# result in long simulation times.
#
# Currently the cycle-accurate model being used doesn't contain much more than
# the processor and a UART, however it's exepected in future this will be
# expanded on and more complex software test suites will be implemented to put
# the system through its paces.
#
#
 
 
# Name of
# the directory we're currently in
# Name of the directory we're currently in
CUR_DIR=$(shell pwd)
 
# The root path of the whole project
275,7 → 290,9
 
# Enable ethernet if defined on the command line
ifdef USE_ETHERNET
EVENT_SIM_FLAGS += "-D USE_ETHERNET=$(USE_ETHERNET)"
EVENT_SIM_FLAGS += "-D USE_ETHERNET=$(USE_ETHERNET) -D USE_ETHERNET_IO=$(USE_ETHERNET)"
# Extra tests we do if ethernet is enabled
TESTS += eth-basic
endif
 
SIM_FLASH_MEM_FILE="flash.in"
296,7 → 313,7
 
 
ifdef UART_PRINTF
TEST_SW_MAKE_OPTS=UART_PRINTF=1
TEST_SW_MAKE_OPTS="UART_PRINTF=1"
endif
 
.PHONY: prepare_sw
357,7 → 374,7
# Define USE_SDRAM to enable the external SDRAM, otherwise the simulation
# defaults to an internal SRAM. Eg. $ make rtl-tests USE_SDRAM=1 VCD=1
# Verilator defaults to internal memories
rtl-tests: prepare_sw_uart_printf prepare_rtl prepare_dirs
rtl-tests: prepare_sw prepare_rtl prepare_dirs
@echo
@echo "Beginning loop that will complete the following tests: $(TESTS)"
@echo
386,6 → 403,10
fi; \
echo "\`define TEST_NAME_STRING \"$$TEST\"" > $(SIM_RUN_DIR)/test_define.v; \
echo "\`define TEST_RESULTS_DIR \"$(SIM_RESULTS_DIR)/\" " >> $(SIM_RUN_DIR)/test_define.v; \
if echo $$TEST | grep -q -i ^eth; then \
echo "\`define ENABLE_ETH_STIM" >> $(SIM_RUN_DIR)/test_define.v; \
echo "\`define ETH_PHY_VERBOSE" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
if [ -z $$NO_SIM_LOGGING ]; then \
echo "\`define OR1200_DISPLAY_ARCH_STATE" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
442,6 → 463,10
if [ ! -z $$USE_SDRAM ]; then \
echo "\`define USE_SDRAM" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
if echo $$TEST | grep -q -i ^eth; then \
echo "\`define ENABLE_ETH_STIM" >> $(SIM_RUN_DIR)/test_define.v; \
echo "\`define ETH_PHY_VERBOSE" >> $(SIM_RUN_DIR)/test_define.v; \
fi; \
echo "+nocopyright" >> $(SIM_RUN_DIR)/$(ICARUS_COMMAND_FILE).generated; \
echo "+nowarn+MACRDF" >> $(SIM_RUN_DIR)/$(ICARUS_COMMAND_FILE).generated; \
echo "\`define TEST_NAME_STRING \"$$TEST\"" > $(SIM_RUN_DIR)/test_define.v; \
700,14 → 725,10
clean: clean-sw clean-sim clean-sysc clean-rtl clean_vpi
 
clean-sw:
@for TEST in $(TESTS); do \
echo "Current test: $$TEST"; \
CURRENT_TEST_SW_DIR=$(SW_DIR)/`echo $$TEST | cut -d "-" -f 1`; \
echo "Current test sw directory: " $$CURRENT_TEST_SW_DIR; \
$(MAKE) -C $$CURRENT_TEST_SW_DIR clean; \
@for SWDIR in `ls $(SW_DIR)`; do \
echo $$SWDIR; \
$(MAKE) -C $(SW_DIR)/$$SWDIR clean; \
done
$(MAKE) -C $(SW_DIR)/support clean
$(MAKE) -C $(SW_DIR)/utils clean
 
clean-sim:
rm -rf $(SIM_RESULTS_DIR) $(SIM_RUN_DIR)/*.* $(SIM_VLT_DIR)
719,4 → 740,5
clean-rtl:
# Clean away temporary verilog source files
rm -f $(RTL_VERILOG_DIR)/intercon.v
rm -f $(RTL_VERILOG_DIR)/components/wb_sdram_ctrl/wb_sdram_ctrl_fsm.v
rm -f $(RTL_VERILOG_DIR)/components/wb_sdram_ctrl/wb_sdram_ctrl_fsm.v
 
/openrisc/trunk/orpsocv2/sim/bin/verilator.scr
34,3 → 34,4
-v $BACKEND_DIR/sim_lib.v
 
+define+DISABLE_IOS_FOR_VERILATOR
 
/openrisc/trunk/orpsocv2/sw/eth/eth-basic.c
0,0 → 1,735
//////////////////////////////////////////////////////////////////////
//// ////
//// Simple Ethernet test code ////
//// ////
//// Description ////
//// ORPSoC test software ////
//// ////
//// To Do: ////
//// - It's a simple test for now, but could be adapted for ////
//// standalone use. ////
//// ////
//// Author(s): ////
//// - jb, jb@orsoc.se, with parts taken from Linux kernel ////
//// open_eth driver. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
 
#include "support.h"
#include "board.h"
#include "uart.h"
#include "open_eth.h"
 
#include "ethphy_micrel.h"
 
/* Dummy exception functions */
void buserr_except(){}
void dpf_except(){}
void ipf_except(){}
void lpint_except(){}
void align_except(){}
void illegal_except(){}
void hpint_except(){}
void dtlbmiss_except(){}
void itlbmiss_except(){}
void range_except(){}
void syscall_except(){}
void res1_except(){}
void trap_except(){}
void res2_except(){}
 
/* Functions in this file */
void ethmac_setup(void);
void oeth_printregs(void);
void ethphy_init(void);
void oeth_dump_bds();
 
/* Defining RTLSIM turns off use of real printf'ing to save time in simulation */
#define RTLSIM
 
#ifdef RTLSIM
#define printk
#else
#define printk printf
#endif
 
/* Let the ethernet packets use a space beginning here for buffering */
#define ETH_BUFF_BASE 0x01000000
 
 
#define RXBUFF_PREALLOC 1
#define TXBUFF_PREALLOC 1
//#undef RXBUFF_PREALLOC
//#undef TXBUFF_PREALLOC
 
/* The transmitter timeout
*/
#define TX_TIMEOUT (2*HZ)
 
/* Buffer number (must be 2^n)
*/
#define OETH_RXBD_NUM 8
#define OETH_TXBD_NUM 8
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1)
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1)
 
/* Buffer size
*/
#define OETH_RX_BUFF_SIZE 2048
#define OETH_TX_BUFF_SIZE 2048
 
/* OR32 Page size def */
#define PAGE_SHIFT 13
#define PAGE_SIZE (1UL << PAGE_SHIFT)
 
/* How many buffers per page
*/
#define OETH_RX_BUFF_PPGAE (PAGE_SIZE/OETH_RX_BUFF_SIZE)
#define OETH_TX_BUFF_PPGAE (PAGE_SIZE/OETH_TX_BUFF_SIZE)
 
/* How many pages is needed for buffers
*/
#define OETH_RX_BUFF_PAGE_NUM (OETH_RXBD_NUM/OETH_RX_BUFF_PPGAE)
#define OETH_TX_BUFF_PAGE_NUM (OETH_TXBD_NUM/OETH_TX_BUFF_PPGAE)
 
/* Buffer size (if not XXBUF_PREALLOC
*/
#define MAX_FRAME_SIZE 1518
 
/* The buffer descriptors track the ring buffers.
*/
struct oeth_private {
//struct sk_buff* rx_skbuff[OETH_RXBD_NUM];
//struct sk_buff* tx_skbuff[OETH_TXBD_NUM];
 
unsigned short tx_next; /* Next buffer to be sent */
unsigned short tx_last; /* Next buffer to be checked if packet sent */
unsigned short tx_full; /* Buffer ring fuul indicator */
unsigned short rx_cur; /* Next buffer to be checked if packet received */
 
oeth_regs *regs; /* Address of controller registers. */
oeth_bd *rx_bd_base; /* Address of Rx BDs. */
oeth_bd *tx_bd_base; /* Address of Tx BDs. */
 
// struct net_device_stats stats;
};
 
 
void oeth_printregs(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
printk("Oeth regs: Mode Register : 0x%lx\n",(unsigned long) regs->moder); /* Mode Register */
printk("Oeth regs: Interrupt Source Register 0x%lx\n", (unsigned long) regs->int_src); /* Interrupt Source Register */
printk("Oeth regs: Interrupt Mask Register 0x%lx\n",(unsigned long) regs->int_mask); /* Interrupt Mask Register */
printk("Oeth regs: Back to Bak Inter Packet Gap Register 0x%lx\n",(unsigned long) regs->ipgt); /* Back to Bak Inter Packet Gap Register */
printk("Oeth regs: Non Back to Back Inter Packet Gap Register 1 0x%lx\n",(unsigned long) regs->ipgr1); /* Non Back to Back Inter Packet Gap Register 1 */
printk("Oeth regs: Non Back to Back Inter Packet Gap Register 2 0x%lx\n",(unsigned long) regs->ipgr2); /* Non Back to Back Inter Packet Gap Register 2 */
printk("Oeth regs: Packet Length Register (min. and max.) 0x%lx\n",(unsigned long) regs->packet_len); /* Packet Length Register (min. and max.) */
printk("Oeth regs: Collision and Retry Configuration Register 0x%lx\n",(unsigned long) regs->collconf); /* Collision and Retry Configuration Register */
printk("Oeth regs: Transmit Buffer Descriptor Number Register 0x%lx\n",(unsigned long) regs->tx_bd_num); /* Transmit Buffer Descriptor Number Register */
printk("Oeth regs: Control Module Mode Register 0x%lx\n",(unsigned long) regs->ctrlmoder); /* Control Module Mode Register */
printk("Oeth regs: MII Mode Register 0x%lx\n",(unsigned long) regs->miimoder); /* MII Mode Register */
printk("Oeth regs: MII Command Register 0x%lx\n",(unsigned long) regs->miicommand); /* MII Command Register */
printk("Oeth regs: MII Address Register 0x%lx\n",(unsigned long) regs->miiaddress); /* MII Address Register */
printk("Oeth regs: MII Transmit Data Register 0x%lx\n",(unsigned long) regs->miitx_data); /* MII Transmit Data Register */
printk("Oeth regs: MII Receive Data Register 0x%lx\n",(unsigned long) regs->miirx_data); /* MII Receive Data Register */
printk("Oeth regs: MII Status Register 0x%lx\n",(unsigned long) regs->miistatus); /* MII Status Register */
printk("Oeth regs: MAC Individual Address Register 0 0x%lx\n",(unsigned long) regs->mac_addr0); /* MAC Individual Address Register 0 */
printk("Oeth regs: MAC Individual Address Register 1 0x%lx\n",(unsigned long) regs->mac_addr1); /* MAC Individual Address Register 1 */
printk("Oeth regs: Hash Register 0 0x%lx\n",(unsigned long) regs->hash_addr0); /* Hash Register 0 */
printk("Oeth regs: Hash Register 1 0x%lx\n",(unsigned long) regs->hash_addr1); /* Hash Register 1 */
}
 
static int last_char;
 
void spin_cursor(void)
{
#ifdef RTLSIM
return;
#endif
volatile unsigned int i; // So the loop doesn't get optimised away
printk(" \r");
if (last_char == 0)
printk("/");
else if (last_char == 1)
printk("-");
else if (last_char == 2)
printk("\\");
else if (last_char == 3)
printk("|");
else if (last_char == 4)
printk("/");
else if (last_char == 5)
printk("-");
else if (last_char == 6)
printk("\\");
else if (last_char == 7)
{
printk("|");
last_char=-1;
}
last_char++;
for(i=0;i<20000;i++);
 
}
 
#define PHYNUM 0
 
/* Scan the MIIM bus for PHYs */
void scan_ethphys(void)
{
unsigned int phynum,regnum, i;
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
regs->miitx_data = 0;
for(phynum=0;phynum<32;phynum++)
{
for (regnum=0;regnum<8;regnum++)
{
printk("scan_ethphys: phy %d r%d ",phynum, regnum);
/* Now actually perform the read on the MIIM bus*/
regs->miiaddress = (regnum << 8) | phynum; /* Basic Control Register */
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY);
printk("%x\n",regs->miirx_data);
}
}
}
 
void ethmac_scanstatus(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
//printk("Oeth: regs->miistatus %x regs->miirx_data %x\n",regs->miistatus, regs->miirx_data);
regs->miiaddress = 0;
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_SCANSTAT;
//printk("Oeth: regs->miiaddress %x regs->miicommand %x\n",regs->miiaddress, regs->miicommand);
//regs->miicommand = 0;
volatile int i; for(i=0;i<1000;i++);
while(regs->miistatus & OETH_MIISTATUS_BUSY) ;
//spin_cursor();
//printk("\r");
or32_exit(0);
}
void ethphy_init(void)
{
volatile int i;
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
/* Init the Micrel KSZ80001L PHY */
/* First reset it */
/* printk("Oeth: regs->miistatus %x regs->miirx_data %x\n",regs->miistatus, regs->miirx_data); */
/* regs->miiaddress = (MICREL_KSZ8001_BCR_ADR << 8); /\* PHY's Basic Control Register *\/ */
/* regs->miitx_data = MICREL_KSZ8001_BCR_RESET; */
/* regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; */
/* printk("Oeth: regs->miiaddress %x regs->miicommand %x\n",regs->miiaddress, regs->miicommand); */
/* regs->miicommand = 0; */
/* while(regs->miistatus & OETH_MIISTATUS_BUSY) */
/* spin_cursor(); */
/* printk("\r"); */
 
printk("Oeth: Reading PHY r0 (status reg)\n");
regs->miiaddress = MICREL_KSZ8001_BCR_ADR<<8 | PHYNUM; /* Basic Control Register */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
 
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
 
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
printk("\r");
/* while (regs->miirx_data & MICREL_KSZ8001_BCR_RESET) */
/* { */
/* regs->miiaddress = MICREL_KSZ8001_BCR_ADR<<8; /\* Basic Control Register *\/ */
/* regs->miitx_data = 0; */
/* regs->miicommand = OETH_MIICOMMAND_RSTAT; */
/* regs->miicommand = 0; */
/* while(regs->miistatus & OETH_MIISTATUS_BUSY) */
/* spin_cursor(); */
/* } */
/* printk("\r"); */
 
printk("\nOeth: PHY r0 value: %x\n",regs->miirx_data);
/* PHY reset and confirmed as such */
/* Now read the link status */
regs->miiaddress = MICREL_KSZ8001_BSR_ADR<<8 | PHYNUM; /* Basic Status Register */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
 
printk("\r");
printk("Oeth: PHY BSR: 0x%x\n",regs->miirx_data & 0xffff);
/* Read the operation mode */
regs->miiaddress = MICREL_KSZ8001_100BTPCR_ADR<<8 | PHYNUM; /* 100BASE-TX */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
printk("\r");
printk("Oeth: PHY 100BASE-TX PHY Control Register: 0x%x\n",regs->miirx_data);
 
 
/* Read the PHY identification register 1 */
regs->miiaddress = MICREL_KSZ8001_PI1_ADR<<8 | PHYNUM; /* PI1 */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
printk("\r");
printk("Oeth: PHY PHY Identifier I: 0x%x\n",regs->miirx_data);
 
/* Read the PHY identification register 2 */
regs->miiaddress = MICREL_KSZ8001_PI2_ADR<<8 | PHYNUM; /* PI2 */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
printk("\r");
printk("Oeth: PHY PHY Identifier II: 0x%x\n",regs->miirx_data);
 
 
}
 
 
void ethmac_setup(void)
{
// from arch/or32/drivers/open_eth.c
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
/*printk("\nbefore reset\n\n");
oeth_printregs();*/
 
/* Reset MII mode module */
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */
regs->miimoder = 0x64; /* Clock divider for MII Management interface */
/* Reset the controller.
*/
regs->moder = OETH_MODER_RST; /* Reset ON */
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */
//printk("\nafter reset\n\n");
//oeth_printregs();
/* Setting TXBD base to OETH_TXBD_NUM.
*/
regs->tx_bd_num = OETH_TXBD_NUM;
/* Set min/max packet length
*/
regs->packet_len = 0x00400600;
/* Set IPGT register to recomended value
*/
regs->ipgt = 0x00000012;
/* Set IPGR1 register to recomended value
*/
regs->ipgr1 = 0x0000000c;
/* Set IPGR2 register to recomended value
*/
regs->ipgr2 = 0x00000012;
/* Set COLLCONF register to recomended value
*/
regs->collconf = 0x000f003f;
/* Set control module mode
*/
#if 0
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW;
#else
regs->ctrlmoder = 0;
#endif
/* Clear MIIM registers */
regs->miitx_data = 0;
regs->miiaddress = 0;
regs->miicommand = 0;
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1;
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 | ETH_MACADDR4 << 8 | ETH_MACADDR5;
/* Clear all pending interrupts
*/
regs->int_src = 0xffffffff;
/* Promisc, IFG, CRCEn
*/
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN | OETH_MODER_FULLD;
/* Enable interrupt sources.
*/
/*
regs->int_mask = OETH_INT_MASK_TXB |
OETH_INT_MASK_TXE |
OETH_INT_MASK_RXF |
OETH_INT_MASK_RXE |
OETH_INT_MASK_BUSY |
OETH_INT_MASK_TXC |
OETH_INT_MASK_RXC;
*/
/* Disable interrupt sources
*/
regs->int_mask = 0;
printk("\nafter config\n\n");
oeth_printregs();
 
// Buffer setup stuff
volatile oeth_bd *tx_bd, *rx_bd;
int i,j,k;
/* Initialize TXBD pointer
*/
tx_bd = (volatile oeth_bd *)OETH_BD_BASE;
/* Initialize RXBD pointer
*/
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
/* Preallocated ethernet buffer setup */
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */
 
/* Setup for TX buffers*/
for(i = 0, k = 0; i < OETH_TX_BUFF_PAGE_NUM; i++) {
for(j = 0; j < OETH_TX_BUFF_PPGAE; j++, k++) {
//tx_bd[k].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ;
tx_bd[k].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC;
tx_bd[k].addr = mem_addr;
mem_addr += OETH_TX_BUFF_SIZE;
}
}
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP;
 
/* Setup for RX buffers */
for(i = 0, k = 0; i < OETH_RX_BUFF_PAGE_NUM; i++) {
for(j = 0; j < OETH_RX_BUFF_PPGAE; j++, k++) {
//rx_bd[k].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ;
rx_bd[k].len_status = OETH_RX_BD_EMPTY;
rx_bd[k].addr = mem_addr;
mem_addr += OETH_RX_BUFF_SIZE;
}
}
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP;
 
/* Enable RX of packets */
/* Set RXEN in MAC MODER */
regs->moder = OETH_MODER_RXEN | regs->moder;
 
}
 
/* Find the next available transmit buffer */
struct oeth_bd* get_next_tx_bd()
{
int i;
volatile oeth_bd *tx_bd;
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/
/* Go through the TX buffs, search for unused one */
for(i = 0; i < OETH_TXBD_NUM; i++) {
if(!(tx_bd[i].len_status & OETH_TX_BD_READY)) /* Looking for buffer NOT ready for transmit. ie we can manipulate it */
{
printk("Oeth: Using TX_bd at 0x%lx\n",(unsigned long)&tx_bd[i]);
return (struct oeth_bd*) &tx_bd[i];
}
}
 
printk("No free tx buffers\n");
/* Set to null our returned buffer */
tx_bd = (volatile oeth_bd *) 0;
return (struct oeth_bd*) tx_bd;
}
 
 
/* print packet contents */
static void
oeth_print_packet(unsigned long add, int len)
{
int i;
printk("ipacket: add = %lx len = %d\n", add, len);
for(i = 0; i < len; i++) {
if(!(i % 16))
printk("\n");
printk(" %.2x", *(((unsigned char *)add) + i));
}
printk("\n");
}
 
/* Setup buffer descriptors with data */
/* length is in BYTES */
void tx_packet(void* data, int length)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
volatile oeth_bd *tx_bd;
volatile int i;
if((tx_bd = (volatile oeth_bd *) get_next_tx_bd()) == NULL)
{
printk("No more TX buffers available\n");
return;
}
printk("Oeth: TX_bd buffer address: 0x%lx\n",(unsigned long) tx_bd->addr);
/* Clear all of the status flags.
*/
tx_bd->len_status &= ~OETH_TX_BD_STATS;
/* If the frame is short, tell CPM to pad it.
*/
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
if (length <= ETH_ZLEN)
tx_bd->len_status |= OETH_TX_BD_PAD;
else
tx_bd->len_status &= ~OETH_TX_BD_PAD;
printk("Oeth: Copying %d bytes from 0x%lx to TX_bd buffer at 0x%lx\n",length,(unsigned long) data,(unsigned long) tx_bd->addr);
/* Copy the data into the transmit buffer, word at a time */
char* data_p = (char*) data;
char* data_b = (char*) tx_bd->addr;
for(i=0;i<length;i++)
{
*(data_b+i) = *(data_p+i);
}
printk("Oeth: Data copied to buffer\n");
/* Set the length of the packet's data in the buffer descriptor */
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) |
((length&0xffff) << 16);
 
//oeth_print_packet(tx_bd->addr, (tx_bd->len_status >> 16));
 
/* Send it on its way. Tell controller its ready,
* and to put the CRC on the end.
*/
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC);
 
oeth_dump_bds();
 
printk("Oeth: MODER addr: 0x%x\n", regs->moder);
 
/* Set TXEN in MAC MODER */
regs->moder = OETH_MODER_TXEN | regs->moder;
 
printk("Oeth: TXBD Status 0x%x\n", tx_bd->len_status);
i=0;
 
/* Wait for BD READY bit to be cleared, indicating it's been sent */
while (OETH_TX_BD_READY & tx_bd->len_status)
{
#ifndef RTLSIM
//for(i=0;i<40000;i++);
//printk("Oeth: TXBD Status 0x%x\n", tx_bd->len_status);
//oeth_printregs();
spin_cursor();
if (i++%64==63) {oeth_dump_bds();}
#endif
}
 
#ifdef RTLSIM
return;
#else
printk("sent\n");
#endif
 
}
 
/* enable RX, loop waiting for arrived packets and print them out */
void oeth_monitor_rx(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
/* Set RXEN in MAC MODER */
regs->moder = OETH_MODER_RXEN | regs->moder;
 
volatile oeth_bd *rx_bd;
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
 
volatile int i;
while (1)
{
for(i=0;i<OETH_RXBD_NUM;i++)
{
if (!(rx_bd[i].len_status & OETH_RX_BD_EMPTY)) /* Not empty */
{
// Something in this buffer!
printk("Oeth: RX in buf %d - len_status: 0x%lx\n",i, rx_bd[i].len_status);
oeth_print_packet(rx_bd[i].addr, rx_bd[i].len_status >> 16);
/* Clear recieved bit */
rx_bd[i].len_status |= OETH_RX_BD_EMPTY;
printk("\t end of packet\n\n");
}
}
}
}
 
/* Print out all buffer descriptors */
void oeth_dump_bds()
{
unsigned long* bd_base = (unsigned long*) OETH_BD_BASE;
 
int i;
for(i=0;i<OETH_TXBD_NUM;i++)
{
printk("oeth: tx_bd%d: len_status: %lx ",i,*bd_base++);
printk("addr: %lx\n", *bd_base++);
}
 
for(i=0;i<OETH_RXBD_NUM;i++)
{
printk("oeth: rx_bd%d: len_status: %lx ",i,*bd_base++);
printk("addr: %lx\n", *bd_base++);
}
}
 
 
 
void send_packet()
{
/* This should be 98 bytes big */
char ping_packet[] = {
0x00, 0x24, 0xe8, 0x91, 0x7c, 0x0d, /*DST MAC*/
0x00, 0xe0, 0x18, 0x73, 0x1d, 0x05, /*SRC MAC*/
0x08, 0x00, /*TYPE*/
/* IP */
0x45, /* Version, header length*/
0x00, /* Differentiated services field */
0x00, 0x54, /* Total length */
0x00, 0x00, /* Identification */
0x40, /* Flags */
0x00, /* Fragment offset */
0x40, /* Time to live */
0x01, /* Protocol (0x01 = ICMP */
0xef, 0xf3, /* Header checksum */
0xc0, 0xa8, 0x64, 0xfb, /* Source IP */
0xc0, 0xa8, 0x64, 0x69, /* Dest. IP */
/* ICMP Message body */
0x08, 0x00, 0x9a, 0xd4, 0xc8, 0x18, 0x00, 0x01, 0xd9, 0x8c, 0x54,
0x4a, 0x7b, 0x37, 0x01, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
};
 
/*Send packet */
tx_packet((void*) ping_packet, 98);
 
}
 
void printstring(char* string)
{
while (*string) uart_putc(*string++);
}
 
int main ()
{
last_char=0; /* Init for spin_cursor()*/
#ifndef RTLSIM
uart_init(); // init the UART before we can printf
printf("\n\tethphytest\n\n");
#endif
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */
//scan_ethphys(); /* Scan MIIM bus for PHYs */
//ethphy_init(); /* Attempt reset and configuration of PHY via MIIM */
//ethmac_scanstatus(); /* Enable scanning of status register via MIIM */
 
//oeth_monitor_rx();
 
send_packet();
 
#ifdef RTLSIM
report(0xdeaddead);
or32_exit(0);
#else
while(1)
spin_cursor();
#endif
 
}
/openrisc/trunk/orpsocv2/sw/eth/ethphy_micrel.h
0,0 → 1,43
 
/* Micrel KSZ8001 PHY configuration */
/* Register addresses */
#define MICREL_KSZ8001_BCR_ADR 0x0 /* Basic Control Register */
#define MICREL_KSZ8001_BSR_ADR 0x1 /* Basic Status Register */
#define MICREL_KSZ8001_PI1_ADR 0x2 /* PHY Identifier I */
#define MICREL_KSZ8001_PI2_ADR 0x3 /* PHY Identifier II */
#define MICREL_KSZ8001_ANAR_ADR 0x4 /* Auto-Negotiation Advertisement Register */
#define MICREL_KSZ8001_ANLPAR_ADR 0x5 /* Auto-Negotiation Link Partner Ability Register */
#define MICREL_KSZ8001_ANER_ADR 0x6 /* Auto-Negotiation Expansion Register */
#define MICREL_KSZ8001_ANNPR_ADR 0x7 /* Auto-Negotiation Next Page Register */
#define MICREL_KSZ8001_LPNPA_ADR 0x8 /* Link Partner Next Page Ability */
#define MICREL_KSZ8001_RXERCR_ADR 0x15 /* RXER Counter Register */
#define MICREL_KSZ8001_ICSR_ADR 0x1b /* Interrupt Control/Status Register */
#define MICREL_KSZ8001_LMDCSR_ADR 0x1d /* LinkMD Control/Status Register */
#define MICREL_KSZ8001_PCR_ADR 0x1e /* PHY Control Register */
#define MICREL_KSZ8001_100BTPCR_ADR 0x1f /* 100BASE-TX PHY Control Register */
 
/* Basic Control Register bits */
#define MICREL_KSZ8001_BCR_DIS_TRANS (1<<0) /* Disable Transmitter */
#define MICREL_KSZ8001_BCR_COL_TEST (1<<7) /* Collision Test */
#define MICREL_KSZ8001_BCR_DUP (1<<8) /* Duplex Mode */
#define MICREL_KSZ8001_BCR_RST_AUTONEG (1<<9) /* Restart Auto-Negotiation */
#define MICREL_KSZ8001_BCR_ISOLATE (1<<10) /* Isolate */
#define MICREL_KSZ8001_BCR_PWR_DOWN (1<<11) /* Power Down */
#define MICREL_KSZ8001_BCR_AUTONEG_EN (1<<12) /* Auto-Negotiation Enable */
#define MICREL_KSZ8001_BCR_SPD_SEL (1<<13) /* Speed Select */
#define MICREL_KSZ8001_BCR_LOOP_BACK (1<<14) /* Loop Back */
#define MICREL_KSZ8001_BCR_RESET (1<<15)/* Reset */
 
/* Basic Status Register bits */
#define MICREL_KSZ8001_BSR_EC (1<<0) /* Extended Capability */
#define MICREL_KSZ8001_BSR_JD (1<<1) /* Jabber Detect */
#define MICREL_KSZ8001_BSR_LS (1<<2) /* Link Status */
#define MICREL_KSZ8001_BSR_AUTONEG_ABLE (1<<3) /* Auto-Negotiation Ability */
#define MICREL_KSZ8001_BSR_RF (1<<4) /* Remote Fault */
#define MICREL_KSZ8001_BSR_AUTONEG_CMPLT (1<<5) /* Auto-Negotiation Complete */
#define MICREL_KSZ8001_BSR_NP (1<<6) /* No Premble */
#define MICREL_KSZ8001_BSR_10BTHD (1<<11) /* 10BASE-T Half Duplex */
#define MICREL_KSZ8001_BSR_10BTFD (1<<12) /* 10BASE-T Full Duplex */
#define MICREL_KSZ8001_BSR_100BTXHD (1<<13) /* 100BASE-TX Half Duplex */
#define MICREL_KSZ8001_BSR_100BTXFD (1<<14) /* 100BASE-TX Full Duplex */
#define MICREL_KSZ8001_BSR_100BT4 (1<<15) /* 100BASE-T4 Capable */
/openrisc/trunk/orpsocv2/sw/eth/open_eth.h
0,0 → 1,149
 
typedef unsigned int uint;
 
/* Ethernet configuration registers */
typedef struct _oeth_regs {
uint moder; /* Mode Register */
uint int_src; /* Interrupt Source Register */
uint int_mask; /* Interrupt Mask Register */
uint ipgt; /* Back to Bak Inter Packet Gap Register */
uint ipgr1; /* Non Back to Back Inter Packet Gap Register 1 */
uint ipgr2; /* Non Back to Back Inter Packet Gap Register 2 */
uint packet_len; /* Packet Length Register (min. and max.) */
uint collconf; /* Collision and Retry Configuration Register */
uint tx_bd_num; /* Transmit Buffer Descriptor Number Register */
uint ctrlmoder; /* Control Module Mode Register */
uint miimoder; /* MII Mode Register */
uint miicommand; /* MII Command Register */
uint miiaddress; /* MII Address Register */
uint miitx_data; /* MII Transmit Data Register */
uint miirx_data; /* MII Receive Data Register */
uint miistatus; /* MII Status Register */
uint mac_addr0; /* MAC Individual Address Register 0 */
uint mac_addr1; /* MAC Individual Address Register 1 */
uint hash_addr0; /* Hash Register 0 */
uint hash_addr1; /* Hash Register 1 */
} oeth_regs;
 
/* Ethernet buffer descriptor */
typedef struct _oeth_bd {
#if 0
ushort len; /* Buffer length */
ushort status; /* Buffer status */
#else
uint len_status;
#endif
uint addr; /* Buffer address */
} oeth_bd;
 
// From include/asm/board.h
#define ETH_BASE_ADD 0x92000000
 
#define OETH_REG_BASE ETH_BASE_ADD
#define OETH_BD_BASE (ETH_BASE_ADD + 0x400)
#define OETH_TOTAL_BD 128
#define OETH_MAXBUF_LEN 0x600
/* Tx BD */
#define OETH_TX_BD_READY 0x8000 /* Tx BD Ready */
#define OETH_TX_BD_IRQ 0x4000 /* Tx BD IRQ Enable */
#define OETH_TX_BD_WRAP 0x2000 /* Tx BD Wrap (last BD) */
#define OETH_TX_BD_PAD 0x1000 /* Tx BD Pad Enable */
#define OETH_TX_BD_CRC 0x0800 /* Tx BD CRC Enable */
#define OETH_TX_BD_UNDERRUN 0x0100 /* Tx BD Underrun Status */
#define OETH_TX_BD_RETRY 0x00F0 /* Tx BD Retry Status */
#define OETH_TX_BD_RETLIM 0x0008 /* Tx BD Retransmission Limit Status */
#define OETH_TX_BD_LATECOL 0x0004 /* Tx BD Late Collision Status */
#define OETH_TX_BD_DEFER 0x0002 /* Tx BD Defer Status */
#define OETH_TX_BD_CARRIER 0x0001 /* Tx BD Carrier Sense Lost Status */
#define OETH_TX_BD_STATS (OETH_TX_BD_UNDERRUN | \
OETH_TX_BD_RETRY | \
OETH_TX_BD_RETLIM | \
OETH_TX_BD_LATECOL | \
OETH_TX_BD_DEFER | \
OETH_TX_BD_CARRIER)
/* Rx BD */
#define OETH_RX_BD_EMPTY 0x8000 /* Rx BD Empty */
#define OETH_RX_BD_IRQ 0x4000 /* Rx BD IRQ Enable */
#define OETH_RX_BD_WRAP 0x2000 /* Rx BD Wrap (last BD) */
#define OETH_RX_BD_MISS 0x0080 /* Rx BD Miss Status */
#define OETH_RX_BD_OVERRUN 0x0040 /* Rx BD Overrun Status */
#define OETH_RX_BD_INVSIMB 0x0020 /* Rx BD Invalid Symbol Status */
#define OETH_RX_BD_DRIBBLE 0x0010 /* Rx BD Dribble Nibble Status */
#define OETH_RX_BD_TOOLONG 0x0008 /* Rx BD Too Long Status */
#define OETH_RX_BD_SHORT 0x0004 /* Rx BD Too Short Frame Status */
#define OETH_RX_BD_CRCERR 0x0002 /* Rx BD CRC Error Status */
#define OETH_RX_BD_LATECOL 0x0001 /* Rx BD Late Collision Status */
#define OETH_RX_BD_STATS (OETH_RX_BD_MISS | \
OETH_RX_BD_OVERRUN | \
OETH_RX_BD_INVSIMB | \
OETH_RX_BD_DRIBBLE | \
OETH_RX_BD_TOOLONG | \
OETH_RX_BD_SHORT | \
OETH_RX_BD_CRCERR | \
OETH_RX_BD_LATECOL)
 
/* MODER Register */
#define OETH_MODER_RXEN 0x00000001 /* Receive Enable */
#define OETH_MODER_TXEN 0x00000002 /* Transmit Enable */
#define OETH_MODER_NOPRE 0x00000004 /* No Preamble */
#define OETH_MODER_BRO 0x00000008 /* Reject Broadcast */
#define OETH_MODER_IAM 0x00000010 /* Use Individual Hash */
#define OETH_MODER_PRO 0x00000020 /* Promiscuous (receive all) */
#define OETH_MODER_IFG 0x00000040 /* Min. IFG not required */
#define OETH_MODER_LOOPBCK 0x00000080 /* Loop Back */
#define OETH_MODER_NOBCKOF 0x00000100 /* No Backoff */
#define OETH_MODER_EXDFREN 0x00000200 /* Excess Defer */
#define OETH_MODER_FULLD 0x00000400 /* Full Duplex */
#define OETH_MODER_RST 0x00000800 /* Reset MAC */
#define OETH_MODER_DLYCRCEN 0x00001000 /* Delayed CRC Enable */
#define OETH_MODER_CRCEN 0x00002000 /* CRC Enable */
#define OETH_MODER_HUGEN 0x00004000 /* Huge Enable */
#define OETH_MODER_PAD 0x00008000 /* Pad Enable */
#define OETH_MODER_RECSMALL 0x00010000 /* Receive Small */
/* Interrupt Source Register */
#define OETH_INT_TXB 0x00000001 /* Transmit Buffer IRQ */
#define OETH_INT_TXE 0x00000002 /* Transmit Error IRQ */
#define OETH_INT_RXF 0x00000004 /* Receive Frame IRQ */
#define OETH_INT_RXE 0x00000008 /* Receive Error IRQ */
#define OETH_INT_BUSY 0x00000010 /* Busy IRQ */
#define OETH_INT_TXC 0x00000020 /* Transmit Control Frame IRQ */
#define OETH_INT_RXC 0x00000040 /* Received Control Frame IRQ */
 
/* Interrupt Mask Register */
#define OETH_INT_MASK_TXB 0x00000001 /* Transmit Buffer IRQ Mask */
#define OETH_INT_MASK_TXE 0x00000002 /* Transmit Error IRQ Mask */
#define OETH_INT_MASK_RXF 0x00000004 /* Receive Frame IRQ Mask */
#define OETH_INT_MASK_RXE 0x00000008 /* Receive Error IRQ Mask */
#define OETH_INT_MASK_BUSY 0x00000010 /* Busy IRQ Mask */
#define OETH_INT_MASK_TXC 0x00000020 /* Transmit Control Frame IRQ Mask */
#define OETH_INT_MASK_RXC 0x00000040 /* Received Control Frame IRQ Mask */
/* Control Module Mode Register */
#define OETH_CTRLMODER_PASSALL 0x00000001 /* Pass Control Frames */
#define OETH_CTRLMODER_RXFLOW 0x00000002 /* Receive Control Flow Enable */
#define OETH_CTRLMODER_TXFLOW 0x00000004 /* Transmit Control Flow Enable */
/* MII Mode Register */
#define OETH_MIIMODER_CLKDIV 0x000000FF /* Clock Divider */
#define OETH_MIIMODER_NOPRE 0x00000100 /* No Preamble */
#define OETH_MIIMODER_RST 0x00000200 /* MIIM Reset */
/* MII Command Register */
#define OETH_MIICOMMAND_SCANSTAT 0x00000001 /* Scan Status */
#define OETH_MIICOMMAND_RSTAT 0x00000002 /* Read Status */
#define OETH_MIICOMMAND_WCTRLDATA 0x00000004 /* Write Control Data */
/* MII Address Register */
#define OETH_MIIADDRESS_FIAD 0x0000001F /* PHY Address */
#define OETH_MIIADDRESS_RGAD 0x00001F00 /* RGAD Address */
/* MII Status Register */
#define OETH_MIISTATUS_LINKFAIL 0x00000001 /* Link Fail */
#define OETH_MIISTATUS_BUSY 0x00000002 /* MII Busy */
#define OETH_MIISTATUS_NVALID 0x00000004 /* Data in MII Status Register is invalid */
 
/openrisc/trunk/orpsocv2/sw/eth/eth-int.c
0,0 → 1,962
//////////////////////////////////////////////////////////////////////
//// ////
//// Interrupt-driven Ethernet test code ////
//// ////
//// Description ////
//// ORPSoC test software ////
//// ////
//// To Do: ////
//// - It's a simple test for now, but could be adapted for ////
//// standalone use. ////
//// ////
//// Author(s): ////
//// - jb, jb@orsoc.se, with parts taken from Linux kernel ////
//// open_eth driver. ////
//// ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 Authors and OPENCORES.ORG ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
 
#include "support.h"
#include "board.h"
#include "spr_defs.h"
#include "int.h"
#include "uart.h"
#include "open_eth.h"
 
#include "ethphy_micrel.h"
 
/* Dummy exception functions */
void buserr_except(){}
void dpf_except(){}
void ipf_except(){}
void lpint_except(){}
void align_except(){}
void illegal_except(){}
void hpint_except(){}
void dtlbmiss_except(){}
void itlbmiss_except(){}
void range_except(){}
void syscall_except(){}
void res1_except(){}
void trap_except(){}
void res2_except(){}
 
/* Exception efective address */
volatile unsigned long except_ea;
 
/* Eception PC */
volatile unsigned long except_pc;
 
volatile unsigned tx_done;
 
/* Functions in this file */
void ethmac_setup(void);
void oeth_printregs(void);
void ethphy_init(void);
void oeth_dump_bds();
/* Interrupt functions */
void oeth_interrupt(void);
static void oeth_rx(void);
static void oeth_tx(void);
 
/* Defining RTLSIM turns off use of real printf'ing to save time in simulation */
#define RTLSIM
 
#ifdef RTLSIM
#define printk
#else
#define printk printf
#endif
 
/* Let the ethernet packets use a space beginning here for buffering */
#define ETH_BUFF_BASE 0x01000000
 
 
#define RXBUFF_PREALLOC 1
#define TXBUFF_PREALLOC 1
//#undef RXBUFF_PREALLOC
//#undef TXBUFF_PREALLOC
 
/* The transmitter timeout
*/
#define TX_TIMEOUT (2*HZ)
 
/* Buffer number (must be 2^n)
*/
#define OETH_RXBD_NUM 8
#define OETH_TXBD_NUM 8
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1)
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1)
 
/* Buffer size
*/
#define OETH_RX_BUFF_SIZE 2048
#define OETH_TX_BUFF_SIZE 2048
 
/* OR32 Page size def */
#define PAGE_SHIFT 13
#define PAGE_SIZE (1UL << PAGE_SHIFT)
 
/* How many buffers per page
*/
#define OETH_RX_BUFF_PPGAE (PAGE_SIZE/OETH_RX_BUFF_SIZE)
#define OETH_TX_BUFF_PPGAE (PAGE_SIZE/OETH_TX_BUFF_SIZE)
 
/* How many pages is needed for buffers
*/
#define OETH_RX_BUFF_PAGE_NUM (OETH_RXBD_NUM/OETH_RX_BUFF_PPGAE)
#define OETH_TX_BUFF_PAGE_NUM (OETH_TXBD_NUM/OETH_TX_BUFF_PPGAE)
 
/* Buffer size (if not XXBUF_PREALLOC
*/
#define MAX_FRAME_SIZE 1518
 
/* The buffer descriptors track the ring buffers.
*/
struct oeth_private {
//struct sk_buff* rx_skbuff[OETH_RXBD_NUM];
//struct sk_buff* tx_skbuff[OETH_TXBD_NUM];
 
unsigned short tx_next; /* Next buffer to be sent */
unsigned short tx_last; /* Next buffer to be checked if packet sent */
unsigned short tx_full; /* Buffer ring fuul indicator */
unsigned short rx_cur; /* Next buffer to be checked if packet received */
oeth_regs *regs; /* Address of controller registers. */
oeth_bd *rx_bd_base; /* Address of Rx BDs. */
oeth_bd *tx_bd_base; /* Address of Tx BDs. */
// struct net_device_stats stats;
};
 
 
void oeth_printregs(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
printk("Oeth regs: Mode Register : 0x%lx\n",(unsigned long) regs->moder); /* Mode Register */
printk("Oeth regs: Interrupt Source Register 0x%lx\n", (unsigned long) regs->int_src); /* Interrupt Source Register */
printk("Oeth regs: Interrupt Mask Register 0x%lx\n",(unsigned long) regs->int_mask); /* Interrupt Mask Register */
printk("Oeth regs: Back to Bak Inter Packet Gap Register 0x%lx\n",(unsigned long) regs->ipgt); /* Back to Bak Inter Packet Gap Register */
printk("Oeth regs: Non Back to Back Inter Packet Gap Register 1 0x%lx\n",(unsigned long) regs->ipgr1); /* Non Back to Back Inter Packet Gap Register 1 */
printk("Oeth regs: Non Back to Back Inter Packet Gap Register 2 0x%lx\n",(unsigned long) regs->ipgr2); /* Non Back to Back Inter Packet Gap Register 2 */
printk("Oeth regs: Packet Length Register (min. and max.) 0x%lx\n",(unsigned long) regs->packet_len); /* Packet Length Register (min. and max.) */
printk("Oeth regs: Collision and Retry Configuration Register 0x%lx\n",(unsigned long) regs->collconf); /* Collision and Retry Configuration Register */
printk("Oeth regs: Transmit Buffer Descriptor Number Register 0x%lx\n",(unsigned long) regs->tx_bd_num); /* Transmit Buffer Descriptor Number Register */
printk("Oeth regs: Control Module Mode Register 0x%lx\n",(unsigned long) regs->ctrlmoder); /* Control Module Mode Register */
printk("Oeth regs: MII Mode Register 0x%lx\n",(unsigned long) regs->miimoder); /* MII Mode Register */
printk("Oeth regs: MII Command Register 0x%lx\n",(unsigned long) regs->miicommand); /* MII Command Register */
printk("Oeth regs: MII Address Register 0x%lx\n",(unsigned long) regs->miiaddress); /* MII Address Register */
printk("Oeth regs: MII Transmit Data Register 0x%lx\n",(unsigned long) regs->miitx_data); /* MII Transmit Data Register */
printk("Oeth regs: MII Receive Data Register 0x%lx\n",(unsigned long) regs->miirx_data); /* MII Receive Data Register */
printk("Oeth regs: MII Status Register 0x%lx\n",(unsigned long) regs->miistatus); /* MII Status Register */
printk("Oeth regs: MAC Individual Address Register 0 0x%lx\n",(unsigned long) regs->mac_addr0); /* MAC Individual Address Register 0 */
printk("Oeth regs: MAC Individual Address Register 1 0x%lx\n",(unsigned long) regs->mac_addr1); /* MAC Individual Address Register 1 */
printk("Oeth regs: Hash Register 0 0x%lx\n",(unsigned long) regs->hash_addr0); /* Hash Register 0 */
printk("Oeth regs: Hash Register 1 0x%lx\n",(unsigned long) regs->hash_addr1); /* Hash Register 1 */
}
 
static int last_char;
 
void spin_cursor(void)
{
#ifdef RTLSIM
return;
#endif
volatile unsigned int i; // So the loop doesn't get optimised away
printk(" \r");
if (last_char == 0)
printk("/");
else if (last_char == 1)
printk("-");
else if (last_char == 2)
printk("\\");
else if (last_char == 3)
printk("|");
else if (last_char == 4)
printk("/");
else if (last_char == 5)
printk("-");
else if (last_char == 6)
printk("\\");
else if (last_char == 7)
{
printk("|");
last_char=-1;
}
last_char++;
for(i=0;i<20000;i++);
 
}
 
#define PHYNUM 0
 
/* Scan the MIIM bus for PHYs */
void scan_ethphys(void)
{
unsigned int phynum,regnum, i;
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
regs->miitx_data = 0;
for(phynum=0;phynum<32;phynum++)
{
for (regnum=0;regnum<8;regnum++)
{
printk("scan_ethphys: phy %d r%d ",phynum, regnum);
/* Now actually perform the read on the MIIM bus*/
regs->miiaddress = (regnum << 8) | phynum; /* Basic Control Register */
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY);
printk("%x\n",regs->miirx_data);
}
}
}
 
void ethmac_scanstatus(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
//printk("Oeth: regs->miistatus %x regs->miirx_data %x\n",regs->miistatus, regs->miirx_data);
regs->miiaddress = 0;
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_SCANSTAT;
//printk("Oeth: regs->miiaddress %x regs->miicommand %x\n",regs->miiaddress, regs->miicommand);
//regs->miicommand = 0;
volatile int i; for(i=0;i<1000;i++);
while(regs->miistatus & OETH_MIISTATUS_BUSY) ;
//spin_cursor();
//printk("\r");
or32_exit(0);
}
void ethphy_init(void)
{
volatile int i;
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
/* Init the Micrel KSZ80001L PHY */
/* First reset it */
/* printk("Oeth: regs->miistatus %x regs->miirx_data %x\n",regs->miistatus, regs->miirx_data); */
/* regs->miiaddress = (MICREL_KSZ8001_BCR_ADR << 8); /\* PHY's Basic Control Register *\/ */
/* regs->miitx_data = MICREL_KSZ8001_BCR_RESET; */
/* regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; */
/* printk("Oeth: regs->miiaddress %x regs->miicommand %x\n",regs->miiaddress, regs->miicommand); */
/* regs->miicommand = 0; */
/* while(regs->miistatus & OETH_MIISTATUS_BUSY) */
/* spin_cursor(); */
/* printk("\r"); */
 
printk("Oeth: Reading PHY r0 (status reg)\n");
regs->miiaddress = MICREL_KSZ8001_BCR_ADR<<8 | PHYNUM; /* Basic Control Register */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
 
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
 
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
printk("\r");
/* while (regs->miirx_data & MICREL_KSZ8001_BCR_RESET) */
/* { */
/* regs->miiaddress = MICREL_KSZ8001_BCR_ADR<<8; /\* Basic Control Register *\/ */
/* regs->miitx_data = 0; */
/* regs->miicommand = OETH_MIICOMMAND_RSTAT; */
/* regs->miicommand = 0; */
/* while(regs->miistatus & OETH_MIISTATUS_BUSY) */
/* spin_cursor(); */
/* } */
/* printk("\r"); */
 
printk("\nOeth: PHY r0 value: %x\n",regs->miirx_data);
/* PHY reset and confirmed as such */
/* Now read the link status */
regs->miiaddress = MICREL_KSZ8001_BSR_ADR<<8 | PHYNUM; /* Basic Status Register */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
 
printk("\r");
printk("Oeth: PHY BSR: 0x%x\n",regs->miirx_data & 0xffff);
/* Read the operation mode */
regs->miiaddress = MICREL_KSZ8001_100BTPCR_ADR<<8 | PHYNUM; /* 100BASE-TX */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
printk("\r");
printk("Oeth: PHY 100BASE-TX PHY Control Register: 0x%x\n",regs->miirx_data);
 
 
/* Read the PHY identification register 1 */
regs->miiaddress = MICREL_KSZ8001_PI1_ADR<<8 | PHYNUM; /* PI1 */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
printk("\r");
printk("Oeth: PHY PHY Identifier I: 0x%x\n",regs->miirx_data);
 
/* Read the PHY identification register 2 */
regs->miiaddress = MICREL_KSZ8001_PI2_ADR<<8 | PHYNUM; /* PI2 */
regs->miitx_data = 0;
regs->miicommand = OETH_MIICOMMAND_RSTAT;
while(!(regs->miistatus & OETH_MIISTATUS_BUSY)); /* Wait for command to be registered*/
regs->miicommand = 0;
while(regs->miistatus & OETH_MIISTATUS_BUSY)
spin_cursor();
printk("\r");
printk("Oeth: PHY PHY Identifier II: 0x%x\n",regs->miirx_data);
 
 
}
 
 
void ethmac_setup(void)
{
// from arch/or32/drivers/open_eth.c
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
/*printk("\nbefore reset\n\n");
oeth_printregs();*/
 
/* Reset MII mode module */
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */
regs->miimoder = 0x64; /* Clock divider for MII Management interface */
/* Reset the controller.
*/
regs->moder = OETH_MODER_RST; /* Reset ON */
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */
//printk("\nafter reset\n\n");
//oeth_printregs();
/* Setting TXBD base to OETH_TXBD_NUM.
*/
regs->tx_bd_num = OETH_TXBD_NUM;
/* Set min/max packet length
*/
regs->packet_len = 0x00400600;
/* Set IPGT register to recomended value
*/
regs->ipgt = 0x12;
/* Set IPGR1 register to recomended value
*/
regs->ipgr1 = 0x0000000c;
/* Set IPGR2 register to recomended value
*/
regs->ipgr2 = 0x00000012;
/* Set COLLCONF register to recomended value
*/
regs->collconf = 0x000f003f;
/* Set control module mode
*/
#if 0
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW;
#else
regs->ctrlmoder = 0;
#endif
/* Clear MIIM registers */
regs->miitx_data = 0;
regs->miiaddress = 0;
regs->miicommand = 0;
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1;
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 | ETH_MACADDR4 << 8 | ETH_MACADDR5;
/* Clear all pending interrupts
*/
regs->int_src = 0xffffffff;
/* Promisc, IFG, CRCEn
*/
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN | OETH_MODER_FULLD;
/* Enable interrupt sources.
*/
 
regs->int_mask = OETH_INT_MASK_TXB |
OETH_INT_MASK_TXE |
OETH_INT_MASK_RXF |
OETH_INT_MASK_RXE |
OETH_INT_MASK_BUSY |
OETH_INT_MASK_TXC |
OETH_INT_MASK_RXC;
printk("\nafter config\n\n");
oeth_printregs();
 
// Buffer setup stuff
volatile oeth_bd *tx_bd, *rx_bd;
int i,j,k;
/* Initialize TXBD pointer
*/
tx_bd = (volatile oeth_bd *)OETH_BD_BASE;
/* Initialize RXBD pointer
*/
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
/* Preallocated ethernet buffer setup */
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */
 
/* Setup for TX buffers*/
for(i = 0, k = 0; i < OETH_TX_BUFF_PAGE_NUM; i++) {
for(j = 0; j < OETH_TX_BUFF_PPGAE; j++, k++) {
//tx_bd[k].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ;
tx_bd[k].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC;
tx_bd[k].addr = mem_addr;
mem_addr += OETH_TX_BUFF_SIZE;
}
}
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP;
 
/* Setup for RX buffers */
for(i = 0, k = 0; i < OETH_RX_BUFF_PAGE_NUM; i++) {
for(j = 0; j < OETH_RX_BUFF_PPGAE; j++, k++) {
rx_bd[k].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; /* Enable interrupt */
rx_bd[k].addr = mem_addr;
mem_addr += OETH_RX_BUFF_SIZE;
}
}
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; /* Final buffer has wrap bit set */
 
/* Enable receiver and transmiter
*/
regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN;
 
return;
}
 
/* Find the next available transmit buffer */
struct oeth_bd* get_next_tx_bd()
{
int i;
volatile oeth_bd *tx_bd;
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/
/* Go through the TX buffs, search for unused one */
for(i = 0; i < OETH_TXBD_NUM; i++) {
if(!(tx_bd[i].len_status & OETH_TX_BD_READY)) /* Looking for buffer NOT ready for transmit. ie we can manipulate it */
{
printk("Oeth: Using TX_bd at 0x%lx\n",(unsigned long)&tx_bd[i]);
return (struct oeth_bd*) &tx_bd[i];
}
}
 
printk("No free tx buffers\n");
/* Set to null our returned buffer */
tx_bd = (volatile oeth_bd *) 0;
return (struct oeth_bd*) tx_bd;
}
 
 
/* print packet contents */
static void
oeth_print_packet(unsigned long add, int len)
{
int i;
printk("ipacket: add = %lx len = %d\n", add, len);
for(i = 0; i < len; i++) {
if(!(i % 16))
printk("\n");
printk(" %.2x", *(((unsigned char *)add) + i));
}
printk("\n");
}
 
/* Setup buffer descriptors with data */
/* length is in BYTES */
void tx_packet(void* data, int length)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
volatile oeth_bd *tx_bd;
volatile int i;
if((tx_bd = (volatile oeth_bd *) get_next_tx_bd()) == NULL)
{
printk("No more TX buffers available\n");
return;
}
printk("Oeth: TX_bd buffer address: 0x%lx\n",(unsigned long) tx_bd->addr);
/* Clear all of the status flags.
*/
tx_bd->len_status &= ~OETH_TX_BD_STATS;
/* If the frame is short, tell CPM to pad it.
*/
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
if (length <= ETH_ZLEN)
tx_bd->len_status |= OETH_TX_BD_PAD;
else
tx_bd->len_status &= ~OETH_TX_BD_PAD;
printk("Oeth: Copying %d bytes from 0x%lx to TX_bd buffer at 0x%lx\n",length,(unsigned long) data,(unsigned long) tx_bd->addr);
/* Copy the data into the transmit buffer, byte at a time */
char* data_p = (char*) data;
char* data_b = (char*) tx_bd->addr;
for(i=0;i<length;i++)
{
*(data_b+i) = *(data_p+i);
}
printk("Oeth: Data copied to buffer\n");
/* Set the length of the packet's data in the buffer descriptor */
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) |
((length&0xffff) << 16);
 
//oeth_print_packet(tx_bd->addr, (tx_bd->len_status >> 16));
 
/* Send it on its way. Tell controller its ready, interrupt when sent
* and to put the CRC on the end.
*/
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ);
 
oeth_dump_bds();
 
printk("Oeth: MODER addr: 0x%x\n", regs->moder);
 
printk("Oeth: TXBD Status 0x%x\n", tx_bd->len_status);
i=0;
 
/* Wait for BD READY bit to be cleared, indicating it's been sent */
/* Not if we've got interrupts enabled. */
/*
while (OETH_TX_BD_READY & tx_bd->len_status)
{
#ifndef RTLSIM
//for(i=0;i<40000;i++);
//printk("Oeth: TXBD Status 0x%x\n", tx_bd->len_status);
//oeth_printregs();
spin_cursor();
if (i++%64==63) {oeth_dump_bds();}
#endif
}
*/
 
return;
 
 
}
 
/* enable RX, loop waiting for arrived packets and print them out */
void oeth_monitor_rx(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
/* Set RXEN in MAC MODER */
regs->moder = OETH_MODER_RXEN | regs->moder;
 
volatile oeth_bd *rx_bd;
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
 
volatile int i;
while (1)
{
for(i=0;i<OETH_RXBD_NUM;i++)
{
if (!(rx_bd[i].len_status & OETH_RX_BD_EMPTY)) /* Not empty */
{
// Something in this buffer!
printk("Oeth: RX in buf %d - len_status: 0x%lx\n",i, rx_bd[i].len_status);
oeth_print_packet(rx_bd[i].addr, rx_bd[i].len_status >> 16);
/* Clear recieved bit */
rx_bd[i].len_status |= OETH_RX_BD_EMPTY;
printk("\t end of packet\n\n");
}
}
}
}
 
/* Print out all buffer descriptors */
void oeth_dump_bds()
{
unsigned long* bd_base = (unsigned long*) OETH_BD_BASE;
 
int i;
for(i=0;i<OETH_TXBD_NUM;i++)
{
printk("oeth: tx_bd%d: len_status: %lx ",i,*bd_base++);
printk("addr: %lx\n", *bd_base++);
}
 
for(i=0;i<OETH_RXBD_NUM;i++)
{
printk("oeth: rx_bd%d: len_status: %lx ",i,*bd_base++);
printk("addr: %lx\n", *bd_base++);
}
}
 
 
 
void send_packet()
{
/* This should be 98 bytes big */
char ping_packet[] = {
0x00, 0x24, 0xe8, 0x91, 0x7c, 0x0d, /*DST MAC*/
0x00, 0xe0, 0x18, 0x73, 0x1d, 0x05, /*SRC MAC*/
0x08, 0x00, /*TYPE*/
/* IP */
0x45, /* Version, header length*/
0x00, /* Differentiated services field */
0x00, 0x54, /* Total length */
0x00, 0x00, /* Identification */
0x40, /* Flags */
0x00, /* Fragment offset */
0x40, /* Time to live */
0x01, /* Protocol (0x01 = ICMP */
0xef, 0xf3, /* Header checksum */
0xc0, 0xa8, 0x64, 0xfb, /* Source IP */
0xc0, 0xa8, 0x64, 0x69, /* Dest. IP */
/* ICMP Message body */
0x08, 0x00, 0x9a, 0xd4, 0xc8, 0x18, 0x00, 0x01, 0xd9, 0x8c, 0x54,
0x4a, 0x7b, 0x37, 0x01, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
};
 
/*Send packet */
tx_packet((void*) ping_packet, 98);
 
}
 
void printstring(char* string)
{
while (*string) uart_putc(*string++);
}
 
 
 
/* The interrupt handler.
*/
void
oeth_interrupt(void)
{
 
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
uint int_events;
int serviced;
serviced = 0;
 
#ifndef RTLSIM
printk(".");
printk("\n=tx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
((oeth_bd *)(OETH_BD_BASE))->len_status,
((oeth_bd *)(OETH_BD_BASE+8))->len_status,
((oeth_bd *)(OETH_BD_BASE+16))->len_status,
((oeth_bd *)(OETH_BD_BASE+24))->len_status,
((oeth_bd *)(OETH_BD_BASE+32))->len_status,
((oeth_bd *)(OETH_BD_BASE+40))->len_status,
((oeth_bd *)(OETH_BD_BASE+48))->len_status,
((oeth_bd *)(OETH_BD_BASE+56))->len_status);
printk("=rx_ | %x | %x | %x | %x | %x | %x | %x | %x\n",
((oeth_bd *)(OETH_BD_BASE+64))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+8))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+16))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+24))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+32))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+40))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+48))->len_status,
((oeth_bd *)(OETH_BD_BASE+64+56))->len_status);
#endif
/* Get the interrupt events that caused us to be here.
*/
int_events = regs->int_src;
regs->int_src = int_events;
 
/* Handle receive event in its own function.
*/
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) {
serviced |= 0x1;
oeth_rx();
}
 
/* Handle transmit event in its own function.
*/
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) {
serviced |= 0x2;
oeth_tx();
}
 
/* Check for receive busy, i.e. packets coming but no place to
* put them.
*/
if (int_events & OETH_INT_BUSY) {
serviced |= 0x4;
#ifndef RTLSIM
printk("b");
#endif
if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE)))
oeth_rx();
}
 
 
#if 0
if (serviced == 0) {
void die(const char * str, struct pt_regs * regs, long err);
int show_stack(unsigned long *esp);
printk("!");
// printk("unserviced irq\n");
// show_stack(NULL);
// die("unserviced irq\n", regs, 801);
}
#endif
 
if (serviced == 0)
#ifdef RTLSIM
report(0);
#else
printk("\neth interrupt called but nothing serviced\n");
#endif
else /* Something happened ... either RX or TX */
#ifdef RTLSIM
report(0xdeaddead);
#else
printk(" | serviced 0x%x\n", serviced);
#endif
 
return;
}
 
 
 
static void
oeth_rx(void)
{
volatile oeth_regs *regs;
regs = (oeth_regs *)(OETH_REG_BASE);
 
volatile oeth_bd *rx_bdp;
int pkt_len, i;
int bad = 0;
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM;
printk("r");
/* Find RX buffers marked as having received data */
for(i = 0; i < OETH_RXBD_NUM; i++)
{
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ /* Looking for NOT empty buffers desc. */
/* Check status for errors.
*/
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) {
bad = 1;
}
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) {
bad = 1;
}
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) {
bad = 1;
}
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) {
bad = 1;
}
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) {
}
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) {
bad = 1;
}
if (bad) {
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS;
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY;
 
continue;
}
else {
/* Process the incoming frame.
*/
pkt_len = rx_bdp[i].len_status >> 16;
/* Do something here with the data - copy it into userspace, perhaps. */
 
#ifdef RTLSIM
report(pkt_len);
#else
oeth_print_packet(rx_bdp[i].addr, rx_bdp[i].len_status >> 16);
printk("\t end of packet\n\n");
#endif
/* finish up */
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */
}
}
}
}
 
 
 
static void
oeth_tx(void)
{
volatile oeth_bd *tx_bd;
int i;
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/
/* Go through the TX buffs, search for one that was just sent */
for(i = 0; i < OETH_TXBD_NUM; i++)
{
/* Looking for buffer NOT ready for transmit. and IRQ enabled */
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) )
{
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ;
 
/* Probably good to check for TX errors here */
/* set our test variable */
tx_done = 1;
 
printk("T%d",i);
}
}
return;
}
 
 
 
int main ()
{
/* Install interrupt handler */
excpt_int = (unsigned long)int_main;
 
/* Initialise handler vector */
int_init();
 
/* Install ethernet interrupt handler, it is enabled here too */
int_add(IRQ_ETH_0, oeth_interrupt, 0);
 
/* Enable interrupts in supervisor register */
mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_IEE);
last_char=0; /* Variable init for spin_cursor() */
 
#ifndef RTLSIM
uart_init(); // init the UART before we can printf
printf("\n\teth interrupts test\n\n");
#endif
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */
//scan_ethphys(); /* Scan MIIM bus for PHYs */
//ethphy_init(); /* Attempt reset and configuration of PHY via MIIM */
//ethmac_scanstatus(); /* Enable scanning of status register via MIIM */
 
//oeth_monitor_rx();
 
/* clear tx_done, the tx interrupt handler will set it when it's been transmitted */
tx_done = 0;
 
send_packet();
 
while(tx_done==0);
 
#ifdef RTLSIM
report(0xdeaddead);
or32_exit(0);
#else
while(1)
spin_cursor();
#endif
 
}
/openrisc/trunk/orpsocv2/sw/eth/except.S
0,0 → 1,193
#include "spr_defs.h"
#include "board.h"
 
// Linked from 0x200, so add 0x200 to the .org for the physical address
.section .vectors, "ax"
 
/*
.org 0x100
_reset:
l.nop
l.j _reset_except
l.nop
*/
.org 0x000
_except_200:
l.nop
l.j _buserr_except
l.nop
 
.org 0x100
_except_300:
l.nop
l.j _dpf_except
l.nop
 
.org 0x200
_except_400:
l.nop
l.j _ipf_except
l.nop
 
.org 0x300
_except_500:
l.nop
l.j _lpint_except
l.nop
 
.org 0x400
_except_600:
l.nop
l.j _align_except
l.nop
 
.org 0x500
_except_700:
l.nop
l.j _illegal_except
l.nop
 
.org 0x600
 
_int_vector:
l.nop
l.addi r1,r1,-116
l.sw 0x18(r1),r9
l.jal store_regs
l.nop
 
l.mfspr r3,r0,SPR_EPCR_BASE
l.movhi r4,hi(_except_pc)
l.ori r4,r4,lo(_except_pc)
l.sw 0(r4),r3
 
l.mfspr r3,r0,SPR_EEAR_BASE
l.movhi r4,hi(_except_ea)
l.ori r4,r4,lo(_except_ea)
l.sw 0(r4),r3
 
l.movhi r9,hi(end_except)
l.ori r9,r9,lo(end_except)
l.movhi r10,hi(_excpt_int)
l.ori r10,r10,lo(_excpt_int)
l.lwz r10,0(r10)
l.jr r10
l.nop
 
.org 0x700
_except_900:
l.nop
l.j _dtlbmiss_except
l.nop
 
.org 0x800
_except_a00:
l.nop
l.j _itlbmiss_except
l.nop
 
.org 0x900
_except_b00:
l.nop
l.j _range_except
l.nop
 
.org 0xa00
_except_c00:
l.nop
l.j _syscall_except
l.nop
 
.org 0xb00
_except_d00:
l.nop
l.j _res1_except
l.nop
 
 
.org 0xc00
_except_e00:
l.nop
l.j _trap_except
l.nop
 
 
store_regs:
l.sw 0x00(r1),r3
l.sw 0x04(r1),r4
l.sw 0x08(r1),r5
l.sw 0x0c(r1),r6
l.sw 0x10(r1),r7
l.sw 0x14(r1),r8
l.sw 0x1c(r1),r10
l.sw 0x20(r1),r11
l.sw 0x24(r1),r12
l.sw 0x28(r1),r13
l.sw 0x2c(r1),r14
l.sw 0x30(r1),r15
l.sw 0x34(r1),r16
l.sw 0x38(r1),r17
l.sw 0x3c(r1),r18
l.sw 0x40(r1),r19
l.sw 0x44(r1),r20
l.sw 0x48(r1),r21
l.sw 0x4c(r1),r22
l.sw 0x50(r1),r23
l.sw 0x54(r1),r24
l.sw 0x58(r1),r25
l.sw 0x5c(r1),r26
l.sw 0x60(r1),r27
l.sw 0x64(r1),r28
l.sw 0x68(r1),r29
l.sw 0x6c(r1),r30
l.sw 0x70(r1),r31
l.jr r9
l.nop
 
end_except:
l.lwz r3,0x00(r1)
l.lwz r4,0x04(r1)
l.lwz r5,0x08(r1)
l.lwz r6,0x0c(r1)
l.lwz r7,0x10(r1)
l.lwz r8,0x14(r1)
l.lwz r9,0x18(r1)
l.lwz r10,0x1c(r1)
l.lwz r11,0x20(r1)
l.lwz r12,0x24(r1)
l.lwz r13,0x28(r1)
l.lwz r14,0x2c(r1)
l.lwz r15,0x30(r1)
l.lwz r16,0x34(r1)
l.lwz r17,0x38(r1)
l.lwz r18,0x3c(r1)
l.lwz r19,0x40(r1)
l.lwz r20,0x44(r1)
l.lwz r21,0x48(r1)
l.lwz r22,0x4c(r1)
l.lwz r23,0x50(r1)
l.lwz r24,0x54(r1)
l.lwz r25,0x58(r1)
l.lwz r26,0x5c(r1)
l.lwz r27,0x60(r1)
l.lwz r28,0x64(r1)
l.lwz r29,0x68(r1)
l.lwz r30,0x6c(r1)
l.lwz r31,0x70(r1)
l.addi r1,r1,116
l.mtspr r0,r9,SPR_EPCR_BASE
l.rfe
l.nop
openrisc/trunk/orpsocv2/sw/eth/except.S Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: openrisc/trunk/orpsocv2/sw/eth/Makefile =================================================================== --- openrisc/trunk/orpsocv2/sw/eth/Makefile (nonexistent) +++ openrisc/trunk/orpsocv2/sw/eth/Makefile (revision 44) @@ -0,0 +1,27 @@ +include ../support/Makefile.inc + + +# We use our own except here, containing interrupt handler vector +common = except.o ../support/libsupport.a + + +all: eth-basic eth-int + +eth-basic: eth-basic.o ../support/reset-nocache.o $(common) + $(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -T ../support/orp.ld $? -o $@.or32 $(GCC_LIB_OPTS) + $(OR32_TOOL_PREFIX)-objcopy -O binary $@.or32 $@.bin + ../utils/bin2hex $@.bin 1 -size_word > $@$(FLASH_MEM_HEX_FILE_SUFFIX).hex + ../utils/bin2vmem $@.bin > $@.vmem + +eth-int: eth-int.o ../support/reset-nocache.o $(common) + $(OR32_TOOL_PREFIX)-gcc $(GCC_OPT) -T ../support/orp.ld $? -o $@.or32 $(GCC_LIB_OPTS) + $(OR32_TOOL_PREFIX)-objcopy -O binary $@.or32 $@.bin + ../utils/bin2hex $@.bin 1 -size_word > $@$(FLASH_MEM_HEX_FILE_SUFFIX).hex + ../utils/bin2vmem $@.bin > $@.vmem + + +%.o: %.c + $(OR32_TOOL_PREFIX)-gcc -DRTLSIM -I ../support $(GCC_OPT) -O2 -g -c -Wall $< -o $@ + +%.o: %.S + $(OR32_TOOL_PREFIX)-gcc -DRTLSIM -I ../support $(GCC_OPT) -O2 -g -c -Wall $< -o $@ Index: openrisc/trunk/orpsocv2/sw/dhry/dhry.c =================================================================== --- openrisc/trunk/orpsocv2/sw/dhry/dhry.c (revision 43) +++ openrisc/trunk/orpsocv2/sw/dhry/dhry.c (revision 44) @@ -16,8 +16,9 @@ */ #include "support.h" #include "dhry.h" - +#ifndef NUM_RUNS #define NUM_RUNS (1) +#endif #define DLX_FREQ 200 /* in MHz */ #define PROC_6 1
/openrisc/trunk/orpsocv2/sw/dhry/Makefile
4,6 → 4,12
#common = ../support/libsupport.a
common = ../support/libsupport.a ../support/except.o
 
ifdef NUM_RUNS
NUM_RUNS=($(NUM_RUNS))
else
NUM_RUNS="(10)"
endif
 
all: $(cases)
 
dhry-nocache-O0: dhry-O0.o ../support/reset-nocache.o $(common)
28,7 → 34,7
 
 
dhry-O0.o: dhry.c
$(OR32_TOOL_PREFIX)-gcc -I../support -O0 $(GCC_OPT) $? -mhard-div -c -o $@
$(OR32_TOOL_PREFIX)-gcc -DNUM_RUNS=$(NUM_RUNS) -I../support -O0 $(GCC_OPT) $? -mhard-div -c -o $@
 
dhry-O2.o: dhry.c
$(OR32_TOOL_PREFIX)-gcc -I../support -O2 $(GCC_OPT) $? -mhard-div -c -o $@
$(OR32_TOOL_PREFIX)-gcc -DNUM_RUNS=$(NUM_RUNS) -I../support -O2 $(GCC_OPT) $? -mhard-div -c -o $@
/openrisc/trunk/orpsocv2/sw/support/int.h
13,3 → 13,6
 
/* Initialize routine */
int int_init();
 
/* Actual interrup handler function */
void int_main();
/openrisc/trunk/orpsocv2/sw/support/Makefile.inc
4,7 → 4,7
 
#GCC_LIB_OPTS= -lgcc -liberty
 
GCC_OPT=-mhard-mul
GCC_OPT=-mhard-mul -g
 
ifdef UART_PRINTF
GCC_OPT += -DUART_PRINTF
/openrisc/trunk/orpsocv2/sw/support/except.S
1,6 → 1,6
#include "spr_defs.h"
 
// Linked from 0x200, so subtract 0x200 from each .org
// Linked from 0x200, so add 0x200 to the .org for the physical address
.section .vectors, "ax"
 
/*
/openrisc/trunk/orpsocv2/sw/support/board.h
20,7 → 20,8
#define UART_BASE 0x90000000
#define UART_IRQ 19
#define ETH_BASE 0xD0000000
#define ETH_IRQ 15
//#define ETH_IRQ 15
#define IRQ_ETH_0 (4) /* interrupt source for Ethernet dvice 0 */
#define MC_BASE_ADDR 0x60000000
#define SPI_BASE 0xa0000000
 

powered by: WebSVN 2.1.0

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