URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc
- from Rev 529 to Rev 530
- ↔ Reverse comparison
Rev 529 → Rev 530
/trunk/orpsocv2/rtl/verilog/ethmac/eth_wishbone.v
142,22 → 142,22
|
// Rx Status signals |
input InvalidSymbol; // Invalid symbol was received during |
// reception in 100 Mbps mode |
// reception in 100 Mbps mode |
input LatchedCrcError; // CRC error |
input RxLateCollision; // Late collision occured while receiving |
// frame |
// frame |
input ShortFrame; // Frame shorter then the minimum size |
// (r_MinFL) was received while small |
// packets are enabled (r_RecSmall) |
// (r_MinFL) was received while small |
// packets are enabled (r_RecSmall) |
input DribbleNibble; // Extra nibble received |
input ReceivedPacketTooBig;// Received packet is bigger than |
// r_MaxFL |
// r_MaxFL |
input [15:0] RxLength; // Length of the incoming frame |
input LoadRxStatus; // Rx status was loaded |
input ReceivedPacketGood;// Received packet's length and CRC are |
// good |
// good |
input AddressMiss; // When a packet is received AddressMiss |
// status is written to the Rx BD |
// status is written to the Rx BD |
input r_RxFlow; |
input r_PassAll; |
input ReceivedPauseFrm; |
165,13 → 165,13
// Tx Status signals |
input [3:0] RetryCntLatched; // Latched Retry Counter |
input RetryLimit; // Retry limit reached (Retry Max value + |
// 1 attempts were made) |
// 1 attempts were made) |
input LateCollLatched; // Late collision occured |
input DeferLatched; // Defer indication (Frame was defered |
// before sucessfully sent) |
// before sucessfully sent) |
output RstDeferLatched; |
input CarrierSenseLost; // Carrier Sense was lost during the |
// frame transmission |
// frame transmission |
|
// Tx |
input MTxClk; // Transmit clock (from PHY) |
193,7 → 193,7
input RxStartFrm; // |
input RxEndFrm; // |
input RxAbort; // This signal is set when address doesn't |
// match. |
// match. |
output RxStatusWriteLatched_sync2; |
|
//Register |
360,83 → 360,188
reg RxPointerRead/* synthesis syn_allow_retiming=0*/; |
|
// RX shift ending signals |
reg ShiftEnded_rck; |
reg ShiftEndedSync1; |
reg ShiftEndedSync2; |
reg ShiftEndedSync3; |
reg ShiftEndedSync_c1; |
reg ShiftEndedSync_c2; |
reg ShiftEnded_rck; |
reg ShiftEndedSync1; |
reg ShiftEndedSync2; |
reg ShiftEndedSync3; |
reg ShiftEndedSync_c1; |
reg ShiftEndedSync_c2; |
|
wire StartShiftWillEnd; |
wire StartShiftWillEnd; |
|
// Pulse for wishbone side having finished writing back |
reg rx_wb_writeback_finished; |
reg rx_wb_writeback_finished; |
// Indicator of last set of writes from the Wishbone master coming up |
reg rx_wb_last_writes; |
reg rx_wb_last_writes; |
|
|
reg StartOccured; |
reg TxStartFrm_sync1; |
reg TxStartFrm_sync2; |
reg TxStartFrm_syncb1; |
reg TxStartFrm_syncb2; |
reg StartOccured; |
reg TxStartFrm_sync1; |
reg TxStartFrm_sync2; |
reg TxStartFrm_syncb1; |
reg TxStartFrm_syncb2; |
|
|
wire TxFifoClear; |
wire TxBufferAlmostFull; |
wire TxBufferFull; |
wire TxBufferEmpty; |
wire TxBufferAlmostEmpty; |
wire SetReadTxDataFromMemory; |
reg BlockReadTxDataFromMemory/* synthesis syn_allow_retiming=0*/; |
wire TxFifoClear; |
wire TxBufferAlmostFull; |
wire TxBufferFull; |
wire TxBufferEmpty; |
wire TxBufferAlmostEmpty; |
wire SetReadTxDataFromMemory; |
reg BlockReadTxDataFromMemory/* synthesis syn_allow_retiming=0*/; |
|
reg tx_burst_en; |
reg rx_burst_en; |
reg [`ETH_BURST_CNT_WIDTH-1:0] tx_burst_cnt; |
reg tx_burst_en; |
reg rx_burst_en; |
reg [`ETH_BURST_CNT_WIDTH-1:0] tx_burst_cnt; |
|
wire ReadTxDataFromMemory_2; |
wire tx_burst; |
wire ReadTxDataFromMemory_2; |
wire tx_burst; |
|
wire [31:0] TxData_wb; |
wire ReadTxDataFromFifo_wb; |
wire [31:0] TxData_wb; |
wire ReadTxDataFromFifo_wb; |
|
wire [`ETH_TX_FIFO_CNT_WIDTH-1:0] txfifo_cnt; |
wire [`ETH_RX_FIFO_CNT_WIDTH-1:0] rxfifo_cnt; |
wire [`ETH_TX_FIFO_CNT_WIDTH-1:0] txfifo_cnt; |
wire [`ETH_RX_FIFO_CNT_WIDTH-1:0] rxfifo_cnt; |
|
reg [`ETH_BURST_CNT_WIDTH-1:0] rx_burst_cnt; |
reg [`ETH_BURST_CNT_WIDTH-1:0] rx_burst_cnt; |
|
wire rx_burst; |
wire enough_data_in_rxfifo_for_burst; |
wire enough_data_in_rxfifo_for_burst_plus1; |
wire rx_burst; |
wire enough_data_in_rxfifo_for_burst; |
wire enough_data_in_rxfifo_for_burst_plus1; |
|
reg ReadTxDataFromMemory/* synthesis syn_allow_retiming=0*/; |
wire WriteRxDataToMemory; |
reg WriteRxDataToMemory_r ; |
reg ReadTxDataFromMemory/* synthesis syn_allow_retiming=0*/; |
wire WriteRxDataToMemory; |
reg WriteRxDataToMemory_r ; |
|
reg MasterWbTX; |
reg MasterWbRX; |
reg MasterWbTX; |
reg MasterWbRX; |
|
reg [29:0] m_wb_adr_o; |
reg m_wb_cyc_o; |
reg [3:0] m_wb_sel_o; |
reg m_wb_we_o; |
reg [29:0] m_wb_adr_o; |
reg m_wb_cyc_o; |
reg [3:0] m_wb_sel_o; |
reg m_wb_we_o; |
|
wire TxLengthEq0; |
wire TxLengthLt4; |
wire TxLengthEq0; |
wire TxLengthLt4; |
|
reg BlockingIncrementTxPointer; |
reg [31:2] TxPointerMSB; |
reg [1:0] TxPointerLSB; |
reg [1:0] TxPointerLSB_rst; |
reg [31:2] RxPointerMSB; |
reg [1:0] RxPointerLSB_rst; |
reg BlockingIncrementTxPointer; |
reg [31:2] TxPointerMSB; |
reg [1:0] TxPointerLSB; |
reg [1:0] TxPointerLSB_rst; |
reg [31:2] RxPointerMSB; |
reg [1:0] RxPointerLSB_rst; |
|
wire RxBurstAcc; |
wire RxWordAcc; |
wire RxHalfAcc; |
wire RxByteAcc; |
wire RxBurstAcc; |
wire RxWordAcc; |
wire RxHalfAcc; |
wire RxByteAcc; |
|
|
|
wire ResetTxBDReady; |
reg BlockingTxStatusWrite_sync1; |
reg BlockingTxStatusWrite_sync2; |
reg BlockingTxStatusWrite_sync3; |
|
reg cyc_cleared; |
reg IncrTxPointer; |
|
reg [3:0] RxByteSel; |
wire MasterAccessFinished; |
|
reg LatchValidBytes; |
reg LatchValidBytes_q; |
|
// Start: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I |
reg ReadTxDataFromFifo_sync1; |
reg ReadTxDataFromFifo_sync2; |
reg ReadTxDataFromFifo_sync3; |
reg ReadTxDataFromFifo_syncb1; |
reg ReadTxDataFromFifo_syncb2; |
reg ReadTxDataFromFifo_syncb3; |
|
reg RxAbortSync1; |
reg RxAbortSync2; |
reg RxAbortSync3; |
reg RxAbortSync4; |
reg RxAbortSyncb1; |
reg RxAbortSyncb2; |
|
reg RxEnableWindow; |
|
wire SetWriteRxDataToFifo; |
|
|
reg WriteRxDataToFifoSync1; |
reg WriteRxDataToFifoSync2; |
reg WriteRxDataToFifoSync3; |
|
wire WriteRxDataToFifo_wb; |
// Receive fifo selection register - JB |
reg [3:0] rx_shift_ended_wb_shr; |
reg rx_ethside_fifo_sel /* synthesis syn_allow_retiming=0; syn_noprune=1; syn_keep=1 */; |
reg rx_wbside_fifo_sel /* synthesis syn_allow_retiming=0; syn_noprune=1; syn_keep=1 */; |
reg rx_discard_packet; |
|
|
reg LatchedRxStartFrm; |
reg SyncRxStartFrm; |
reg SyncRxStartFrm_q; |
reg SyncRxStartFrm_q2; |
wire RxFifoReset; |
|
wire [31:0] rx_fifo0_data_out; |
wire rx_fifo0_write; |
wire rx_fifo0_read; |
wire rx_fifo0_clear; |
wire rx_fifo0_full; |
wire rx_fifo0_afull; |
wire rx_fifo0_empty; |
wire rx_fifo0_aempty; |
|
|
wire [31:0] rx_fifo1_data_out; |
wire rx_fifo1_write; |
wire rx_fifo1_read; |
wire rx_fifo1_clear; |
wire rx_fifo1_full; |
wire rx_fifo1_afull; |
wire rx_fifo1_empty; |
wire rx_fifo1_aempty; |
|
wire [`ETH_RX_FIFO_CNT_WIDTH-1:0] rx_fifo0_cnt; |
wire [`ETH_RX_FIFO_CNT_WIDTH-1:0] rx_fifo1_cnt; |
|
|
wire TxError; |
wire RxError; |
|
wire write_rx_data_to_memory_wait; |
wire write_rx_data_to_memory_go; |
|
reg RxStatusWriteLatched; |
reg RxStatusWriteLatched_sync1; |
reg RxStatusWriteLatched_sync2; |
reg RxStatusWriteLatched_syncb1; |
reg RxStatusWriteLatched_syncb2; |
reg busy_wb; |
|
reg overflow_bug_reset; |
|
// Fix bug when overflow causes things to become a bit confused |
always @ (posedge WB_CLK_I) |
if (Reset) |
overflow_bug_reset <= 0; |
else |
overflow_bug_reset <= (rx_fifo1_empty & rx_fifo0_empty & |
!RxEnableWindow & !rx_wb_writeback_finished & |
!rx_wb_last_writes & RxEn & RxEn_q & |
(rx_ethside_fifo_sel != rx_wbside_fifo_sel)); |
|
always @(posedge overflow_bug_reset) |
$display("%t: %m overflow_bug_reset posedge",$time); |
|
|
`ifdef ETH_WISHBONE_B3 |
`ifndef BURST_4BEAT |
assign m_wb_bte_o = 2'b00; // Linear burst |
613,7 → 718,6
Flop <= ~Flop; |
end |
|
wire ResetTxBDReady; |
assign ResetTxBDReady = TxDonePulse | TxAbortPulse | TxRetryPulse; |
|
// Latching READY status of the Tx buffer descriptor |
685,10 → 789,6
end |
|
|
reg BlockingTxStatusWrite_sync1; |
reg BlockingTxStatusWrite_sync2; |
reg BlockingTxStatusWrite_sync3; |
|
// Synchronizing BlockingTxStatusWrite to MTxClk |
always @ (posedge MTxClk or posedge Reset) |
begin |
768,27 → 868,21
begin |
if(TxLengthLt4) |
TxLength <= 16'h0; |
else |
if(TxPointerLSB_rst==2'h0) |
TxLength <= TxLength - 16'd4; // Length is subtracted at |
else if(TxPointerLSB_rst==2'h0) |
TxLength <= TxLength - 16'd4; // Length is subtracted at |
// the data request |
else |
if(TxPointerLSB_rst==2'h1) |
TxLength <= TxLength - 16'd3; // Length is subtracted |
else if(TxPointerLSB_rst==2'h1) |
TxLength <= TxLength - 16'd3; // Length is subtracted |
// at the data request |
else |
if(TxPointerLSB_rst==2'h2) |
TxLength <= TxLength - 16'd2; // Length is subtracted |
else if(TxPointerLSB_rst==2'h2) |
TxLength <= TxLength - 16'd2; // Length is subtracted |
// at the data request |
else |
if(TxPointerLSB_rst==2'h3) |
TxLength <= TxLength - 16'd1; // Length is subtracted |
else if(TxPointerLSB_rst==2'h3) |
TxLength <= TxLength - 16'd1; // Length is subtracted |
// at the data request |
end |
end |
|
|
|
//Latching length from the buffer descriptor; |
always @ (posedge WB_CLK_I or posedge Reset) |
begin |
802,10 → 896,7
assign TxLengthEq0 = TxLength == 0; |
assign TxLengthLt4 = TxLength < 4; |
|
reg cyc_cleared; |
reg IncrTxPointer; |
|
|
// Latching Tx buffer pointer from buffer descriptor. Only 30 MSB bits are |
// latched because TxPointerMSB is only used for word-aligned accesses. |
always @ (posedge WB_CLK_I or posedge Reset) |
854,10 → 945,6
end |
|
|
reg [3:0] RxByteSel; |
wire MasterAccessFinished; |
|
|
always @ (posedge WB_CLK_I or posedge Reset) |
begin |
if(Reset) |
1344,9 → 1431,6
// Marks which bytes are valid within the word. |
assign TxValidBytes = TxLengthLt4 ? TxLength[1:0] : 2'b0; |
|
reg LatchValidBytes; |
reg LatchValidBytes_q; |
|
always @ (posedge WB_CLK_I or posedge Reset) |
begin |
if(Reset) |
1392,7 → 1476,9
|
|
// Temporary Tx and Rx buffer descriptor address |
assign TempTxBDAddress[7:1] = {7{ TxStatusWrite & ~WrapTxStatusBit}} & (TxBDAddress + 1) ; // Tx BD increment or wrap (last BD) |
assign TempTxBDAddress[7:1] = {7{ TxStatusWrite & ~WrapTxStatusBit}} & |
(TxBDAddress + 1) ; // Tx BD increment or wrap |
// (last BD) |
|
assign TempRxBDAddress[7:1] = {7{ WrapRxStatusBit}} & (r_TxBDNum[6:0]) | // Using first Rx BD |
{7{~WrapRxStatusBit}} & (RxBDAddress + 1) ; // Using next Rx BD (incremenrement address) |
1746,15 → 1832,6
end |
|
|
// Start: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I |
reg ReadTxDataFromFifo_sync1; |
reg ReadTxDataFromFifo_sync2; |
reg ReadTxDataFromFifo_sync3; |
reg ReadTxDataFromFifo_syncb1; |
reg ReadTxDataFromFifo_syncb2; |
reg ReadTxDataFromFifo_syncb3; |
|
|
always @ (posedge MTxClk or posedge Reset) |
begin |
if(Reset) |
1877,13 → 1954,6
end |
|
|
reg RxAbortSync1; |
reg RxAbortSync2; |
reg RxAbortSync3; |
reg RxAbortSync4; |
reg RxAbortSyncb1; |
reg RxAbortSyncb2; |
|
assign StartRxBDRead = RxStatusWrite | RxAbortSync3 & ~RxAbortSync4 | |
r_RxEn & ~r_RxEn_q; |
|
1960,13 → 2030,11
begin |
if(Reset) |
RxBDOK <= 1'b0; |
else |
if(rx_wb_writeback_finished | RxAbortSync2 & ~RxAbortSync3 | |
~r_RxEn & r_RxEn_q) |
RxBDOK <= 1'b0; |
else |
if(RxBDReady) |
RxBDOK <= 1'b1; |
else if(rx_wb_writeback_finished | RxAbortSync2 & ~RxAbortSync3 | |
~r_RxEn & r_RxEn_q) |
RxBDOK <= 1'b0; |
else if(RxBDReady) |
RxBDOK <= 1'b1; |
end |
|
// Reading Rx BD pointer |
2033,12 → 2101,10
begin |
if(Reset) |
RxEn_needed <= 1'b0; |
else |
if(/*~RxReady &*/ r_RxEn & WbEn & ~WbEn_q) |
RxEn_needed <= 1'b1; |
else |
if(RxPointerRead & RxEn & RxEn_q) |
RxEn_needed <= 1'b0; |
else if(/*~RxReady &*/ r_RxEn & WbEn & ~WbEn_q) |
RxEn_needed <= 1'b1; |
else if(RxPointerRead & RxEn & RxEn_q) |
RxEn_needed <= 1'b0; |
end |
|
|
2046,8 → 2112,6
// of frame is detected. |
assign RxStatusWrite = rx_wb_writeback_finished & RxEn & RxEn_q; |
|
reg RxEnableWindow; |
|
// Indicating that last byte is being reveived |
always @ (posedge MRxClk or posedge Reset) |
begin |
2146,8 → 2210,6
end |
end |
|
wire SetWriteRxDataToFifo; |
|
// Assembling data that will be written to the rx_fifo |
always @ (posedge MRxClk or posedge Reset) |
begin |
2169,11 → 2231,6
end |
|
|
reg WriteRxDataToFifoSync1; |
reg WriteRxDataToFifoSync2; |
reg WriteRxDataToFifoSync3; |
|
|
// Indicating start of the reception process |
assign SetWriteRxDataToFifo = (RxValid & ~RxStartFrm & |
RxEnableWindow & (&RxByteCnt)) |
2222,14 → 2279,24
WriteRxDataToFifoSync3 <= WriteRxDataToFifoSync2; |
end |
|
wire WriteRxDataToFifo_wb; |
|
assign WriteRxDataToFifo_wb = WriteRxDataToFifoSync2 & |
~WriteRxDataToFifoSync3; |
// Receive fifo selection register - JB |
reg [3:0] rx_shift_ended_wb_shr; |
reg rx_ethside_fifo_sel /* synthesis syn_allow_retiming=0; syn_noprune=1; syn_keep=1 */; |
reg rx_wbside_fifo_sel /* synthesis syn_allow_retiming=0; syn_noprune=1; syn_keep=1 */; |
|
|
// Signal to indicate data in current buffer should be discarded as we had |
// no open buffer for it. |
// Goes high when rx_wb_last_writes goes off and we still haven't gotten a |
// RX buffer for it. |
always @(posedge WB_CLK_I) |
if (Reset) |
rx_discard_packet <= 0; |
else if (rx_shift_ended_wb_shr[3:2] == 2'b01) |
rx_discard_packet <= 0; |
else if (rx_wb_last_writes & RxBDRead) |
rx_discard_packet <= 1; |
|
|
// Shift in this - our detection of end of data RX |
always @(posedge WB_CLK_I) |
rx_shift_ended_wb_shr <= {rx_shift_ended_wb_shr[2:0], |
2239,8 → 2306,9
always @ (posedge WB_CLK_I or posedge Reset) |
if(Reset) |
rx_ethside_fifo_sel <= 0; |
else |
if(rx_shift_ended_wb_shr[3:2] == 2'b01) |
else if (rx_discard_packet | overflow_bug_reset) |
rx_ethside_fifo_sel <= 0; |
else if(rx_shift_ended_wb_shr[3:2] == 2'b01 & !rx_discard_packet) |
// Switch over whenever we've finished receiving last frame's data |
rx_ethside_fifo_sel <= ~rx_ethside_fifo_sel; |
|
2249,17 → 2317,12
always @ (posedge WB_CLK_I or posedge Reset) |
if(Reset) |
rx_wbside_fifo_sel <= 0; |
else |
if(rx_wb_writeback_finished & RxEn & RxEn_q) |
// Switch over whenever we've finished receiving last frame's data |
rx_wbside_fifo_sel <= ~rx_wbside_fifo_sel; |
else if (rx_discard_packet | overflow_bug_reset) |
rx_wbside_fifo_sel <= 0; |
else if(rx_wb_writeback_finished & RxEn & RxEn_q) |
// Switch over whenever we've finished receiving last frame's data |
rx_wbside_fifo_sel <= ~rx_wbside_fifo_sel; |
|
reg LatchedRxStartFrm; |
reg SyncRxStartFrm; |
reg SyncRxStartFrm_q; |
reg SyncRxStartFrm_q2; |
wire RxFifoReset; |
|
always @ (posedge MRxClk or posedge Reset) |
begin |
if(Reset) |
2304,31 → 2367,9
assign rx_startfrm_wb = SyncRxStartFrm_q & ~SyncRxStartFrm_q2; |
|
|
assign RxFifoReset = rx_startfrm_wb; |
assign RxFifoReset = rx_startfrm_wb | rx_discard_packet | overflow_bug_reset; |
|
|
|
wire [31:0] rx_fifo0_data_out; |
wire rx_fifo0_write; |
wire rx_fifo0_read; |
wire rx_fifo0_clear; |
wire rx_fifo0_full; |
wire rx_fifo0_afull; |
wire rx_fifo0_empty; |
wire rx_fifo0_aempty; |
|
|
wire [31:0] rx_fifo1_data_out; |
wire rx_fifo1_write; |
wire rx_fifo1_read; |
wire rx_fifo1_clear; |
wire rx_fifo1_full; |
wire rx_fifo1_afull; |
wire rx_fifo1_empty; |
wire rx_fifo1_aempty; |
|
wire [`ETH_RX_FIFO_CNT_WIDTH-1:0] rx_fifo0_cnt; |
wire [`ETH_RX_FIFO_CNT_WIDTH-1:0] rx_fifo1_cnt; |
|
// RX FIFO buffer 0 controls |
assign rx_fifo0_write = (!rx_ethside_fifo_sel) & WriteRxDataToFifo_wb & |
~rx_fifo0_full; |
2406,13 → 2447,9
rx_fifo1_full : rx_fifo0_full; |
|
|
|
|
|
wire write_rx_data_to_memory_wait; |
assign write_rx_data_to_memory_wait = !RxBDOK | RxPointerRead; |
wire write_rx_data_to_memory_go; |
|
|
`ifdef ETH_RX_BURST_EN |
assign enough_data_in_rxfifo_for_burst = rxfifo_cnt>=(`ETH_BURST_LENGTH); |
assign enough_data_in_rxfifo_for_burst_plus1 = rxfifo_cnt>(`ETH_BURST_LENGTH - 1); |
2471,6 → 2508,8
rx_wb_last_writes <= ShiftEndedSync1 & ~ShiftEndedSync2; |
else if (rx_wb_writeback_finished & RxEn & RxEn_q) |
rx_wb_last_writes <= 0; |
else if (rx_discard_packet | overflow_bug_reset) |
rx_wb_last_writes <= 0; |
|
// Pulse indicating last of RX data has been written out |
always @ (posedge WB_CLK_I or posedge Reset) |
2504,12 → 2543,10
begin |
if(Reset) |
RxEnableWindow <= 1'b0; |
else |
if(RxStartFrm) |
RxEnableWindow <= 1'b1; |
else |
if(RxEndFrm | RxAbort) |
RxEnableWindow <= 1'b0; |
else if(RxStartFrm) |
RxEnableWindow <= 1'b1; |
else if(RxEndFrm | RxAbort) |
RxEnableWindow <= 1'b0; |
end |
|
|
2585,7 → 2622,15
end |
|
|
assign RxStatusIn = {ReceivedPauseFrm, AddressMiss, RxOverrun, InvalidSymbol, DribbleNibble, ReceivedPacketTooBig, ShortFrame, LatchedCrcError, RxLateCollision}; |
assign RxStatusIn = {ReceivedPauseFrm, |
AddressMiss, |
RxOverrun, |
InvalidSymbol, |
DribbleNibble, |
ReceivedPacketTooBig, |
ShortFrame, |
LatchedCrcError, |
RxLateCollision}; |
|
always @ (posedge MRxClk or posedge Reset) |
begin |
2602,20 → 2647,17
begin |
if(Reset) |
RxOverrun <= 1'b0; |
else |
if(RxStatusWrite) |
RxOverrun <= 1'b0; |
else |
if(RxBufferFull & WriteRxDataToFifo_wb) |
RxOverrun <= 1'b1; |
else if(RxStatusWrite | rx_discard_packet | overflow_bug_reset) |
RxOverrun <= 1'b0; |
else if(RxBufferFull & WriteRxDataToFifo_wb) |
RxOverrun <= 1'b1; |
end |
|
|
assign TxError = TxUnderRun | RetryLimit | LateCollLatched | |
CarrierSenseLost; |
|
wire TxError; |
assign TxError = TxUnderRun | RetryLimit | LateCollLatched | CarrierSenseLost; |
|
wire RxError; |
|
// ShortFrame (RxStatusInLatched[2]) can not set an error because short |
// frames are aborted when signal r_RecSmall is set to 0 in MODER register. |
2624,14 → 2666,6
assign RxError = (|RxStatusInLatched[6:3]) | (|RxStatusInLatched[1:0]); |
|
|
|
reg RxStatusWriteLatched; |
reg RxStatusWriteLatched_sync1; |
reg RxStatusWriteLatched_sync2; |
reg RxStatusWriteLatched_syncb1; |
reg RxStatusWriteLatched_syncb2; |
|
|
// Latching and synchronizing RxStatusWrite signal. This signal is used for |
// clearing the ReceivedPauseFrm signal |
always @ (posedge WB_CLK_I or posedge Reset) |
2746,7 → 2780,6
|
|
|
reg busy_wb; |
always @ (posedge WB_CLK_I or posedge Reset) |
if(Reset) |
busy_wb <= 0; |
2783,21 → 2816,25
assign dbg_dat0[26:24] = tx_burst_cnt; |
|
// Third byte |
assign dbg_dat0[23] = 0; |
assign dbg_dat0[22] = 0; |
assign dbg_dat0[21] = rx_burst; |
assign dbg_dat0[20] = rx_burst_en; |
assign dbg_dat0[19] = 0; |
assign dbg_dat0[18] = 0; |
assign dbg_dat0[17] = tx_burst; |
assign dbg_dat0[16] = tx_burst_en; |
assign dbg_dat0[23] = rx_ethside_fifo_sel; |
assign dbg_dat0[22] = rx_wbside_fifo_sel; |
assign dbg_dat0[21] = rx_fifo0_empty; |
assign dbg_dat0[20] = rx_fifo1_empty; |
assign dbg_dat0[19] = overflow_bug_reset; |
assign dbg_dat0[18] = RxBDOK; |
assign dbg_dat0[17] = write_rx_data_to_memory_go; |
assign dbg_dat0[16] = rx_wb_last_writes; |
// Second byte - TxBDAddress - or TX BD address pointer |
assign dbg_dat0[15:8] = { 1'b0, TxBDAddress}; |
assign dbg_dat0[15:8] = { BlockingTxBDRead , TxBDAddress}; |
// Bottom byte - FSM controlling vector |
assign dbg_dat0[7:0] = {MasterWbTX,MasterWbRX, |
ReadTxDataFromMemory_2,WriteRxDataToMemory, |
MasterAccessFinished,cyc_cleared, |
tx_burst,rx_burst}; |
assign dbg_dat0[7:0] = {MasterWbTX, |
MasterWbRX, |
ReadTxDataFromMemory_2, |
WriteRxDataToMemory, |
MasterAccessFinished, |
cyc_cleared, |
tx_burst, |
rx_burst}; |
|
`endif |
|
/trunk/orpsocv2/rtl/verilog/ethmac/eth_fifo.v
45,44 → 45,49
module eth_fifo (data_in, data_out, clk, reset, write, read, clear, |
almost_full, full, almost_empty, empty, cnt); |
|
parameter DATA_WIDTH = 32; |
parameter DEPTH = 8; |
parameter CNT_WIDTH = 3; |
parameter DATA_WIDTH = 32; |
parameter DEPTH = 8; |
parameter CNT_WIDTH = 3; |
|
input clk; |
input reset; |
input write; |
input read; |
input clear; |
input [DATA_WIDTH-1:0] data_in; |
input clk; |
input reset; |
input write; |
input read; |
input clear; |
input [DATA_WIDTH-1:0] data_in; |
|
output [DATA_WIDTH-1:0] data_out; |
output almost_full; |
output full; |
output almost_empty; |
output empty; |
output [CNT_WIDTH-1:0] cnt; |
output [DATA_WIDTH-1:0] data_out; |
output almost_full; |
output full; |
output almost_empty; |
output empty; |
output [CNT_WIDTH-1:0] cnt; |
|
|
reg [CNT_WIDTH-1:0] read_pointer; |
reg [CNT_WIDTH-1:0] cnt; |
reg final_read; |
reg [CNT_WIDTH-1:0] read_pointer; |
reg [CNT_WIDTH-1:0] cnt; |
|
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
cnt <= 0; |
else |
if(clear) |
cnt <= { {(CNT_WIDTH-1){1'b0}}, read^write}; |
else |
if(read ^ write) |
if(read) |
cnt <= cnt - 1; |
else |
cnt <= cnt + 1; |
end |
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
cnt <= 0; |
else |
if(clear) |
cnt <= { {(CNT_WIDTH-1){1'b0}}, read^write}; |
else |
if(read ^ write) |
if(read) |
cnt <= cnt - 1; |
else |
cnt <= cnt + 1; |
end |
|
|
assign empty = ~(|cnt); |
assign almost_empty = cnt==1; |
assign full = {{32-CNT_WIDTH{1'b0}},cnt} == (DEPTH-1); |
assign almost_full = {{32-CNT_WIDTH{1'b0}},cnt} == (DEPTH-2); |
|
|
`ifdef ETH_FIFO_GENERIC |
|
90,11 → 95,11
|
|
// This should make the synthesis tool infer a RAM |
reg [CNT_WIDTH-1:0] waddr, raddr, raddr_reg; |
reg clear_reg; // Register the clear pulse |
reg [CNT_WIDTH-1:0] waddr, raddr, raddr_reg; |
reg clear_reg; // Register the clear pulse |
|
reg fallthrough_read; |
reg [CNT_WIDTH-1:0] fallthrough_read_addr; |
reg fallthrough_read; |
reg [CNT_WIDTH-1:0] fallthrough_read_addr; |
|
|
always @(posedge clk) |
106,7 → 111,7
always @(posedge clk) |
if (empty & write) |
fallthrough_read_addr <= waddr; |
|
|
always @(posedge clk) |
if (reset) |
waddr <= 0; |
137,163 → 142,231
|
assign data_out = fifo[raddr_reg]; |
|
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
read_pointer <= 0; |
else |
if(clear) |
// Begin read pointer at 1 |
read_pointer <= { {(CNT_WIDTH-1){1'b0}}, 1'b1}; |
else |
if(read & ~empty) |
read_pointer <= read_pointer + 1'b1; |
end |
|
always @(posedge clk) |
if (reset) |
final_read <= 0; |
else if (final_read & read & !write) |
final_read <= ~final_read; |
else if ((cnt == 1) & read & !write) |
final_read <= 1; // Indicate last read data has been output |
|
assign empty = ~(|cnt); |
assign almost_empty = cnt==1; |
assign full = {{32-CNT_WIDTH{1'b0}},cnt} == (DEPTH-1); |
//assign almost_full = &cnt[CNT_WIDTH-1:0]; |
assign almost_full = {{32-CNT_WIDTH{1'b0}},cnt} == (DEPTH-2); |
|
`else // !`ifdef ETH_FIFO_GENERIC |
|
reg [CNT_WIDTH-1:0] write_pointer; |
|
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
read_pointer <= 0; |
else |
if(clear) |
// Begin read pointer at 1 |
read_pointer <= { {(CNT_WIDTH-1){1'b0}}, 1'b1}; |
else |
if(read & ~empty) |
read_pointer <= read_pointer + 1'b1; |
end |
|
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
read_pointer <= 0; |
else |
if(clear) |
read_pointer <= { {(CNT_WIDTH-1){1'b0}}, read}; |
else |
if(read & ~empty) |
read_pointer <= read_pointer + 1'b1; |
end |
|
`else // !`ifdef ETH_FIFO_GENERIC |
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
write_pointer <= 0; |
else |
if(clear) |
write_pointer <= { {(CNT_WIDTH-1){1'b0}}, write}; |
else |
if(write & ~full) |
write_pointer <= write_pointer + 1'b1; |
end // always @ (posedge clk or posedge reset) |
|
reg [CNT_WIDTH-1:0] write_pointer; |
`endif // !`ifdef ETH_FIFO_GENERIC |
|
`ifdef ETH_FIFO_XILINX |
|
generate |
if (CNT_WIDTH==4) |
begin |
xilinx_dist_ram_16x32 fifo |
( .data_out(data_out), |
.we(write & ~full), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
end // if (CNT_WIDTH==4) |
else if (CNT_WIDTH==6) |
begin |
|
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
read_pointer <= 0; |
else |
if(clear) |
read_pointer <= { {(CNT_WIDTH-1){1'b0}}, read}; |
else |
if(read & ~empty) |
read_pointer <= read_pointer + 1'b1; |
end |
wire [DATA_WIDTH-1:0] data_out0; |
wire [DATA_WIDTH-1:0] data_out1; |
wire [DATA_WIDTH-1:0] data_out2; |
wire [DATA_WIDTH-1:0] data_out3; |
|
wire we_ram0,we_ram1,we_ram2,we_ram3; |
|
always @ (posedge clk or posedge reset) |
begin |
if(reset) |
write_pointer <= 0; |
else |
if(clear) |
write_pointer <= { {(CNT_WIDTH-1){1'b0}}, write}; |
else |
if(write & ~full) |
write_pointer <= write_pointer + 1'b1; |
end |
assign we_ram0 = (write_pointer[5:4]==2'b00); |
assign we_ram1 = (write_pointer[5:4]==2'b01); |
assign we_ram2 = (write_pointer[5:4]==2'b10); |
assign we_ram3 = (write_pointer[5:4]==2'b11); |
|
assign data_out = (read_pointer[5:4]==2'b11) ? data_out3 : |
(read_pointer[5:4]==2'b10) ? data_out2 : |
(read_pointer[5:4]==2'b01) ? data_out1 : data_out0; |
|
xilinx_dist_ram_16x32 fifo0 |
( .data_out(data_out0), |
.we(write & ~full & we_ram0), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
xilinx_dist_ram_16x32 fifo1 |
( .data_out(data_out1), |
.we(write & ~full & we_ram1), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
`ifdef ETH_FIFO_XILINX |
|
generate |
if (CNT_WIDTH==4) |
begin |
xilinx_dist_ram_16x32 fifo |
( .data_out(data_out), |
.we(write & ~full), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
end // if (CNT_WIDTH==4) |
else if (CNT_WIDTH==6) |
begin |
xilinx_dist_ram_16x32 fifo2 |
( .data_out(data_out2), |
.we(write & ~full & we_ram2), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
xilinx_dist_ram_16x32 fifo3 |
( .data_out(data_out3), |
.we(write & ~full & we_ram3), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
end // if (CNT_WIDTH==6) |
|
endgenerate |
`endif // `ifdef ETH_FIFO_XILINX |
|
wire [DATA_WIDTH-1:0] data_out0; |
wire [DATA_WIDTH-1:0] data_out1; |
wire [DATA_WIDTH-1:0] data_out2; |
wire [DATA_WIDTH-1:0] data_out3; |
|
wire we_ram0,we_ram1,we_ram2,we_ram3; |
`ifdef ETH_FIFO_RAMB18 |
|
assign we_ram0 = (write_pointer[5:4]==2'b00); |
assign we_ram1 = (write_pointer[5:4]==2'b01); |
assign we_ram2 = (write_pointer[5:4]==2'b10); |
assign we_ram3 = (write_pointer[5:4]==2'b11); |
|
assign data_out = (read_pointer[5:4]==2'b11) ? data_out3 : |
(read_pointer[5:4]==2'b10) ? data_out2 : |
(read_pointer[5:4]==2'b01) ? data_out1 : data_out0; |
|
xilinx_dist_ram_16x32 fifo0 |
( .data_out(data_out0), |
.we(write & ~full & we_ram0), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
xilinx_dist_ram_16x32 fifo1 |
( .data_out(data_out1), |
.we(write & ~full & we_ram1), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
xilinx_dist_ram_16x32 fifo2 |
( .data_out(data_out2), |
.we(write & ~full & we_ram2), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
|
xilinx_dist_ram_16x32 fifo3 |
( .data_out(data_out3), |
.we(write & ~full & we_ram3), |
.data_in(data_in), |
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer[3:0]), |
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer[3:0]), |
.wclk(clk) |
); |
end // if (CNT_WIDTH==6) |
endgenerate |
wire [8:0] read_pointer_to_xilinx_ram; |
wire [8:0] read_pointer_preincremented; |
assign read_pointer_preincremented = read_pointer + 1; |
|
assign read_pointer_to_xilinx_ram = (read) ? |
read_pointer_preincremented : |
read_pointer; |
|
|
|
wire [8:0] write_pointer_to_xilinx_ram; |
assign write_pointer_to_xilinx_ram = {{(9-CNT_WIDTH){1'b0}},write_pointer}; |
|
`else // !ETH_FIFO_XILINX |
`ifdef ETH_ALTERA_ALTSYNCRAM |
altera_dpram_16x32 altera_dpram_16x32_inst |
( |
.data (data_in), |
.wren (write & ~full), |
.wraddress (clear ? {CNT_WIDTH-1{1'b0}} : write_pointer), |
.rdaddress (clear ? {CNT_WIDTH-1{1'b0}} : read_pointer ), |
.clock (clk), |
.q (data_out) |
); //exemplar attribute altera_dpram_16x32_inst NOOPT TRUE |
`endif // `ifdef ETH_ALTERA_ALTSYNCRAM |
`endif // !`ifdef ETH_FIFO_XILINX |
|
// synthesis translate_off |
// Port A - Write |
// Port B - Rread |
BLK_MEM_GEN_V3_1 #( |
.C_ADDRA_WIDTH(9), |
.C_ADDRB_WIDTH(9), |
.C_ALGORITHM(1), |
.C_BYTE_SIZE(9), |
.C_COMMON_CLK(0), |
.C_DEFAULT_DATA("0"), |
.C_DISABLE_WARN_BHV_COLL(0), |
.C_DISABLE_WARN_BHV_RANGE(0), |
.C_FAMILY("virtex5"), |
.C_HAS_ENA(0), |
.C_HAS_ENB(0), |
.C_HAS_INJECTERR(0), |
.C_HAS_MEM_OUTPUT_REGS_A(0), |
.C_HAS_MEM_OUTPUT_REGS_B(0), |
.C_HAS_MUX_OUTPUT_REGS_A(0), |
.C_HAS_MUX_OUTPUT_REGS_B(0), |
.C_HAS_REGCEA(0), |
.C_HAS_REGCEB(0), |
.C_HAS_RSTA(0), |
.C_HAS_RSTB(0), |
.C_INITA_VAL("0"), |
.C_INITB_VAL("0"), |
.C_INIT_FILE_NAME("no_coe_file_loaded"), |
.C_LOAD_INIT_FILE(0), |
.C_MEM_TYPE(1), |
.C_MUX_PIPELINE_STAGES(0), |
.C_PRIM_TYPE(1), |
.C_READ_DEPTH_A(512), |
.C_READ_DEPTH_B(512), |
.C_READ_WIDTH_A(32), |
.C_READ_WIDTH_B(32), |
.C_RSTRAM_A(0), |
.C_RSTRAM_B(0), |
.C_RST_PRIORITY_A("CE"), |
.C_RST_PRIORITY_B("CE"), |
.C_RST_TYPE("SYNC"), |
.C_SIM_COLLISION_CHECK("WARNING_ONLY"), |
.C_USE_BYTE_WEA(0), |
.C_USE_BYTE_WEB(0), |
.C_USE_DEFAULT_DATA(0), |
.C_USE_ECC(0), |
.C_WEA_WIDTH(1), |
.C_WEB_WIDTH(1), |
.C_WRITE_DEPTH_A(512), |
.C_WRITE_DEPTH_B(512), |
.C_WRITE_MODE_A("WRITE_FIRST"), |
.C_WRITE_MODE_B("READ_FIRST"), |
.C_WRITE_WIDTH_A(32), |
.C_WRITE_WIDTH_B(32), |
.C_XDEVICEFAMILY("virtex5")) |
inst ( |
.CLKA(clk), |
.WEA(write), |
.ADDRA(write_pointer_to_xilinx_ram), |
.DINA(data_in), |
.CLKB(clk), |
.ADDRB(read_pointer_to_xilinx_ram), |
.DOUTB(data_out), |
.RSTA(reset), |
.ENA(), |
.REGCEA(), |
.DOUTA(), |
.RSTB(), |
.ENB(), |
.REGCEB(), |
.WEB(), |
.DINB(), |
.INJECTSBITERR(), |
.INJECTDBITERR(), |
.SBITERR(), |
.DBITERR(), |
.RDADDRECC() |
); |
// synthesis translate_on |
`endif // `ifdef ETH_FIFO_RAMB18 |
|
assign empty = ~(|cnt); |
assign almost_empty = cnt == 1; |
assign full = cnt == (DEPTH-1); |
assign almost_full = &cnt[CNT_WIDTH-1:0]; |
|
`endif // !`ifdef ETH_FIFO_GENERIC |
|
`ifdef ETH_ALTERA_ALTSYNCRAM |
altera_dpram_16x32 altera_dpram_16x32_inst |
( |
.data (data_in), |
.wren (write & ~full), |
.wraddress (clear ? {CNT_WIDTH-1{1'b0}} : write_pointer), |
.rdaddress (clear ? {CNT_WIDTH-1{1'b0}} : read_pointer ), |
.clock (clk), |
.q (data_out) |
); //exemplar attribute altera_dpram_16x32_inst NOOPT TRUE |
`endif // `ifdef ETH_ALTERA_ALTSYNCRAM |
|
|
endmodule // eth_fifo |
|
endmodule |
/trunk/orpsocv2/doc/orpsoc.texi
100,9 → 100,9
|
The @value{ORPSOC} project is intended to serve dual purposes. One is to act as a development platform for OpenRISC processors, and as a development platform of OpenRISC-based SoCs targeted at specific hardware. |
|
Organising a single project to satisfy these requirements can lead to some confusion. This section is intended to make the organisation of the project clear. |
Organising a single project to satisfy these requirements can lead to some overlap and redundancy. This section is intended to make the organisation of the project clear. |
|
The reference implementation based in the root (base directory) of the project contains enough componenets to create a simple OpenRISC-based SoC. Each board build is intended to implement as fully-featured a system as possible, depending on the targeted hardware. |
The reference implementation based in the root (base directory) of the project contains enough components to create a simple OpenRISC-based SoC. Each board build is intended to implement as fully-featured a system as possible, depending on the targeted hardware. |
|
The project is organised in such a way that each board build can use both the reference implementation's RTL modules and software, as well as its own set of RTL and software. The reference implementation is limited to what is available in the RTL and software directories in the root of the project, and is not technology dependent. |
|
111,17 → 111,19
@node Software Organisation |
@section Software |
|
The @code{sw} path contains primarily target software (code intended for cross-compilation and execution on an OpenRISC processor.) Thre is also a path, @code{sw/utils} containing custom tools, intended to be run on the host, for manipulation of binary software images. |
The @code{sw} path contains primarily target software (code intended for cross-compilation and execution on an OpenRISC processor.) There is also a path, @code{sw/utils} containing custom tools, intended to be run on the host, for manipulation of binary software images. |
|
Driver software, implementing access functions for hardware modules, are found under @code{sw/drivers}. |
Driver software, implementing access functions for hardware modules, are found under @code{sw/drivers}. |
|
There is a minimal support library under the @code{sw/lib} path. Both drivers and support library are compiled together to create a library called @code{liborpsoc} which is placed in @code{sw/lib}. |
|
All CPU-related functions are made available through the file @code{cpu-utils.h} which is located in @code{sw/lib/include} and depending on the CPU being used, can be used to switch between different CPU driver functions. All CPU drivers are under the @code{sw/drivers} path. |
|
@emph{Note:} It is expected in the future that the OpenRISC toolchain based on newlib will provide all of the necessary support software provided in this CPU-specific driver path. When the first release of the newlib-based toolchain occurs it is expected the software in ORPSoC will be changed to use this toolchain instead. |
|
Test software is found under @code{sw/tests}. Typically, each is for a specific module, or for a particular capability (eg. tests for the UART capability are under @code{sw/tests/uart}, rather than @code{sw/tests/uart16550} which.) There are no specific rules here. |
|
Under each test directory are two directories, @code{board} and @code{sim}, containing appropriate test software. Code for simulation will produce less printfs and aim to execute within realistic timeframes for RTL simulation. Board targeted test software is obviously written with the opposite considerations in mind. |
Under each test directory are two directories, @code{board} and @code{sim}, containing appropriate test software. Code for simulation will produce less printfs and aim to execute within realistic timeframes for RTL simulation. Board targeted test software is obviously written with the opposite considerations in mind and be more verbose and perhaps run orders of magnitudes more tests. |
|
@node Software Test Naming |
|
136,7 → 138,7
|
There are, however, some naming restrictions for this project. |
|
The directory name (presumably the name of the module, something like @code{uart16550}) should also be the name of the top level file, eg. @code{uart16550.v}, and the top level module should also be simply this name, eg. @code{module uart16550 (...}. |
The directory name (presumably the name of the module, something like @code{uart16550}) should also be the name of the top level file, eg. @code{uart16550.v}, and the top level module should also be simply this name, eg. @code{module uart16550 (...);}. |
|
This will avoid confusion and help the scripts locate modules. |
|
151,6 → 153,8
|
Despite this being far from a thorough verification platform, it is considered useful to be able to perform enough simulation to ensure that the fundamental system is correctly assembled and can communicate with the peripherals. |
|
It is expected that by running the command @code{make rtl-test} in each board's simulation run path, a basic simulation of the system initialising should be run. |
|
@node Organisation of Reference And Board Designs |
@section Reference And Board Designs |
|
214,7 → 218,7
Host system tools - things like gcc, make, texinfo. |
|
@item |
Target system toolchain and software - the OpenRISC GNU toolchain, with gcc crosscompiler, support libraries, the GNU debugger (gdb), OpenRISC port of various OSes and RTOS, etc. |
Target system toolchain and software - the OpenRISC GNU toolchain, with gcc cross-compiler, support libraries, the GNU debugger (gdb), OpenRISC port of various OSes and RTOS, etc. |
|
@item |
Electronic design automation (EDA) tools - preprocessors, simulators, FPGA tool suites, etc. |
438,7 → 442,7
When using Modelsim (specifying @code{SIMULATOR=modelsim}), if the version does not include the individual @code{vopt} executable, specify @code{MGC_NO_VOPT=1} when compiling. |
|
@item VPI |
Pass @code{VPI=1} to have the an external JTAG debug module stall the processor just after bootup, and then provide a GDB stub (interacting with the Verilog sim via the VPI) to allow control of the system in a similar fashtion to that of a physical target controlled over JTAG via a debug proxy application. The port for GDB is hardcoded to 50002. See the code in @code{bench/verilog/vpi/c} for more details. |
Pass @code{VPI=1} to have the an external JTAG debug module stall the processor just after bootup, and then provide a GDB stub (interacting with the Verilog sim via the VPI) to allow control of the system in a similar fashion to that of a physical target controlled over JTAG via a debug proxy application. The port for GDB is hard-coded to 50002. See the code in @code{bench/verilog/vpi/c} for more details. |
If running with Modelsim, ensure the path @code{MGC_PATH} is set and points to a directory containing a path named @code{modeltech}, which should be the Modelsim install. |
|
@end table |
643,7 → 647,7
Backend: Actel Designer (included in Actel Libero Suite) |
Programming: Actel FlashPRO (included in Actel Libero Suite) |
|
This has been tested with with Libero v8.6 and v9.0sp1 under Ubuntu Linux. |
This has been tested with with Libero versions 8.6, 9.0sp1 and 9.1 under Ubuntu Linux. It is recommended the very latest version available be used. |
|
@node ORDB1A3PE1500 Debug Tools |
@subsection Debug Tools |
869,7 → 873,7
|
Inspect that file to see which modules are able to be included. At present the list includes USB 1.1 host controller and/or slave interface, I2C master/slave core, and SPI master cores. |
|
These cores should be supported and ready to go by just defining them (uncomment in the @code{orspco-defines.v} file.) |
These cores should be supported and ready to go by just defining them (uncomment in the @code{orpsoc-defines.v} file.) |
|
@node ORDB1A3PE1500 Customising Adding Modules |
@subsection Adding RTL Modules |
914,7 → 918,7
|
The section in @code{backend/par/bin/Makefile} mapping signals to Makefile variables will need to have these new signals added to them. The section in the file begins with @code{$(PDC_FILE):} and is actually a set of long bash lines. |
|
Continuing the format already there should be easy enough. Remember that the @code{orspoc-defines.v} file is parsed and it's possible to tell if the module is included by testing if the variable is defined. |
Continuing the format already there should be easy enough. Remember that the @code{orpsoc-defines.v} file is parsed and it's possible to tell if the module is included by testing if the variable is defined. |
|
For example, to add I/Os for a module called @code{foo}, and in @code{orpsoc-defines.v} a value @code{FOO1} is defined, we can add I/Os @code{foo1_srx_i} and @code{foo1_tx_o[3:0]} with the following. |
|
984,7 → 988,7
|
At present the build contains a memory controller for the DDR2 SDRAM (based around a Xilinx MIG derived controller) and SSRAM. None of the other peripherals (VGA/AC97/PS2/USB/LCD) have controllers in the design yet. |
|
The OpenCores 10/100 Ethernet MAC can be used for Ethernet, but only with the PHY in 10/100 mode using the MII interface to the Marvel Alaska Ethernet PHY IC. There still may be bugs in the FIFO buffer configuration in the ethmac module when the Xilinx FIFO option is enabled via the ethmac_defines.v file. Adding GMII support to the MAC, is a TODO task. |
The OpenCores 10/100 Ethernet MAC can be used for Ethernet, but only with the PHY in 10/100 mode using the MII interface to the Marvel Alaska Ethernet PHY IC. There still may be bugs in the FIFO buffer configuration in the ML501's @code{ethmac_defines.v} file should not be changed. |
|
The project is configured to generate either a @code{.bit} file for direct programming via JTAG, or a @code{.mcs} file with inbuilt bootloader software for the processor, meaning the board can be powered up and an application like ORPmon loaded without having to reprogram it from iMPACT between power cycles. |
|
1008,6 → 1012,8
|
If the @code{XILINX_PATH} variable is not set correctly, the makefiles will not run. |
|
This build has been tested with ISE versions 11.1 and 12.3. |
|
@node ML501 Tools |
@section Tools |
|
1052,7 → 1058,7
@section Simulating |
@cindex simulating ML501 |
|
Ensure the @code{XILINX_PATH} environment variable is set correcetly. @xref{ML501 XILINX_PATH} for information. |
Ensure the @code{XILINX_PATH} environment variable is set correctly. @xref{ML501 XILINX_PATH} for information. |
|
Note that if this path is not set, simulations will not compile. |
|
1361,7 → 1367,7
|
Again, supply and ground leads for the UART drivers on the USB debugger can be sourced from J7/left-column J4 as per the debug interface subsection. |
|
If both UART and debug interface are connected via the ORSoC USB debugger, this ultimately ends up witht he first 2 pins on the right column of J4 as RX/TX for the UART then the JTAG TDO, TDI, TMS and TCK in succession down the right column of J4. |
If both UART and debug interface are connected via the ORSoC USB debugger, this ultimately ends up with the first 2 pins on the right column of J4 as RX/TX for the UART then the JTAG TDO, TDI, TMS and TCK in succession down the right column of J4. |
|
See the ML501 schematic (http://www.xilinx.com/support/documentation/boards_and_kits/ml501_20061010_bw.pdf) for more details on these headers, and refer to the pinouts in the ML501 UCF, in the board's @code{backend/par/bin/ml501.ucf} file. |
|
1408,7 → 1414,7
|
Each board port may contain additional software drivers and tests in its own software directory, the structure of which mimics that of the main software directory. |
|
@node Software Componenets |
@node Software Components |
@section Components |
|
This section outlines the different components of the software library in the @code{sw/} path in the root of @value{ORPSOC}. |
1452,7 → 1458,7
|
Test names are referenced using this @code{module}-@code{testname} pair. The automated testing mechanism implemented by the Makefile scripts will always search the @code{sim} paths for tests, rather than the @code{board} paths. |
|
@emph{Note:} There is no automated testing mechnism for the board-targeted software yet. It is anticipated that a testing harness for these will be developed, and we encourage users to help solve this problem. |
@emph{Note:} There is no automated testing mechanism for the board-targeted software yet. It is anticipated that a testing harness for these will be developed, and we encourage users to help solve this problem. |
|
@node Software Components Library |
@subsection Library |
1481,7 → 1487,7
|
@emph{Note:} For any tests or drivers named the same found in both a board's software path and the root software path, the @emph{board's} software will be used instead. |
|
@emph{Note:} When compiling any software in the @emph{root} software path (such as in the applications folder) intended to run on a particular board, make use of the @code{BOARD} variable to indicat which board's configuration (@code{board.h} file, and any board-specific drivers) to use. For example: |
@emph{Note:} When compiling any software in the @emph{root} software path (such as in the applications folder) intended to run on a particular board, make use of the @code{BOARD} variable to indicate which board's configuration (@code{board.h} file, and any board-specific drivers) to use. For example: |
|
@example |
@kbd{orpsoc/sw/apps/app1$ make app1.elf BOARD=xilinx/ml501} |
/trunk/orpsocv2/sim/bin/Makefile
66,6 → 66,7
or1200-ext \ |
or1200-cy \ |
or1200-ov \ |
or1200-sf \ |
or1200-ffl1 \ |
or1200-linkregtest \ |
or1200-tick \ |
/trunk/orpsocv2/sw/tests/ethmac/board/ethmac-ping.c
45,6 → 45,7
#include "printf.h" |
#include "eth-phy-mii.h" |
|
|
volatile unsigned tx_done; |
static int next_tx_buf_num; |
|
63,6 → 64,10
//#define OUR_IP_BYTES 0xac,0x1e,0x0,0x2 // 172.30.0.2 |
//#define OUR_IP_LONG 0xac1e0002 |
|
//#define OUR_IP_BYTES 0xa,0x0,0x0,0x14 // 10.0.0.20 |
//#define OUR_IP_LONG 0x0a000014 |
|
|
static char our_ip[4] = {OUR_IP_BYTES}; |
|
#define DEST_IP_BYTES 0xc0,0xa8,0x64,0x69 // 192 .168.100.105 |
69,10 → 74,12
//#define DEST_IP_BYTES 0xc0,0xa8,0x01,0x08 // 192 .168.1.8 |
//#define DEST_IP_BYTES 0xc0,0xa8,0x00,0x0f // 192 .168.0.15 |
//#define DEST_IP_BYTES 0xac,0x1e,0x0,0x01 // 172.30.0.1 |
//#define DEST_IP_BYTES 0xa,0x0,0x0,0x1 // 10.0.0.1 |
|
#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x64,0xff // 192.168.100.255 |
//#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x01,0xff // 192.168.1.255 |
//#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x00,0xff // 192.168.0.255 |
//#define BCAST_DEST_IP_BYTES 0xa,0x0,0x0,0xff // 10.0.0.255 |
|
/* Functions in this file */ |
void ethmac_setup(void); |
88,6 → 95,8
|
// Global used to control whether we print out packets as we receive them |
int print_packet_contents; |
int packet_inspect_debug; |
int print_ethmac_debug_reg; |
|
/* Let the ethernet packets use a space beginning here for buffering */ |
#define ETH_BUFF_BASE 0x01000000 |
104,8 → 113,8
|
/* Buffer number (must be 2^n) |
*/ |
#define OETH_RXBD_NUM 64 |
#define OETH_TXBD_NUM 64 |
#define OETH_RXBD_NUM 124 |
#define OETH_TXBD_NUM 4 |
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1) |
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1) |
|
137,6 → 146,82
// struct net_device_stats stats; |
}; |
|
#define PRINT_BIT_NAME(bit,name) printf("%02d:"name" %d\n",bit,!!(reg&(1<<bit))) |
void oeth_print_moder(unsigned long reg) |
{ |
PRINT_BIT_NAME(16,"RECSMALL"); |
PRINT_BIT_NAME(15,"PAD"); |
PRINT_BIT_NAME(14,"HUGEN"); |
PRINT_BIT_NAME(13,"CRCEN"); |
PRINT_BIT_NAME(12,"DLYCRCEN"); |
PRINT_BIT_NAME(10,"FULLD"); |
PRINT_BIT_NAME(9,"EXDFREN"); |
PRINT_BIT_NAME(8,"NOBCKOF"); |
PRINT_BIT_NAME(7,"LOOPBCK"); |
PRINT_BIT_NAME(6,"IFG"); |
PRINT_BIT_NAME(5,"PRO"); |
PRINT_BIT_NAME(4,"IAM"); |
PRINT_BIT_NAME(3,"BRO"); |
PRINT_BIT_NAME(2,"NOPRE"); |
PRINT_BIT_NAME(1,"TXEN"); |
PRINT_BIT_NAME(0,"RXEN"); |
} |
|
void oeth_print_intsource(unsigned long reg) |
{ |
PRINT_BIT_NAME(6,"RXCtrlFrame"); |
PRINT_BIT_NAME(5,"TXCtrlFrame"); |
PRINT_BIT_NAME(4,"BUSY"); |
PRINT_BIT_NAME(3,"RXE"); |
PRINT_BIT_NAME(2,"RXB"); |
PRINT_BIT_NAME(1,"TXE"); |
PRINT_BIT_NAME(0,"TXB"); |
} |
|
void oeth_print_ctrlmoder(unsigned long reg) |
{ |
PRINT_BIT_NAME(2,"TXFLOW"); |
PRINT_BIT_NAME(1,"RXFLOW"); |
PRINT_BIT_NAME(0,"PASSALL"); |
} |
|
void oeth_print_txbuf(unsigned long reg) |
{ |
printf("RD%d ",!!(reg&(1<<15))); |
printf("IQ%d ",!!(reg&(1<<14))); |
printf("WP%d ",!!(reg&(1<<13))); |
printf("PD%d ",!!(reg&(1<<12))); |
printf("CC%d ",!!(reg&(1<<11))); |
printf("UN%d ",!!(reg&(1<<8))); |
printf("RY%d ",!!(reg&(1<<3))); |
printf("LC%d ",!!(reg&(1<<2))); |
printf("DF%d ",!!(reg&(1<<1))); |
printf("CS%d ",!!(reg&(1<<0))); |
printf("\n"); |
|
} |
|
|
void oeth_print_rxbuf(unsigned long reg) |
{ |
printf("EM%d ",!!(reg&(1<<15))); |
printf("IQ%d ",!!(reg&(1<<14))); |
printf("WP%d ",!!(reg&(1<<13))); |
printf("PD%d ",!!(reg&(1<<12))); |
printf("CF%d ",!!(reg&(1<<8))); |
//printf("MS%d ",!!(reg&(1<<7))); |
printf("OR%d ",!!(reg&(1<<6))); |
printf("IS%d ",!!(reg&(1<<5))); |
printf("DN%d ",!!(reg&(1<<4))); |
printf("TL%d ",!!(reg&(1<<3))); |
printf("SF%d ",!!(reg&(1<<2))); |
printf("CE%d ",!!(reg&(1<<1))); |
printf("LC%d ",!!(reg&(1<<0))); |
printf("\n"); |
|
} |
|
// PRINT_BIT_NAME(,""); |
void oeth_printregs(void) |
{ |
volatile oeth_regs *regs; |
144,8 → 229,10
|
printf("Oeth regs: Mode Register : 0x%lx\n", |
(unsigned long) regs->moder); /* Mode Register */ |
oeth_print_moder((unsigned long) regs->moder); |
printf("Oeth regs: Interrupt Source Register 0x%lx\n", |
(unsigned long) regs->int_src); /* Interrupt Source Register */ |
oeth_print_intsource((unsigned long) regs->int_src); |
printf("Oeth regs: Interrupt Mask Register 0x%lx\n", |
(unsigned long) regs->int_mask); /* Interrupt Mask Register */ |
printf("Oeth regs: Back to Bak Inter Packet Gap Register 0x%lx\n", |
162,6 → 249,7
(unsigned long) regs->tx_bd_num); /* Transmit Buffer Descriptor Number Register */ |
printf("Oeth regs: Control Module Mode Register 0x%lx\n", |
(unsigned long) regs->ctrlmoder); /* Control Module Mode Register */ |
oeth_print_ctrlmoder((unsigned long) regs->ctrlmoder); |
printf("Oeth regs: MII Mode Register 0x%lx\n", |
(unsigned long) regs->miimoder); /* MII Mode Register */ |
printf("Oeth regs: MII Command Register 0x%lx\n", |
182,9 → 270,23
(unsigned long) regs->hash_addr0); /* Hash Register 0 */ |
printf("Oeth regs: Hash Register 1 0x%lx\n", |
(unsigned long) regs->hash_addr1); /* Hash Register 1 */ |
printf("Oeth regs: TXCTRL 0x%lx\n", |
(unsigned long) regs->txctrl); /* TX ctrl reg */ |
printf("Oeth regs: RXCTRL 0x%lx\n", |
(unsigned long) regs->rxctrl); /* RX ctrl reg */ |
printf("Oeth regs: WBDBG 0x%lx\n", |
(unsigned long) regs->wbdbg); /* Wishbone debug reg */ |
|
} |
|
void oeth_print_wbdebug(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
printf("Oeth regs: WBDBG 0x%lx\n", |
(unsigned long) regs->wbdbg); /* Wishbone debug reg */ |
} |
|
static int last_char; |
|
void spin_cursor(void) |
909,7 → 1011,61
return; |
} |
|
void oeth_ctrlmode_switch(void) |
{ |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
if (regs->ctrlmoder & (OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW)) |
{ |
printf("Disabling TX/RX flow control"); |
|
regs->ctrlmoder = 0; |
} |
else |
{ |
printf("Enabling TX/RX flow control"); |
|
regs->ctrlmoder = (OETH_CTRLMODER_TXFLOW | |
OETH_CTRLMODER_RXFLOW); |
|
} |
|
} |
|
void |
oeth_toggle_promiscuous(void) |
{ |
// from arch/or32/drivers/open_eth.c |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
if ( regs->moder & OETH_MODER_PRO ) |
{ |
printf("Disabling "); |
regs->moder &= ~OETH_MODER_PRO; |
|
} |
else |
{ |
printf("Enabling "); |
regs->moder |= OETH_MODER_PRO; |
|
} |
printf("promisucous mode\n"); |
} |
|
void oeth_transmit_pause(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->txctrl = 0x1fffe; |
} |
|
|
void |
ethmac_togglehugen(void) |
{ |
|
982,7 → 1138,7
|
/* print packet contents */ |
static void |
oeth_print_packet(unsigned long add, int len) |
oeth_print_packet(int bd, unsigned long add, int len) |
{ |
|
int truncate = (len > 256); |
989,7 → 1145,7
int length_to_print = truncate ? 256 : len; |
|
int i; |
printf("\nipacket: add = %lx len = %d\n", add, len); |
printf("\nbd%03d packet: add = %lx len = %d\n", bd,add, len); |
for(i = 0; i < length_to_print; i++) { |
if(!(i % 8)) |
printf(" "); |
1062,7 → 1218,13
*/ |
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ); |
|
next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
//next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
next_tx_buf_num++; |
if (next_tx_buf_num == OETH_TXBD_NUM) |
{ |
next_tx_buf_num = 0; |
} |
|
|
return; |
|
1090,7 → 1252,7
{ |
// Something in this buffer! |
printf("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); |
oeth_print_packet(i,rx_bd[i].addr, rx_bd[i].len_status >> 16); |
/* Clear recieved bit */ |
rx_bd[i].len_status |= OETH_RX_BD_EMPTY; |
printf("\t end of packet\n\n"); |
1098,23 → 1260,36
} |
} |
|
#include "spr-defs.h" |
|
/* Print out all buffer descriptors */ |
void oeth_dump_bds() |
{ |
unsigned long* bd_base = (unsigned long*) OETH_BD_BASE; |
// Disable interrupts |
mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_IEE); |
|
int i; |
for(i=0;i<OETH_TXBD_NUM;i++) |
{ |
printf("oeth: tx_bd%d: len_status: %lx ",i,*bd_base++); |
printf("addr: %lx\n", *bd_base++); |
} |
unsigned long* bd_base = (unsigned long*) OETH_BD_BASE; |
|
for(i=0;i<OETH_RXBD_NUM;i++) |
{ |
printf("oeth: rx_bd%d: len_status: %lx ",i,*bd_base++); |
printf("addr: %lx\n", *bd_base++); |
} |
int i; |
for(i=0;i<OETH_TXBD_NUM;i++) |
{ |
printf("TXBD%03d len_status %08lx ",i,*bd_base); |
oeth_print_txbuf(*bd_base++); |
//printf("addr: %lx\n", *bd_base++); |
*bd_base++; |
} |
|
for(i=0;i<OETH_RXBD_NUM;i++) |
{ |
printf("RXBD%03d len_status %08lx ",i,*bd_base); |
oeth_print_rxbuf(*bd_base++); |
*bd_base++; |
|
//printf("addr: %lx\n", *bd_base++); |
} |
|
// Enable interrupts |
mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_IEE); |
|
} |
|
1318,70 → 1493,89
oeth_interrupt(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
uint int_events; |
int serviced; |
uint int_events; |
int serviced; |
|
serviced = 0; |
serviced = 0; |
|
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
|
|
/* Indicate busy */ |
if (int_events & OETH_INT_BUSY) |
{ |
printf("\tBusy flag\n"); |
/* |
printf("\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); |
*/ |
printf("=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); |
/* Indicate busy */ |
if (int_events & OETH_INT_BUSY) |
{ |
printf("\tBusy flag\n"); |
/* |
printf("\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); |
*/ |
printf("=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); |
|
printf("=int | txb %d | txe %d | rxb %d | rxe %d | busy %d\n", |
(int_events & OETH_INT_TXB) > 0, |
(int_events & OETH_INT_TXE) > 0, |
(int_events & OETH_INT_RXF) > 0, |
(int_events & OETH_INT_RXE) > 0, |
(int_events & OETH_INT_BUSY) > 0); |
} |
|
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
oeth_rx(); |
} |
printf("=int | rxc %d | txc %d | txb %d | txe %d | rxb %d | rxe %d | busy %d\n", |
(int_events & OETH_INT_RXC) > 0, |
(int_events & OETH_INT_TXC) > 0, |
(int_events & OETH_INT_TXB) > 0, |
(int_events & OETH_INT_TXE) > 0, |
(int_events & OETH_INT_RXF) > 0, |
(int_events & OETH_INT_RXE) > 0, |
(int_events & OETH_INT_BUSY) > 0); |
}/* |
else |
printf("=int | rxc %d | txc %d | txb %d | txe %d | rxb %d | rxe %d | busy %d\n", |
(int_events & OETH_INT_RXC) > 0, |
(int_events & OETH_INT_TXC) > 0, |
(int_events & OETH_INT_TXB) > 0, |
(int_events & OETH_INT_TXE) > 0, |
(int_events & OETH_INT_RXF) > 0, |
(int_events & OETH_INT_RXE) > 0, |
(int_events & OETH_INT_BUSY) > 0); |
*/ |
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
oeth_rx(); |
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
} |
|
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
|
} |
} |
|
return; |
return; |
} |
|
// ARP stuff |
1552,6 → 1746,10
// Check for ICMP echo request type |
if (!(icmp->type == ICMP_TYPE_ECHO_REQ)) |
return; |
|
// Skip forward to the target I.P address |
if (packet_inspect_debug) |
printf("Ping packet\n"); |
|
// Go ahead and construct a response packet |
// Setup pointers |
1701,11 → 1899,15
|
if (arp->ar_hrd == ARP_ETHER && arp->ar_op == ARPOP_REQUEST) |
{ |
// Skip forward to the target I.P address |
// Skip forward to the target I.P address |
if (packet_inspect_debug) |
printf("ARP packet\n"); |
|
char * internet_protocol_adr = (((unsigned long)&arp->ar_data[0]) + (arp->ar_hln * 2) + (arp->ar_pln)); |
char * internet_protocol_adr = (((unsigned long)&arp->ar_data[0]) + |
(arp->ar_hln * 2) + (arp->ar_pln)); |
|
//printf("Is ARP ethernet request\ncheck adr at 0x%.8x\n",internet_protocol_adr); |
//printf("Is ARP ethernet request\ncheck adr at 0x%.8x\n", |
// internet_protocol_adr); |
if ((internet_protocol_adr[0] == our_ip[0]) && |
(internet_protocol_adr[1] == our_ip[1]) && |
(internet_protocol_adr[2] == our_ip[2]) && |
1731,15 → 1933,18
reply_arp->ar_pln = 0x04; |
reply_arp->ar_op = ARPOP_REPLY; |
// My MAC |
memcpy( (void*)&reply_arp->ar_data[0] , (void*)&reply_pkt->et_src , 6); |
memcpy( (void*)&reply_arp->ar_data[0] , |
(void*)&reply_pkt->et_src , 6); |
// My IP |
memcpy( (void*)&reply_arp->ar_data[6] , (void*)&our_ip , 4); |
// Their MAC |
memcpy( (void*)&reply_arp->ar_data[10] , (void*)ð_pkt->et_src , 6); |
memcpy( (void*)&reply_arp->ar_data[10] , |
(void*)ð_pkt->et_src , 6); |
// Their IP |
char * their_internet_protocol_adr = |
(((unsigned long)&arp->ar_data[0]) + arp->ar_hln ); |
memcpy( (void*)&reply_arp->ar_data[16] , (void*)&their_internet_protocol_adr[0] , 4); |
memcpy( (void*)&reply_arp->ar_data[16] , |
(void*)&their_internet_protocol_adr[0] , 4); |
|
tx_packet((void*)arp_reply_packet,(ETHER_HDR_SIZE+ARP_HDR_SIZE) ); |
|
1753,74 → 1958,84
static void |
oeth_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
|
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
if (print_packet_contents) |
printf("rx"); |
if (print_packet_contents) |
printf("rx "); |
|
/* 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) { |
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
/* Looking for NOT empty buffers desc. */ |
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ |
/* 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 (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
} |
|
if (bad) { |
printf("RXE: 0x%x\n",rx_bdp[i].len_status & OETH_RX_BD_STATS); |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
bad = 0; |
continue; |
} |
else { |
if (bad) { |
printf("RXE: 0x%x\n",rx_bdp[i].len_status & |
OETH_RX_BD_STATS); |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
bad = 0; |
continue; |
} |
else { |
|
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
|
/* Do something here with the data - copy it into userspace, perhaps. */ |
// See if it's an ARP packet |
packet_check_arp_header((void *)rx_bdp[i].addr ); |
// See if it's an ICMP echo request |
packet_check_icmp_header((void *)rx_bdp[i].addr ); |
if (print_packet_contents) |
{ |
oeth_print_packet(rx_bdp[i].addr, rx_bdp[i].len_status >> 16); |
printf("\t end of packet\n\n"); |
} |
/* 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 */ |
/* Do something here with the data - copy it |
into userspace, perhaps. */ |
// See if it's an ARP packet |
packet_check_arp_header((void*)rx_bdp[i].addr); |
// See if it's an ICMP echo request |
packet_check_icmp_header((void*)rx_bdp[i].addr); |
if (print_packet_contents) |
{ |
oeth_print_packet(i, rx_bdp[i].addr, |
rx_bdp[i].len_status |
>> 16); |
printf("\t end of packet\n\n"); |
} |
/* finish up */ |
/* Clear stats */ |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
/* Mark RX BD as empty */ |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
|
oeth_transmit_pause(); //try this! |
|
|
} |
} |
} |
} |
} |
} |
|
|
1828,33 → 2043,37
static void |
oeth_tx(void) |
{ |
volatile oeth_bd *tx_bd; |
int i; |
if (print_packet_contents) |
printf("tx"); |
volatile oeth_bd *tx_bd; |
int i; |
if (print_packet_contents) |
printf("tx"); |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
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)) ) |
/* Go through the TX buffs, search for one that was just sent */ |
for(i = 0; i < OETH_TXBD_NUM; i++) |
{ |
//oeth_print_packet(tx_bd[i].addr, (tx_bd[i].len_status >> 16)); |
/* 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; |
/* 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 */ |
// Check if either carrier sense lost or colission indicated |
if (tx_bd[i].len_status & OETH_TX_BD_STATS) |
printf("TXER: 0x%x\n",(tx_bd[i].len_status & OETH_TX_BD_STATS)); |
/* Probably good to check for TX errors here */ |
// Check if either carrier sense lost or colission |
// indicated |
if (tx_bd[i].len_status & OETH_TX_BD_STATS) |
printf("TXER: 0x%x\n", |
(tx_bd[i].len_status &OETH_TX_BD_STATS)); |
|
if (print_packet_contents) |
printf("T%d",i); |
if (print_packet_contents) |
printf("T%d",i); |
} |
} |
} |
return; |
return; |
} |
|
|
1861,126 → 2080,157
int main () |
{ |
|
print_packet_contents = 0; // Default to not printing packet contents. |
|
/* Initialise vector handler */ |
int_init(); |
print_packet_contents = 0; // Default to not printing packet contents. |
packet_inspect_debug = 0; |
print_ethmac_debug_reg = 0; |
|
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
/* Initialise vector handler */ |
int_init(); |
|
/* Enable interrupts */ |
cpu_enable_user_interrupts(); |
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
|
/* Enable interrupts */ |
cpu_enable_user_interrupts(); |
|
last_char=0; /* Variable init for spin_cursor() */ |
next_tx_buf_num = 4; /* init for tx buffer counter */ |
last_char=0; /* Variable init for spin_cursor() */ |
next_tx_buf_num = 4; /* init for tx buffer counter */ |
|
uart_init(DEFAULT_UART); // init the UART before we can printf |
printf("\n\teth ping program\n\n"); |
printf("\n\tboard IP: %d.%d.%d.%d\n",our_ip[0]&0xff,our_ip[1]&0xff, |
our_ip[2]&0xff,our_ip[3]&0xff); |
uart_init(DEFAULT_UART); // init the UART before we can printf |
printf("\n\teth ping program\n\n"); |
printf("\n\tboard IP: %d.%d.%d.%d\n",our_ip[0]&0xff,our_ip[1]&0xff, |
our_ip[2]&0xff,our_ip[3]&0xff); |
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */ |
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 */ |
//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 */ |
|
/* Loop, monitoring user input from TTY */ |
while(1) |
{ |
char c; |
|
while(!uart_check_for_char(DEFAULT_UART)) |
/* Loop, monitoring user input from TTY */ |
while(1) |
{ |
spin_cursor(); |
//oeth_monitor_rx(); |
} |
char c; |
|
c = uart_getc(DEFAULT_UART); |
while(!uart_check_for_char(DEFAULT_UART)) |
{ |
|
spin_cursor(); |
|
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
} |
|
c = uart_getc(DEFAULT_UART); |
|
if (c == 's') |
tx_packet((void*) ping_packet, 98); |
else if (c == 'S') |
tx_packet((void*)big_ping_packet, 1514); |
else if (c == 'h') |
scan_ethphys(); |
else if (c == 'i') |
ethphy_init(); |
else if (c == 'P') |
{ |
print_packet_contents = print_packet_contents ? 0 : 1; |
if (print_packet_contents) |
printf("Enabling packet dumping\n"); |
else |
printf("Packet dumping disabled\n"); |
} |
else if (c == 'p') |
oeth_printregs(); |
else if (c == '0') |
scan_ethphy(0); |
else if (c == '1') |
scan_ethphy(1); |
else if (c == '7') |
{ |
//scan_ethphy(7); |
//ethphy_print_status(7); |
printf("ext_sr 0x%x\n",eth_mii_read(0x7, 0x1b)); |
} |
else if (c == 'r') |
{ |
ethphy_reset(7); |
printf("PHY reset\n"); |
} |
else if (c == 'R') |
{ |
//oeth_reset_tx_bd_pointer(); |
ethmac_setup(); |
printf("MAC reset\n"); |
} |
else if (c == 'n') |
ethphy_reneg(7); |
else if (c == 'N') |
ethphy_set_autoneg(7); |
else if (c == 'm') |
ethmac_togglehugen(); |
else if (c == 't') |
ethphy_set_10mbit(0); |
else if (c == 'w') |
{ |
// Play with HWCFG mode of Alaska 88e1111 Phy |
c = uart_getc(DEFAULT_UART); |
short newvalue; |
// c is an ascii char, let's convert it to actual hex value |
if (c >= 'A' && c <= 'F') |
newvalue = c - (65 - 10); |
else if (c >= 'a' && c <= 'f') |
newvalue = c - (99 - 10); |
else if (c >= '0' && c <= '9') |
newvalue = c - 48; |
if (c == 's') |
tx_packet((void*) ping_packet, 98); |
else if (c == 'S') |
tx_packet((void*)big_ping_packet, 1514); |
else if (c == 'h') |
scan_ethphys(); |
else if (c == 'i') |
ethphy_init(); |
else if (c == 'c') |
oeth_ctrlmode_switch(); |
else if (c == 'P') |
{ |
print_packet_contents = print_packet_contents ? 0 : 1; |
if (print_packet_contents) |
printf("Enabling packet dumping\n"); |
else |
printf("Packet dumping disabled\n"); |
} |
else if (c == 'p') |
oeth_printregs(); |
else if (c == '0') |
scan_ethphy(0); |
else if (c == '1') |
scan_ethphy(1); |
else if (c == '7') |
{ |
//scan_ethphy(7); |
//ethphy_print_status(7); |
printf("ext_sr 0x%x\n",eth_mii_read(0x7, 0x1b)); |
} |
else if (c == 'r') |
{ |
ethphy_reset(7); |
printf("PHY reset\n"); |
} |
else if (c == 'R') |
{ |
//oeth_reset_tx_bd_pointer(); |
ethmac_setup(); |
printf("MAC reset\n"); |
} |
else if (c == 'n') |
ethphy_reneg(7); |
else if (c == 'N') |
ethphy_set_autoneg(7); |
else if (c == 'm') |
ethmac_togglehugen(); |
else if (c == 't') |
ethphy_set_10mbit(0); |
else if (c == 'w') |
{ |
// Play with HWCFG mode of Alaska 88e1111 Phy |
c = uart_getc(DEFAULT_UART); |
short newvalue; |
// c is an ascii char, let's convert it to actual hex |
// value |
if (c >= 'A' && c <= 'F') |
newvalue = c - (65 - 10); |
else if (c >= 'a' && c <= 'f') |
newvalue = c - (99 - 10); |
else if (c >= '0' && c <= '9') |
newvalue = c - 48; |
|
// Take this value and or it into the bottom bit (supposedly ext_sr) |
// Take this value and or it into the bottom bit |
// (supposedly ext_sr) |
#define MII_M1111_PHY_EXT_SR 0x1b |
short ext_sr; |
ext_sr = eth_mii_read(0x7, MII_M1111_PHY_EXT_SR); |
short ext_sr; |
ext_sr = eth_mii_read(0x7, MII_M1111_PHY_EXT_SR); |
#define MII_M1111_HWCFG_MODE_MASK 0xf |
ext_sr &= ~MII_M1111_HWCFG_MODE_MASK; |
ext_sr |= (short) newvalue; |
eth_mii_write(0x7, MII_M1111_PHY_EXT_SR, ext_sr); |
printf("ext_sr updated to - 0x%x\n",eth_mii_read(0x7, MII_M1111_PHY_EXT_SR)); |
} |
else if ( c == 'b' ) |
{ |
printf("\n\t---\n"); |
oeth_dump_bds(); |
printf("\t---\n"); |
} |
ext_sr &= ~MII_M1111_HWCFG_MODE_MASK; |
ext_sr |= (short) newvalue; |
eth_mii_write(0x7, MII_M1111_PHY_EXT_SR, ext_sr); |
printf("ext_sr updated to - 0x%x\n", |
eth_mii_read(0x7, MII_M1111_PHY_EXT_SR)); |
} |
else if ( c == 'b' ) |
{ |
printf("\n\t---\n"); |
oeth_dump_bds(); |
printf("\t---\n"); |
} |
|
else if ( c == 'B' ) |
{ |
tx_packet((void*) broadcast_ping_packet, 298); |
else if ( c == 'B' ) |
{ |
tx_packet((void*) broadcast_ping_packet, 298); |
} |
else if (c == 'u' ) |
oeth_transmit_pause(); |
else if (c == 'd' ) |
{ |
oeth_print_wbdebug(); |
print_ethmac_debug_reg = !print_ethmac_debug_reg; |
} |
else if (c == 'v' ) |
{ |
if (packet_inspect_debug) |
printf("Disabling "); |
else |
printf("Enabling "); |
|
printf("packet type announcments\n"); |
|
packet_inspect_debug = !packet_inspect_debug; |
} |
else if ( c == 'o' ) |
oeth_toggle_promiscuous(); |
|
} |
|
} |
|
} |
/trunk/orpsocv2/sw/tests/ethmac/sim/ethmac-rxtxcallresponse.c
5,10 → 5,6
//// Description //// |
//// Send packets while receiving packets //// |
//// //// |
//// Test data comes from pre-calculated array of random values, //// |
//// MAC TX buffer pointers are set to addresses in this array, //// |
//// saving copying the data around before transfers. //// |
//// //// |
//// Author(s): //// |
//// - jb, jb@orsoc.se, with parts taken from Linux kernel //// |
//// open_eth driver. //// |
479,6 → 475,7
report(0xbaad0004); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
// not necessarily an issue |
report(0xbaad0005); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
636,7 → 633,7
send_ethmac_rxtx_test_init_packet(0x0); // 0x0 - call response test |
|
#define ETH_TX_MIN_PACKET_SIZE 512 |
#define ETH_TX_NUM_PACKETS (ETH_TX_MIN_PACKET_SIZE + 20) |
#define ETH_TX_NUM_PACKETS 20 |
|
//int response_time = 150000; // Response time before response packet it sent |
// back (should be in nanoseconds). |
644,7 → 641,7
|
unsigned long num_to_check; |
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check<ETH_TX_MIN_PACKET_SIZE + ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_call_packet(num_to_check, response_time); |
|
660,7 → 657,7
oeth_enable_rx(); |
|
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check<ETH_TX_MIN_PACKET_SIZE + ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_call_packet(num_to_check, response_time); |
|
/trunk/orpsocv2/sw/tests/ethmac/sim/ethmac-rxtxoverflow.c
0,0 → 1,602
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Interrupt-driven Ethernet MAC transmit test code //// |
//// //// |
//// Description //// |
//// Attempt to overflow the RX path in MAC //// |
//// //// |
//// 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 //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
// Test sends the test code (0x1) for overflow test in first packet, which is |
// read by Verilog stimulus module. |
|
// SW is setup to echo back all packets it receives. TB sends 16 packets, as |
// fast as possible, which should saturate the MAC's buffers. |
// TB then waits for a BD to be ready and sends one more packet, and ensures |
// that arrives in memory OK. |
// Test is over when this software manages to send back 4 reply packets. |
|
#include "cpu-utils.h" |
#include "board.h" |
#include "int.h" |
#include "ethmac.h" |
#include "eth-phy-mii.h" |
|
volatile unsigned tx_done; |
volatile unsigned rx_done; |
static int next_tx_buf_num; |
|
/* Functions in this file */ |
void ethmac_setup(void); |
/* Interrupt functions */ |
void oeth_interrupt(void); |
static void oeth_rx(void); |
static void oeth_tx(void); |
|
/* 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 16 |
#define OETH_TXBD_NUM 16 |
#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 0x600-4 |
#define OETH_TX_BUFF_SIZE 0x600-4 |
|
/* 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; |
}; |
|
#define PHYNUM 7 |
|
void |
eth_mii_write(char phynum, short regnum, short data) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miitx_data = data; |
regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
} |
|
short |
eth_mii_read(char phynum, short regnum) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miicommand = OETH_MIICOMMAND_RSTAT; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
|
return regs->miirx_data; |
} |
|
|
|
// Wait here until all packets have been transmitted |
void |
wait_until_all_tx_clear(void) |
{ |
int i; |
volatile oeth_bd *tx_bd; |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
int some_tx_waiting = 1; |
|
while (some_tx_waiting) |
{ |
some_tx_waiting = 0; |
/* Go through the TX buffs, search for unused one */ |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
|
// Looking for buffer ready for transmit |
if((tx_bd[i].len_status & OETH_TX_BD_READY)) |
some_tx_waiting = 1; |
|
} |
} |
} |
|
|
void |
ethphy_set_10mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 10Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr &= ~BMCR_ANENABLE; // Clear auto negotiate bit |
cr &= ~BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethphy_set_100mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 100Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr |= BMCR_ANENABLE; // Clear auto negotiate bit |
cr |= BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethmac_setup(void) |
{ |
// from arch/or32/drivers/open_eth.c |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
/* 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 */ |
|
/* 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; |
|
// 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 TX Buffers |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
//tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ; |
tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC; |
tx_bd[i].addr = mem_addr; |
mem_addr += OETH_TX_BUFF_SIZE; |
} |
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP; |
|
// Setup RX buffers |
for(i = 0; i < OETH_RXBD_NUM; i++) { |
rx_bd[i].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; // Init. with IRQ |
rx_bd[i].addr = mem_addr; |
mem_addr += OETH_RX_BUFF_SIZE; |
} |
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; // Last buffer wraps |
|
/* Enable RX and TX in MAC |
*/ |
regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN); |
regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN; |
|
next_tx_buf_num = 0; // init tx buffer pointer |
|
return; |
} |
|
// Enable RX in ethernet MAC |
void |
oeth_enable_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->moder |= OETH_MODER_RXEN; |
} |
|
// Disable RX in ethernet MAC |
void |
oeth_disable_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->moder &= ~(OETH_MODER_RXEN); |
} |
|
|
/* 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; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
tx_bd = (struct oeth_bd*) &tx_bd[next_tx_buf_num]; |
|
// If it's in use - wait |
while ((tx_bd->len_status & OETH_TX_BD_IRQ)); |
|
/* 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; |
|
if ((int) data != 0){ |
//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]; |
} |
} |
|
/* Set the length of the packet's data in the buffer descriptor */ |
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) | |
((length&0xffff) << 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); |
|
next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
|
tx_done++; |
|
// This test over after 4 packets sent. |
if (tx_done == 4) |
{ |
report(0x8000000d); |
exit(0); |
} |
|
return; |
|
|
} |
|
/* The interrupt handler. |
*/ |
void |
oeth_interrupt(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
uint int_events; |
int serviced; |
|
serviced = 0; |
|
/* 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(); |
serviced |= 0x2; |
|
} |
|
/* Check for receive busy, i.e. packets coming but no place to |
* put them. |
*/ |
if (int_events & OETH_INT_BUSY) { |
serviced |= 0x4; |
if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE))) |
oeth_rx(); |
} |
|
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; |
|
|
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
bad=0; |
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; |
report(0xbaad0001); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) { |
bad = 1; |
report(0xbaad0002); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) { |
bad = 1; |
report(0xbaad0003); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) { |
bad = 1; |
report(0xbaad0004); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
// not necessarily an issue |
report(0xbaad0005); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
report(0xbaad0006); |
} |
if (bad) { |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
exit(0xbaaaaaad); |
|
continue; |
} |
else { |
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
|
// Attempt to transmit it back |
tx_packet((void*)rx_bdp[i].addr,pkt_len); |
|
/* 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 */ |
rx_done++; |
} |
} |
} |
} |
|
|
|
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++; |
|
// This test over after 4 packets sent. |
if (tx_done == 4) |
{ |
report(0x8000000d); |
exit(0); |
} |
|
} |
} |
return; |
} |
|
// Send a packet, the very first byte of which will be read by the testbench |
// and used to indicate which test we'll use. |
static char cmd_tx_buffer[40]; |
void |
send_ethmac_rxtx_test_init_packet(char test) |
{ |
int i; |
|
cmd_tx_buffer[0] = test; |
// Clear rest of buffer |
for(i=0;i<40;i++) cmd_tx_buffer[i] = test; |
tx_packet(cmd_tx_buffer, 40); // Smallest packet that can be sent |
} |
|
// Loop to check if a number is prime by doing mod divide of the number |
// to test by every number less than it |
int |
is_prime_number(unsigned long n) |
{ |
unsigned long c; |
if (n < 2) return 0; |
for(c=2;c<n;c++) |
if ((n % c) == 0) |
return 0; |
return 1; |
} |
|
|
int |
main () |
{ |
|
/* Initialise handler vector */ |
int_init(); |
|
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
|
/* Enable interrupts in supervisor register */ |
cpu_enable_user_interrupts(); |
|
/* Enable CPU timer */ |
cpu_enable_timer(); |
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX */ |
|
/* clear tx_done, the tx interrupt handler will set it when it's been |
transmitted */ |
tx_done = 0; |
rx_done = 0; |
|
ethphy_set_100mbit(0); |
|
send_ethmac_rxtx_test_init_packet(0x1); // 0x1 - overflow test |
|
while(1); // Sit and wait for test to finish in interrupt-triggered code |
|
} |
/trunk/orpsocv2/sw/tests/or1200/sim/or1200-cy.S
102,7 → 102,7
|
.global _start |
_start: |
// Clear all regs |
// Clear regs |
l.movhi r1, 0 |
l.movhi r2, 0 |
l.movhi r3, 0 |
109,31 → 109,6
l.movhi r4, 0 |
l.movhi r5, 0 |
l.movhi r6, 0 |
l.movhi r7, 0 |
l.movhi r8, 0 |
l.movhi r9, 0 |
l.movhi r10, 0 |
l.movhi r11, 0 |
l.movhi r12, 0 |
l.movhi r13, 0 |
l.movhi r14, 0 |
l.movhi r15, 0 |
l.movhi r16, 0 |
l.movhi r17, 0 |
l.movhi r18, 0 |
l.movhi r19, 0 |
l.movhi r20, 0 |
l.movhi r21, 0 |
l.movhi r22, 0 |
l.movhi r23, 0 |
l.movhi r24, 0 |
l.movhi r25, 0 |
l.movhi r26, 0 |
l.movhi r27, 0 |
l.movhi r28, 0 |
l.movhi r29, 0 |
l.movhi r30, 0 |
l.movhi r31, 0 |
|
#ifdef OR1200_IMPL_CY |
// Kick off test |
149,16 → 124,16
|
|
#define CHECK_CY_CLEAR \ |
l.mfspr r20, r0, SPR_SR ; \ |
l.andi r21, r20, SPR_SR_CY ; \ |
l.sfne r21, r0 ; \ |
l.mfspr r6, r0, SPR_SR ; \ |
l.andi r6, r6, SPR_SR_CY ; \ |
l.sfne r6, r0 ; \ |
l.bf _fail ; \ |
l.nop |
|
#define CHECK_CY_SET \ |
l.mfspr r20, r0, SPR_SR ; \ |
l.andi r21, r20, SPR_SR_CY ; \ |
l.sfnei r21, SPR_SR_CY ; \ |
l.mfspr r6, r0, SPR_SR ; \ |
l.andi r6, r6, SPR_SR_CY ; \ |
l.sfnei r6, SPR_SR_CY ; \ |
l.bf _fail ; \ |
l.nop |
|
/trunk/orpsocv2/sw/tests/or1200/sim/or1200-basic.S
83,110 → 83,9
|
.global _start |
_start: |
|
/* Instruction cache enable */ |
/* Check if IC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_ICP |
l.sfeq r26,r0 |
l.bf .L8 |
l.jal _cache_init |
l.nop |
|
/* Disable IC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_ICE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
|
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_ICCFGR |
l.andi r26,r24,SPR_ICCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
|
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_ICCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
|
/* Invalidate IC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
|
.L7: |
l.mtspr r0,r6,SPR_ICBIR |
l.sfne r6,r5 |
l.bf .L7 |
l.add r6,r6,r14 |
|
/* Enable IC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_ICE |
l.mtspr r0,r6,SPR_SR |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
|
.L8: |
/* Data cache enable */ |
/* Check if DC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_DCP |
l.sfeq r26,r0 |
l.bf .L10 |
l.nop |
/* Disable DC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_DCE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_DCCFGR |
l.andi r26,r24,SPR_DCCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_DCCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
/* Invalidate DC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
.L9: |
l.mtspr r0,r6,SPR_DCBIR |
l.sfne r6,r5 |
l.bf .L9 |
l.add r6,r6,r14 |
/* Enable DC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_DCE |
l.mtspr r0,r6,SPR_SR |
.L10: |
// Kick off test |
l.jal _main |
l.nop |
1100,4 → 999,5
l.nop 0x2 |
l.ori r3, r0, 0 /* Clear R3 */ |
l.nop 0x1 /* Exit simulation */ |
|
l.nop |
l.nop |
/trunk/orpsocv2/sw/tests/or1200/sim/or1200-intsyscall.S
8,9 → 8,9
Within the test we'll use following global variables: |
|
r15 syscall interrupt counter |
r16 syscall function counter |
r17 irq interrupt counter |
r18 intgen's base address |
r6 syscall function counter |
r10 irq interrupt counter |
r12 intgen's base address |
|
|
The test does the following: |
77,15 → 77,15
.org 0x800 |
.global _user_irq_handler |
_user_irq_handler: |
l.addi r17, r17, 1 |
l.addi r10, r10, 1 |
/* Report values , 0x00000800 == user interrupt report*/ |
l.ori r3, r0, 0x0800 |
l.nop 2 |
l.or r3, r0, r17 |
l.or r3, r0, r10 |
l.nop 2 |
/* TODO - propably confirm it was intgen's IRQ that caused this */ |
/* Clear interrupt source */ |
l.ori r7, r18, 0x1 /* intgen IRQ clear address */ |
l.ori r7, r12, 0x1 /* intgen IRQ clear address */ |
l.sb 0(r7), r0 /* Any write clears the bit */ |
/* Clear OR1200 PICSR */ |
l.mfspr r7, r0, SPR_PICSR |
107,7 → 107,7
l.xor r5, r5, r4 |
l.and r5, r7, r5 /* New SR without interrupt bits set */ |
l.mtspr r0, r5, SPR_ESR_BASE /* SR after l.rfe */ |
/* Report values , 0x00000c00 == tick timer report*/ |
/* Report values , 0x00000c00 == system call report*/ |
l.ori r3, r0, 0x0c00 |
l.nop 2 |
/* Get syscall number */ |
135,9 → 135,6
/* =================================================== [ main ] === */ |
.global _main |
_main: |
l.movhi r15, 0 |
l.movhi r16, 0 |
l.movhi r17, 0 |
|
# |
# unmask (enable) all ints |
151,13 → 148,18
l.ori r6,r6,SPR_SR_IEE |
l.mtspr r0,r6,SPR_SR |
|
l.movhi r15, 0 |
l.movhi r6, 0 |
l.movhi r10, 0 |
|
|
|
// Assumes r18 is intgen's base address |
l.movhi r18,hi(INTGEN_BASE) |
// Assumes r12 is intgen's base address |
l.movhi r12,hi(INTGEN_BASE) |
|
#define INTGEN_LOAD(x) \ |
l.ori r5,r0,lo(x) ;\ |
l.sb 0(r18),r5 |
l.sb 0(r12),r5 |
|
|
/* Test begin */ |
179,11 → 181,11
l.nop |
l.ori r5,r0,1 |
l.sys 0x5 |
l.sb 0(r18),r5 |
l.sb 0(r12),r5 |
l.nop |
l.nop |
l.nop |
l.sfnei r16, 0xf /* Should equal 15, 0xf */ |
l.sfnei r6, 0xf /* Should equal 15, 0xf */ |
l.bf _fail |
l.nop |
|
204,15 → 206,15
/* We'll restore them now */ |
l.mtspr r0, r7, SPR_ESR_BASE /* SR before syscall */ |
l.mtspr r0, r8, SPR_EPCR_BASE |
l.add r16, r16, r3 /* Add syscall number to our counter */ |
l.add r6, r6, r3 /* Add syscall number to our counter */ |
l.movhi r4, hi(0x00400000) /* 4MB mark of memory */ |
/* Ensure memory access OK */ |
l.slli r3, r3, 2 /* Turn syscall number into a word address (<< 2) */ |
l.add r4, r4, r3 /* Access this offset from 4MB mark */ |
l.sw 0(r4), r16 /* Do a write to memory */ |
l.lwz r16, 0(r4) /* Do a read from memory */ |
l.sw 0(r4), r6 /* Do a write to memory */ |
l.lwz r6, 0(r4) /* Do a read from memory */ |
/* Report running value of syscall counter */ |
l.or r3, r0, r16 |
l.or r3, r0, r6 |
l.nop 2 |
l.rfe /* Now continue from where we had the l.sys */ |
|
/trunk/orpsocv2/sw/tests/or1200/sim/or1200-except.S
95,7 → 95,7
l.mfspr r3,r0,SPR_EEAR_BASE /* Get EEA */ |
l.nop 2 |
l.addi r11,r11,1 /* Increment 1st exception counter */ |
l.sfeqi r30, 0xd /* Is this a data bus test, if so return with l.rfe */ |
l.sfeqi r2, 0xd /* Is this a data bus test, if so return with l.rfe */ |
l.bf 1f |
l.movhi r5, 0 /* r5 should be the one causing the error on dbus */ |
/* Instruction bus error test return */ |
138,27 → 138,32
.global _dtlb_handler |
/* Exception handler - DMMU TLB miss */ |
/* Assume 64-entry TLB cache */ |
_dtlb_handler: |
l.mfspr r20, r0, SPR_EEAR_BASE |
_dtlb_handler: |
l.sw -4(r1),r4 |
l.sw -8(r1),r5 |
l.sw -12(r1),r6 |
l.sw -16(r1),r7 |
l.sw -20(r1),r8 |
l.mfspr r2, r0, SPR_EEAR_BASE |
/* Find the entry/set for this address */ |
l.srli r21, r20, 13 /* r21 = VPN, shift by size 8192 = 2**13 */ |
l.andi r22, r21, 0x3f /* 64 entries = 6 bit mask, r22 = set number */ |
l.srli r13, r2, 13 /* r13 = VPN, shift by size 8192 = 2**13 */ |
l.andi r4, r13, 0x3f /* 64 entries = 6 bit mask, r4 = set number */ |
/* If page is in the 0xc0000000 space we map to 16MB part of |
memory, ie 0x0 => 0x01000000, otherwise 1-1 mapping */ |
l.movhi r23, hi(0xc0000000) |
l.ori r23, r23, lo(0xc0000000) |
l.srli r23, r23, 13 /* Get page address, shift by page size, 13 bits */ |
l.movhi r24, hi(0xff << 11) /* Mask for top byte of VPN */ |
l.ori r24, r24, lo(0xff << 11) |
l.and r24, r24, r21 /* Mask in only top byte of VPN */ |
l.sfeq r23, r24 /* Decide if it's in our special mapped region or not*/ |
l.movhi r5, hi(0xc0000000) |
l.ori r5, r5, lo(0xc0000000) |
l.srli r5, r5, 13 /* Get page address, shift by page size, 13 bits */ |
l.movhi r6, hi(0xff << 11) /* Mask for top byte of VPN */ |
l.ori r6, r6, lo(0xff << 11) |
l.and r6, r6, r13 /* Mask in only top byte of VPN */ |
l.sfeq r5, r6 /* Decide if it's in our special mapped region or not*/ |
|
/* First, Setup value for DTLBM (match) reg, is same for both cases */ |
l.movhi r24, hi(SPR_ITLBMR_VPN) /* VPN mask into r24 */ |
l.ori r24, r24, lo(SPR_ITLBMR_VPN) |
l.and r25, r20, r24 /* AND address with VPN mask */ |
l.ori r25, r25, SPR_DTLBMR_V /* OR in valid bit */ |
l.mtspr r22, r25, SPR_DTLBMR_BASE(0) /* Write to DTLBR register */ |
l.movhi r6, hi(SPR_ITLBMR_VPN) /* VPN mask into r6 */ |
l.ori r6, r6, lo(SPR_ITLBMR_VPN) |
l.and r7, r2, r6 /* AND address with VPN mask */ |
l.ori r7, r7, SPR_DTLBMR_V /* OR in valid bit */ |
l.mtspr r4, r7, SPR_DTLBMR_BASE(0) /* Write to DTLBR register */ |
|
l.bf _highmem_map |
l.nop |
166,31 → 171,35
_lomem_map: |
/* Do 1:1 mapping for this request */ |
/* Setup value for translate register */ |
l.movhi r24, hi(SPR_ITLBTR_PPN) /* PPN mask into r24 */ |
l.ori r24, r24, lo(SPR_ITLBTR_PPN) |
l.and r25, r20, r24 /* AND address with PPN mask */ |
l.ori r25, r25, DTLB_PR_NOLIMIT /* Set all execute enables, no lims. */ |
l.mtspr r22, r25, SPR_DTLBTR_BASE(0) /* Write to DTLTR register */ |
l.movhi r6, hi(SPR_ITLBTR_PPN) /* PPN mask into r6 */ |
l.ori r6, r6, lo(SPR_ITLBTR_PPN) |
l.and r7, r2, r6 /* AND address with PPN mask */ |
l.ori r7, r7, DTLB_PR_NOLIMIT /* Set all execute enables, no lims. */ |
l.mtspr r4, r7, SPR_DTLBTR_BASE(0) /* Write to DTLTR register */ |
l.j _dtlb_done |
l.addi r18, r18, 1 /* Incremement low-mapping counter */ |
l.addi r14, r14, 1 /* Incremement low-mapping counter */ |
|
_highmem_map: |
/* Do top byte, 0xc0->0x01, mapping for this request */ |
/* Setup value for translate register */ |
l.movhi r24, hi(SPR_ITLBTR_PPN) /* PPN mask into r24 */ |
l.ori r24, r24, lo(SPR_ITLBTR_PPN) |
l.and r25, r20, r24 /* AND address with PPN mask */ |
l.movhi r26, hi(0xff000000) /* Top byte address mask */ |
l.or r25, r26, r25 /* Set top byte to 0xff */ |
l.xor r25, r26, r25 /* Now clear top byte with XOR */ |
l.movhi r26, hi(0x01000000) /* Top address byte */ |
l.or r25, r26, r25 /* Set top address byte */ |
l.ori r25, r25, DTLB_PR_NOLIMIT /* Set all execute enables, no lims. */ |
l.mtspr r22, r25, SPR_DTLBTR_BASE(0) /* Write to DTLTR register */ |
l.addi r19, r19, 1 /* Incremement low-mapping counter */ |
l.movhi r6, hi(SPR_ITLBTR_PPN) /* PPN mask into r6 */ |
l.ori r6, r6, lo(SPR_ITLBTR_PPN) |
l.and r7, r2, r6 /* AND address with PPN mask */ |
l.movhi r8, hi(0xff000000) /* Top byte address mask */ |
l.or r7, r8, r7 /* Set top byte to 0xff */ |
l.xor r7, r8, r7 /* Now clear top byte with XOR */ |
l.movhi r8, hi(0x01000000) /* Top address byte */ |
l.or r7, r8, r7 /* Set top address byte */ |
l.ori r7, r7, DTLB_PR_NOLIMIT /* Set all execute enables, no lims. */ |
l.mtspr r4, r7, SPR_DTLBTR_BASE(0) /* Write to DTLTR register */ |
l.addi r15, r15, 1 /* Incremement low-mapping counter */ |
|
_dtlb_done: |
|
l.lwz r4,-4(r1) |
l.lwz r5,-8(r1) |
l.lwz r6,-12(r1) |
l.lwz r7,-16(r1) |
l.lwz r8,-20(r1) |
l.rfe |
|
|
202,110 → 211,8
|
.global _start |
_start: |
|
/* Instruction cache enable */ |
/* Check if IC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_ICP |
l.sfeq r26,r0 |
l.bf .L8 |
l.jal _cache_init |
l.nop |
|
/* Disable IC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_ICE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
|
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_ICCFGR |
l.andi r26,r24,SPR_ICCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
|
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_ICCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
|
/* Invalidate IC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
|
.L7: |
l.mtspr r0,r6,SPR_ICBIR |
l.sfne r6,r5 |
l.bf .L7 |
l.add r6,r6,r14 |
|
/* Enable IC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_ICE |
l.mtspr r0,r6,SPR_SR |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
|
.L8: |
/* Data cache enable */ |
/* Check if DC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_DCP |
l.sfeq r26,r0 |
l.bf .L10 |
l.nop |
/* Disable DC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_DCE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_DCCFGR |
l.andi r26,r24,SPR_DCCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_DCCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
/* Invalidate DC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
.L9: |
l.mtspr r0,r6,SPR_DCBIR |
l.sfne r6,r5 |
l.bf .L9 |
l.add r6,r6,r14 |
/* Enable DC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_DCE |
l.mtspr r0,r6,SPR_SR |
.L10: |
// Kick off test |
l.jal _main |
l.nop |
323,8 → 230,8
l.addi r11,r0,0 /* exception counter 1 */ |
l.addi r12,r0,0 /* exception counter 2 */ |
l.addi r13,r0,0 |
l.addi r18,r0,0 /* DMMU exception counter for low mem mapping */ |
l.addi r19,r0,0 /* DMMU exception counter for hi mem mapping */ |
l.addi r14,r0,0 /* DMMU exception counter for low mem mapping */ |
l.addi r15,r0,0 /* DMMU exception counter for hi mem mapping */ |
l.sw 0x0(r0),r0 /* Initialize RAM */ |
l.sw 0x4(r0),r0 /* Initialize RAM */ |
l.sw 0x8(r0),r0 /* Initialize RAM */ |
553,7 → 460,7
l.nop |
l.movhi r12, 0 /* Reset exception counters */ |
l.movhi r11, 0 |
l.ori r30, r0, 0xd /* put 0xd in r30, indicate it's databus test */ |
l.ori r2, r0, 0xd /* put 0xd in r2, indicate it's databus test */ |
/* Cause access error */ |
/* Load word */ |
l.movhi r5, 0xee00 /* Address to cause an error */ |
636,7 → 543,7
/* TODO: do this it with cache enabled/disabled */ |
l.movhi r12, 0 /* Reset exception counters */ |
l.movhi r11, 0 |
l.movhi r30, 0x0 /* put 0x0 in r30,indicate it's instruction bus test*/ |
l.movhi r2, 0x0 /* put 0x0 in r2,indicate it's instruction bus test*/ |
/* Cause access error */ |
l.movhi r5, 0xee00 /* Address to cause an error */ |
l.jalr r5 /* Jump and link to bad address */ |
673,10 → 580,10
l.movhi r7, hi(0xaabbccdd) |
l.ori r7, r7, lo(0xaabbccdd) |
l.sw 0(r5), r7 /* Shouldn't trigger MMU */ |
l.sfne r18, r0 |
l.sfne r14, r0 |
l.bf _dmmu_test_error |
l.nop |
l.sfne r19, r0 |
l.sfne r15, r0 |
l.bf _dmmu_test_error |
l.nop |
|
692,10 → 599,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0x1 /* Check for lo mem mapping */ |
l.sfnei r14, 0x1 /* Check for lo mem mapping */ |
l.bf _dmmu_test_error |
l.nop |
l.sfne r19, r0 /* hi-mem counter should still be 0 */ |
l.sfne r15, r0 /* hi-mem counter should still be 0 */ |
l.bf _dmmu_test_error |
l.nop |
|
706,10 → 613,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0x1 /* Check for lo mem mapping */ |
l.sfnei r14, 0x1 /* Check for lo mem mapping */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0x1 /* hi-mem counter should still be 0 */ |
l.sfnei r15, 0x1 /* hi-mem counter should still be 0 */ |
l.bf _dmmu_test_error |
l.nop |
|
719,10 → 626,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0x2 /* Check for lo mem mapping increment */ |
l.sfnei r14, 0x2 /* Check for lo mem mapping increment */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0x1 /* hi-mem counter should still be 1 */ |
l.sfnei r15, 0x1 /* hi-mem counter should still be 1 */ |
l.bf _dmmu_test_error |
l.nop |
|
729,10 → 636,10
l.addi r7, r7, 0x1111 /* Incremement value we're writing */ |
|
l.sw 4(r6), r7 /* Should cause DMMU miss, himem */ |
l.sfnei r18, 0x2 /* Check for lo mem mapping */ |
l.sfnei r14, 0x2 /* Check for lo mem mapping */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0x2 /* hi-mem counter should be 2 */ |
l.sfnei r15, 0x2 /* hi-mem counter should be 2 */ |
l.bf _dmmu_test_error |
l.nop |
|
741,10 → 648,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0x3 /* Check for lo mem mapping increment */ |
l.sfnei r14, 0x3 /* Check for lo mem mapping increment */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0x2 /* hi-mem counter should still be 2 */ |
l.sfnei r15, 0x2 /* hi-mem counter should still be 2 */ |
l.bf _dmmu_test_error |
l.nop |
|
777,10 → 684,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0xb /* Check for lo mem mapping increment to 11 */ |
l.sfnei r14, 0xb /* Check for lo mem mapping increment to 11 */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0xa /* hi-mem counter should be 10 */ |
l.sfnei r15, 0xa /* hi-mem counter should be 10 */ |
l.bf _dmmu_test_error |
l.nop |
|
/trunk/orpsocv2/sw/Makefile.inc
29,8 → 29,6
#### #### |
###################################################################### |
|
DESIGN_NAME ?=orpsoc |
|
OR32_TOOL_PREFIX=or32-elf- |
|
OR32_LD=$(OR32_TOOL_PREFIX)ld |
46,11 → 44,17
# Special case for CPU drivers |
CPU_DRIVER ?=$(SW_ROOT)/drivers/or1200 |
|
# If BOARD_PATH is set, we'll first scan that path for which drivers they have |
DESIGN_NAME ?=orpsoc |
|
# If BOARD is set, we'll first scan that path for which drivers they have |
# and will override any locally named driver directories here. |
ifdef BOARD |
BOARD_PATH=$(SW_ROOT)/../boards/$(BOARD) |
#$(info BOARD is being used: $(BOARD_PATH)) |
|
ifeq ($(V), 1) |
$(info BOARD is set to : $(BOARD_PATH)) |
endif |
|
BOARD_SPECIFIC_DRIVERS=$(shell if [ -e \ |
$(BOARD_PATH)/sw/drivers ]; then \ |
ls $(BOARD_PATH)/sw/drivers; \ |
58,6 → 62,12
BOARD_SW_TESTS=$(shell if [ -e $(BOARD_PATH)/sw/tests ]; then\ |
ls $(BOARD_PATH)/sw/tests; \ |
fi) |
|
# Set RTL_VERILOG_INCLUDE_DIR |
RTL_VERILOG_INCLUDE_DIR=$(BOARD_PATH)/rtl/verilog/include |
#We don't actually want this |
#DESIGN_NAME ?=$(strip $(shell echo $(BOARD)| cut -d '/' -f 2)) |
|
endif |
|
COMMON_SW_DRIVERS=$(shell ls $(SW_ROOT)/drivers ) |
199,10 → 209,10
%.elf: %.S $(ELF_DEPENDS) $(SUPPORT_LIBS) |
$(Q)$(OR32_CC) $< $(ELF_DEPENDS) $(OR32_CFLAGS) $(OR32_LDFLAGS) -o $@ |
|
%.o: %.S |
%.o: %.S processed-verilog-headers |
$(Q)$(OR32_CC) $(OR32_CFLAGS) -c $< -o $@ |
|
%.o: %.c |
%.o: %.c processed-verilog-headers |
$(Q)$(OR32_CC) $(OR32_CFLAGS) -c $< -o $@ |
|
COMPILE_SRCS_BASENAMES=$(basename $(COMPILE_SRCS)) |
213,11 → 223,11
|
# Rule to make all necessary driver objects |
|
$(ORPSOC_LIB): $(PROCESSED_DEFINES) |
$(ORPSOC_LIB): |
$(Q)echo; echo "\t### Building software support library ###"; echo |
$(Q)$(MAKE) -C $(SW_ROOT)/lib liborpsoc.a |
|
$(VECTORS_OBJ): |
$(VECTORS_OBJ): |
$(Q)$(MAKE) -C $(CPU_DRIVER) crt0.o |
|
|
/trunk/orpsocv2/sw/drivers/ethmac/include/ethmac.h
64,7 → 64,11
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 */ |
uint hash_addr1; /* Hash Register 1 */ |
uint txctrl; /* Transmit control frame Register */ |
uint rxctrl; /* Rx control frame Register */ |
uint wbdbg; /* Wishbone state machine debug information */ |
|
} oeth_regs; |
|
/* Ethernet buffer descriptor */ |
/trunk/orpsocv2/sw/drivers/or1200/cache.S
0,0 → 1,114
#include "spr-defs.h" |
/* Cache init. To be called during init ONLY */ |
|
.global _cache_init |
.type _cache_init,@function |
|
_cache_init: |
/* Instruction cache enable */ |
/* Check if IC present and skip enabling otherwise */ |
l.mfspr r3,r0,SPR_UPR |
l.andi r4,r3,SPR_UPR_ICP |
l.sfeq r4,r0 |
l.bf .L8 |
l.nop |
|
/* Disable IC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_ICE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
|
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r3,r0,SPR_ICCFGR |
l.andi r4,r3,SPR_ICCFGR_CBS |
l.srli r5,r4,7 |
l.ori r6,r0,16 |
l.sll r14,r6,r5 |
|
/* Establish number of cache sets |
r7 contains number of cache sets |
r5 contains log(# of cache sets) |
*/ |
l.andi r4,r3,SPR_ICCFGR_NCS |
l.srli r5,r4,3 |
l.ori r6,r0,1 |
l.sll r7,r6,r5 |
|
/* Invalidate IC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r5 |
|
.L7: |
l.mtspr r0,r6,SPR_ICBIR |
l.sfne r6,r5 |
l.bf .L7 |
l.add r6,r6,r14 |
|
/* Enable IC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_ICE |
l.mtspr r0,r6,SPR_SR |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
|
.L8: |
/* Data cache enable */ |
/* Check if DC present and skip enabling otherwise */ |
l.mfspr r3,r0,SPR_UPR |
l.andi r4,r3,SPR_UPR_DCP |
l.sfeq r4,r0 |
l.bf .L10 |
l.nop |
/* Disable DC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_DCE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r3,r0,SPR_DCCFGR |
l.andi r4,r3,SPR_DCCFGR_CBS |
l.srli r5,r4,7 |
l.ori r6,r0,16 |
l.sll r14,r6,r5 |
/* Establish number of cache sets |
r7 contains number of cache sets |
r5 contains log(# of cache sets) |
*/ |
l.andi r4,r3,SPR_DCCFGR_NCS |
l.srli r5,r4,3 |
l.ori r6,r0,1 |
l.sll r7,r6,r5 |
/* Invalidate DC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r5 |
.L9: |
l.mtspr r0,r6,SPR_DCBIR |
l.sfne r6,r5 |
l.bf .L9 |
l.add r6,r6,r14 |
/* Enable DC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_DCE |
l.mtspr r0,r6,SPR_SR |
|
.L10: |
/* Return */ |
l.jr r9 |
l.nop |
/trunk/orpsocv2/sw/drivers/or1200/crt0.S
65,6 → 65,7
l.movhi r29, 0 |
l.movhi r30, 0 |
l.movhi r31, 0 |
|
/* Clear status register, set supervisor mode */ |
l.ori r1, r0, SPR_SR_SM |
l.mtspr r0, r1, SPR_SR |
196,125 → 197,18
|
ENTRY(_start) |
|
|
|
/* Instruction cache enable */ |
/* Check if IC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_ICP |
l.sfeq r26,r0 |
l.bf .L8 |
/* Cache initialisation */ |
l.jal _cache_init |
l.nop |
|
/* Disable IC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_ICE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
|
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_ICCFGR |
l.andi r26,r24,SPR_ICCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
|
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_ICCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
|
/* Invalidate IC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
|
.L7: |
l.mtspr r0,r6,SPR_ICBIR |
l.sfne r6,r5 |
l.bf .L7 |
l.add r6,r6,r14 |
|
/* Enable IC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_ICE |
l.mtspr r0,r6,SPR_SR |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
|
.L8: |
/* Data cache enable */ |
/* Check if DC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_DCP |
l.sfeq r26,r0 |
l.bf .L10 |
l.nop |
/* Disable DC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_DCE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_DCCFGR |
l.andi r26,r24,SPR_DCCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_DCCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
/* Invalidate DC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
.L9: |
l.mtspr r0,r6,SPR_DCBIR |
l.sfne r6,r5 |
l.bf .L9 |
l.add r6,r6,r14 |
/* Enable DC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_DCE |
l.mtspr r0,r6,SPR_SR |
|
.L10: |
|
/* Clear BSS */ |
LOAD_SYMBOL_2_GPR(r28, _bss_start) |
LOAD_SYMBOL_2_GPR(r30, _bss_end) |
LOAD_SYMBOL_2_GPR(r5, _bss_start) |
LOAD_SYMBOL_2_GPR(r6, _bss_end) |
1: |
l.sw (0)(r28), r0 |
l.sfltu r28, r30 |
l.sw (0)(r5), r0 |
l.sfltu r5, r6 |
l.bf 1b |
l.addi r28, r28, 4 |
|
/* Initialise UART in a C function */ |
/*l.jal _uart_init |
l.nop*/ |
l.addi r5, r5, 4 |
|
/* Jump to main program entry point (argc = argv = 0) */ |
CLEAR_GPR(r3) |
360,7 → 254,7
l.sw 0x70(r1), r30 |
l.sw 0x74(r1), r31 |
l.sw 0x78(r1), r32 |
|
|
l.jal default_exception_handler_c |
l.nop |
|
/trunk/orpsocv2/sw/drivers/or1200/int.c
25,37 → 25,37
} |
|
/* Add interrupt handler */ |
int int_add(unsigned long vect, void (* handler)(void *), void *arg) |
int int_add(unsigned long irq, void (* handler)(void *), void *arg) |
{ |
if(vect >= MAX_INT_HANDLERS) |
if(irq >= MAX_INT_HANDLERS) |
return -1; |
|
int_handlers[vect].handler = handler; |
int_handlers[vect].arg = arg; |
int_handlers[irq].handler = handler; |
int_handlers[irq].arg = arg; |
|
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << vect)); |
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << irq)); |
|
return 0; |
} |
|
/* Disable interrupt */ |
int int_disable(unsigned long vect) |
int int_disable(unsigned long irq) |
{ |
if(vect >= MAX_INT_HANDLERS) |
if(irq >= MAX_INT_HANDLERS) |
return -1; |
|
mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(0x00000001L << vect)); |
mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(0x00000001L << irq)); |
|
return 0; |
} |
|
/* Enable interrupt */ |
int int_enable(unsigned long vect) |
int int_enable(unsigned long irq) |
{ |
if(vect >= MAX_INT_HANDLERS) |
if(irq >= MAX_INT_HANDLERS) |
return -1; |
|
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << vect)); |
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << irq)); |
|
return 0; |
} |
71,7 → 71,12
while(i < 32) { |
if((picsr & (0x01L << i)) && (int_handlers[i].handler != 0)) { |
(*int_handlers[i].handler)(int_handlers[i].arg); |
mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(0x00000001L << i)); |
#ifdef OR1200_INT_CHECK_BIT_CLEARED |
// Ensure PICSR bit is cleared, incase it takes some time for the |
// IRQ line going low to propagate back to PIC |
while (mfspr(SPR_PICSR) & (0x00000001L << i)) |
#endif |
mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(0x00000001L << i)); |
} |
i++; |
} |
/trunk/orpsocv2/sw/drivers/or1200/link.ld
72,14 → 72,10
/* ensure there is enough room for stack */ |
.stack (NOLOAD): { |
. = ALIGN(4); |
sstack = . ; |
_sstack = . ; |
. = . + _min_stack ; |
. = . + _min_stack ; |
. = ALIGN(4); |
stack = . ; |
_stack = . ; |
estack = . ; |
_estack = . ; |
} > ram |
|
.stab 0 (NOLOAD) : |
/trunk/orpsocv2/sw/drivers/or1200/Makefile
1,7 → 1,7
SW_ROOT=../.. |
|
# Sources to go into the liborpsoc.a support library |
COMPILE_SRCS=exceptions.c int.c or1200-mmu.S or1200-utils.c |
COMPILE_SRCS=exceptions.c int.c or1200-mmu.S or1200-utils.c cache.S |
|
include $(SW_ROOT)/Makefile.inc |
|
/trunk/orpsocv2/boards/actel/ordb1a3pe1500/bench/verilog/include/eth_stim.v
80,6 → 80,7
|
// Do call/response test |
reg eth_stim_do_rx_reponse_to_tx; |
reg eth_stim_do_overflow_test; |
|
|
parameter num_tx_bds = 16; |
151,6 → 152,7
expected_rxbd = num_tx_bds; // init this here |
|
eth_stim_do_rx_reponse_to_tx = 0; |
eth_stim_do_overflow_test = 0; |
|
|
while (eth_stim_waiting) // Loop, waiting for enabling of MAC by software |
179,7 → 181,7
eth_phy0.eth_speed, // Speed |
eth_stim_num_rx_only_IPG, // IPG |
48'h0012_3456_789a, 48'h0708_090A_0B0C, 1, |
0, 0); |
0, 0, 0); |
|
eth_stim_waiting = 0; |
end |
201,6 → 203,11
// kickoff call/response here |
eth_stim_do_rx_reponse_to_tx = 1; |
end |
1: |
begin |
// kickoff overflow test here |
eth_stim_do_overflow_test = 1; |
end |
default: |
begin |
do_rx_while_tx_stim(1400); |
229,7 → 236,7
send_packet_loop(num_packets, start_packet_size, 2'b01, 1, |
speed_loop[0], 10000, |
48'h0012_3456_789a, 48'h0708_090A_0B0C, 1, |
inject_errors, inject_errors_mod); |
inject_errors, inject_errors_mod, 0); |
|
end |
|
290,7 → 297,7
$display("do_rx_while_tx packet_size = %0d", packet_size); |
send_packet_loop(1, packet_size, 2'b01, 1, eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0); |
48'h0708_090A_0B0C, 1, 1'b0, 0, 0); |
|
// If RX enable went low, wait for it go high again |
if (ethmac_rxen===1'b0) |
324,6 → 331,14
// Continue if we are enabled |
do_rx_response_to_tx(); |
end |
|
// If in call-response mode, whenever we receive a TX packet, we generate |
// one and send it back |
always @(posedge eth_stim_do_overflow_test) |
begin |
// Continue if we are enabled |
do_overflow_stimulus(); |
end |
|
// Generate RX packet in rsponse to TX packet |
task do_rx_response_to_tx; |
360,7 → 375,7
$display("do_rx_response_to_tx packet_size = %0d", packet_size); |
send_packet_loop(1, packet_size, 2'b01, 1, eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0); |
48'h0708_090A_0B0C, 1, 1'b0, 0, 0); |
|
// If RX enable went low, wait for it go high again |
if (ethmac_rxen===1'b0) |
380,11 → 395,118
|
end |
endtask // do_rx_response_to_tx |
|
|
|
// Generate RX packet in rsponse to TX packet |
task do_overflow_stimulus; |
//input unused; |
reg [31:0] IPG; // Inter-packet gap |
reg [31:0] packet_size; |
|
integer j; |
|
begin |
|
// Maximum packet size |
packet_size = 1500; |
|
// Minimum IPG |
IPG = eth_stim_IPG_min_100mb; |
|
$display("do_overflow_stimulus IPG = %0d", IPG); |
|
|
$display("do_overflow_stimulus packetsize = %0d", packet_size); |
|
send_packet_loop(num_rx_bds, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 0); |
|
// This one should cause overflow, don't check it gets there OK |
send_packet_loop(1, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 1); |
|
// Wind back expected RXBD number |
if (expected_rxbd == num_tx_bds) |
expected_rxbd = num_tx_bds + num_rx_bds - 1; |
else |
expected_rxbd = expected_rxbd - 1; |
|
// This one should cause overflow, don't check it gets there OK |
send_packet_loop(1, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 1); |
|
// Wind back expected RXBD number |
if (expected_rxbd == num_tx_bds) |
expected_rxbd = num_tx_bds + num_rx_bds - 1; |
else |
expected_rxbd = expected_rxbd - 1; |
|
|
// This one should cause overflow, don't check it gets there OK |
send_packet_loop(1, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 1); |
|
// Wind back expected RXBD number |
if (expected_rxbd == num_tx_bds) |
expected_rxbd = num_tx_bds + num_rx_bds - 1; |
else |
expected_rxbd = expected_rxbd - 1; |
|
|
// This one should cause overflow, don't check it gets there OK |
send_packet_loop(1, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 1); |
|
// Wind back expected RXBD number |
if (expected_rxbd == num_tx_bds) |
expected_rxbd = num_tx_bds + num_rx_bds - 1; |
else |
expected_rxbd = expected_rxbd - 1; |
|
|
// Wait until a buffer descriptor becomes available |
while(`ETH_TOP.wishbone.RxBDRead==1'b1) |
#1000; |
|
$display("%t: RxBDRead gone low",$time); |
#10000; |
|
|
|
send_packet_loop(1, packet_size, 2'b01, 1, eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 0); |
|
|
// If RX enable went low, wait for it go high again |
if (ethmac_rxen===1'b0) |
begin |
|
while (ethmac_rxen===1'b0) |
begin |
@(posedge ethmac_rxen); |
#10000; |
end |
|
// RX disabled and when re-enabled we reset the buffer |
// descriptor number |
expected_rxbd = num_tx_bds; |
|
end |
|
end |
endtask // do_overflow_stimulus |
|
|
|
// |
// always@() to check the TX buffer descriptors |
// |
546,11 → 668,12
end // for (i=0;i<tx_len_bd;i=i+1) |
|
`else // !`ifdef VERSATILE_SDRAM |
|
|
$display("eth_stim.v: CANNOT INSPECT RAM. PLEASE CONFIGURE CORRECTLY"); |
$display("RAM pointer for BD is 0x%h, bank offset we'll use is 0x%h", |
tx_bd_addr, txpnt_wb); |
$finish; |
|
`endif // !`ifdef VERSATILE_SDRAM |
`endif // !`ifdef RAM_WB |
|
574,6 → 697,17
end |
endtask // check_tx_packet |
|
|
// Local buffer of "sent" data to the ethernet MAC, we will check against |
// Size of our local buffer in bytes |
parameter eth_rx_sent_circbuf_size = (16*1024); |
parameter eth_rx_sent_circbuf_size_mask = eth_rx_sent_circbuf_size - 1; |
integer eth_rx_sent_circbuf_fill_ptr = 0; |
integer eth_rx_sent_circbuf_read_ptr = 0; |
// The actual buffer |
reg [7:0] eth_rx_sent_circbuf [0:eth_rx_sent_circbuf_size-1]; |
|
|
// |
// Task to send a set of packets |
// |
588,8 → 722,9
input [47:0] src_mac; |
input random_fill; |
input random_errors; |
input [31:0] random_error_mod; |
integer j; |
input [31:0] random_error_mod; |
input dont_confirm_rx; |
integer j, k; |
reg error_this_time; |
integer error_type; // 0 = rxerr, 1=bad preamble 2=bad crc 3=TODO |
reg [31:0] rx_bd_lenstat; |
663,9 → 798,16
// if RX enable still set (might have gone low during this packet |
if (ethmac_rxen) |
begin |
if (error_this_time) |
if (error_this_time || dont_confirm_rx) begin |
// Put in dummy length, checking function will skip... |
rx_packet_lengths[(eth_rx_num_packets_sent& 12'h3ff)]=32'heeeeeeee; |
|
for(k=0;k<length;k=k+1) |
// skip data in verify buffer |
eth_rx_sent_circbuf_read_ptr = (eth_rx_sent_circbuf_read_ptr+1)& |
eth_rx_sent_circbuf_size_mask; |
|
end |
else |
rx_packet_lengths[(eth_rx_num_packets_sent & 12'h3ff)] = length; |
|
716,15 → 858,6
end // for (j=0;j<num_packets | length <32;j=j+1) |
end |
endtask // send_packet_loop |
|
// Local buffer of "sent" data to the ethernet MAC, we will check against |
// Size of our local buffer in bytes |
parameter eth_rx_sent_circbuf_size = (16*1024); |
parameter eth_rx_sent_circbuf_size_mask = eth_rx_sent_circbuf_size - 1; |
integer eth_rx_sent_circbuf_fill_ptr = 0; |
integer eth_rx_sent_circbuf_read_ptr = 0; |
// The actual buffer |
reg [7:0] eth_rx_sent_circbuf [0:eth_rx_sent_circbuf_size-1]; |
|
/* |
TASKS for set and check RX packets: |
1092,7 → 1225,6
rx_bd_addr, rxpnt_wb); |
$finish; |
|
|
`endif // !`ifdef VERSATILE_SDRAM |
`endif // !`ifdef RAM_WB |
|
/trunk/orpsocv2/boards/actel/ordb1a3pe1500/rtl/verilog/include/or1200_defines.v
364,6 → 364,7
// |
//`define OR1200_IMPL_ALU_COMP1 |
`define OR1200_IMPL_ALU_COMP2 |
//`define OR1200_IMPL_ALU_COMP3 |
|
// |
// Implement Find First/Last '1' |
/trunk/orpsocv2/boards/actel/ordb1a3pe1500/syn/synplify/bin/Makefile
284,7 → 284,7
## |
# Generate a report for each module, and for whole thing |
## |
MODULES ?=arbiter_ibus arbiter_dbus arbiter_bytebus jtag_tap or1200_top dbg_if rom ram_wb uart16550 spacewire_wb_if mp2_top simple_spi i2c_core_wb_if usbslave scet gpio versatile_mem_ctrl urtu_top |
MODULES ?= or1200_top |
MODULES_SRR=$(shell for mod in $(MODULES); do echo $(SYN_WORK_DIR)"/"$(SYN_PROJ_NAME)"/"$$mod".srr"; done) |
|
syn-report: $(MODULES_SRR) |
/trunk/orpsocv2/boards/xilinx/ml501/bench/verilog/include/eth_stim.v
80,7 → 80,7
|
// Do call/response test |
reg eth_stim_do_rx_reponse_to_tx; |
|
reg eth_stim_do_overflow_test; |
|
parameter num_tx_bds = 16; |
parameter num_tx_bds_mask = 4'hf; |
149,8 → 149,8
expected_rxbd = num_tx_bds; // init this here |
|
eth_stim_do_rx_reponse_to_tx = 0; |
eth_stim_do_overflow_test = 0; |
|
|
while (eth_stim_waiting) // Loop, waiting for enabling of MAC by software |
begin |
#100; |
177,7 → 177,7
eth_phy0.eth_speed, // Speed |
eth_stim_num_rx_only_IPG, // IPG |
48'h0012_3456_789a, 48'h0708_090A_0B0C, 1, |
0, 0); |
0, 0, 0); |
|
eth_stim_waiting = 0; |
end |
199,6 → 199,11
// kickoff call/response here |
eth_stim_do_rx_reponse_to_tx = 1; |
end |
1: |
begin |
// kickoff overflow test here |
eth_stim_do_overflow_test = 1; |
end |
default: |
begin |
do_rx_while_tx_stim(1400); |
227,7 → 232,7
send_packet_loop(num_packets, start_packet_size, 2'b01, 1, |
speed_loop[0], 10000, |
48'h0012_3456_789a, 48'h0708_090A_0B0C, 1, |
inject_errors, inject_errors_mod); |
inject_errors, inject_errors_mod, 0); |
|
end |
|
288,7 → 293,7
$display("do_rx_while_tx packet_size = %0d", packet_size); |
send_packet_loop(1, packet_size, 2'b01, 1, eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0); |
48'h0708_090A_0B0C, 1, 1'b0, 0, 0); |
|
// If RX enable went low, wait for it go high again |
if (ethmac_rxen===1'b0) |
322,6 → 327,15
// Continue if we are enabled |
do_rx_response_to_tx(); |
end |
|
|
// If in call-response mode, whenever we receive a TX packet, we generate |
// one and send it back |
always @(posedge eth_stim_do_overflow_test) |
begin |
// Continue if we are enabled |
do_overflow_stimulus(); |
end |
|
// Generate RX packet in rsponse to TX packet |
task do_rx_response_to_tx; |
358,7 → 372,7
$display("do_rx_response_to_tx packet_size = %0d", packet_size); |
send_packet_loop(1, packet_size, 2'b01, 1, eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0); |
48'h0708_090A_0B0C, 1, 1'b0, 0, 0); |
|
// If RX enable went low, wait for it go high again |
if (ethmac_rxen===1'b0) |
379,10 → 393,117
end |
endtask // do_rx_response_to_tx |
|
// Generate RX packet in rsponse to TX packet |
task do_overflow_stimulus; |
//input unused; |
reg [31:0] IPG; // Inter-packet gap |
reg [31:0] packet_size; |
|
integer j; |
|
begin |
|
// Maximum packet size |
packet_size = 1500; |
|
// Minimum IPG |
IPG = eth_stim_IPG_min_100mb; |
|
$display("do_overflow_stimulus IPG = %0d", IPG); |
|
|
$display("do_overflow_stimulus packetsize = %0d", packet_size); |
|
send_packet_loop(num_rx_bds, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 0); |
|
// This one should cause overflow, don't check it gets there OK |
send_packet_loop(1, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 1); |
|
// Wind back expected RXBD number |
if (expected_rxbd == num_tx_bds) |
expected_rxbd = num_tx_bds + num_rx_bds - 1; |
else |
expected_rxbd = expected_rxbd - 1; |
|
// This one should cause overflow, don't check it gets there OK |
send_packet_loop(1, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 1); |
|
// Wind back expected RXBD number |
if (expected_rxbd == num_tx_bds) |
expected_rxbd = num_tx_bds + num_rx_bds - 1; |
else |
expected_rxbd = expected_rxbd - 1; |
|
|
// This one should cause overflow, don't check it gets there OK |
send_packet_loop(1, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 1); |
|
// Wind back expected RXBD number |
if (expected_rxbd == num_tx_bds) |
expected_rxbd = num_tx_bds + num_rx_bds - 1; |
else |
expected_rxbd = expected_rxbd - 1; |
|
|
// This one should cause overflow, don't check it gets there OK |
send_packet_loop(1, packet_size, 2'b01, 1, |
eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 1); |
|
// Wind back expected RXBD number |
if (expected_rxbd == num_tx_bds) |
expected_rxbd = num_tx_bds + num_rx_bds - 1; |
else |
expected_rxbd = expected_rxbd - 1; |
|
|
// Wait until a buffer descriptor becomes available |
while(`ETH_TOP.wishbone.RxBDRead==1'b1) |
#1000; |
|
$display("%t: RxBDRead gone low",$time); |
#10000; |
|
|
|
send_packet_loop(1, packet_size, 2'b01, 1, eth_phy0.eth_speed, |
IPG, 48'h0012_3456_789a, |
48'h0708_090A_0B0C, 1, 1'b0, 0, 0); |
|
|
// If RX enable went low, wait for it go high again |
if (ethmac_rxen===1'b0) |
begin |
|
while (ethmac_rxen===1'b0) |
begin |
@(posedge ethmac_rxen); |
#10000; |
end |
|
// RX disabled and when re-enabled we reset the buffer |
// descriptor number |
expected_rxbd = num_tx_bds; |
|
end |
|
end |
endtask // do_overflow_stimulus |
|
|
|
// |
// always@() to check the TX buffer descriptors |
// |
653,7 → 774,7
//$display("Checking address in tx bd 0x%0h",txpnt_sdram); |
sdram_byte = 8'hx; |
`ifdef RAM_WB |
sdram_byte = dut.ram_wb0.ram_wb_b3_0.get_byte(txpnt_sdram); |
sdram_byte = dut.ram_wb0.ram_wb_b3_0.get_mem8(txpnt_sdram); |
`else |
`ifdef VERSATILE_SDRAM |
sdram0.get_byte(txpnt_sdram,sdram_byte); |
707,6 → 828,17
end |
endtask // check_tx_packet |
|
|
// Local buffer of "sent" data to the ethernet MAC, we will check against |
// Size of our local buffer in bytes |
parameter eth_rx_sent_circbuf_size = (16*1024); |
parameter eth_rx_sent_circbuf_size_mask = eth_rx_sent_circbuf_size - 1; |
integer eth_rx_sent_circbuf_fill_ptr = 0; |
integer eth_rx_sent_circbuf_read_ptr = 0; |
// The actual buffer |
reg [7:0] eth_rx_sent_circbuf [0:eth_rx_sent_circbuf_size-1]; |
|
|
// |
// Task to send a set of packets |
// |
721,8 → 853,9
input [47:0] src_mac; |
input random_fill; |
input random_errors; |
input [31:0] random_error_mod; |
integer j; |
input [31:0] random_error_mod; |
input dont_confirm_rx; |
integer j, k; |
reg error_this_time; |
integer error_type; // 0 = rxerr, 1=bad preamble 2=bad crc 3=TODO |
reg [31:0] rx_bd_lenstat; |
796,9 → 929,16
// if RX enable still set (might have gone low during this packet |
if (ethmac_rxen) |
begin |
if (error_this_time) |
if (error_this_time || dont_confirm_rx) begin |
// Put in dummy length, checking function will skip... |
rx_packet_lengths[(eth_rx_num_packets_sent& 12'h3ff)]=32'heeeeeeee; |
|
for(k=0;k<length;k=k+1) |
// skip data in verify buffer |
eth_rx_sent_circbuf_read_ptr = (eth_rx_sent_circbuf_read_ptr+1)& |
eth_rx_sent_circbuf_size_mask; |
|
end |
else |
rx_packet_lengths[(eth_rx_num_packets_sent & 12'h3ff)] = length; |
|
849,15 → 989,6
end // for (j=0;j<num_packets | length <32;j=j+1) |
end |
endtask // send_packet_loop |
|
// Local buffer of "sent" data to the ethernet MAC, we will check against |
// Size of our local buffer in bytes |
parameter eth_rx_sent_circbuf_size = (16*1024); |
parameter eth_rx_sent_circbuf_size_mask = eth_rx_sent_circbuf_size - 1; |
integer eth_rx_sent_circbuf_fill_ptr = 0; |
integer eth_rx_sent_circbuf_read_ptr = 0; |
// The actual buffer |
reg [7:0] eth_rx_sent_circbuf [0:eth_rx_sent_circbuf_size-1]; |
|
/* |
TASKS for set and check RX packets: |
1176,13 → 1307,18
begin |
|
sdram_byte = 8'hx; |
`ifdef XILINX_DDR2 |
|
`ifdef RAM_WB |
sdram_byte = dut.ram_wb0.ram_wb_b3_0.get_mem8(rxpnt_sdram); |
`else |
`ifdef XILINX_DDR2 |
get_byte_from_xilinx_ddr2(rxpnt_sdram, sdram_byte); |
`else |
`else |
$display(" * Error:"); |
|
$display(" * eth_stim needs to be able to access the main memory to check packet rx/tx"); |
$finish; |
`endif |
`endif |
|
phy_byte = eth_rx_sent_circbuf[eth_rx_sent_circbuf_read_ptr]; |
/trunk/orpsocv2/boards/xilinx/ml501/rtl/verilog/include/ethmac_defines.v
46,24 → 46,11
|
// Generic FIFO implementation - hopefully synthesizable with Synplify |
//`define ETH_FIFO_GENERIC |
// Ethernet implemented in Xilinx Chips (uncomment following lines) |
`define ETH_FIFO_XILINX // Use Xilinx distributed ram for tx and rx fifo |
// `define ETH_XILINX_RAMB4 // Selection of the used memory for Buffer descriptors |
// Core is going to be implemented in Virtex FPGA and contains Virtex |
// specific elements. |
// specific elements. |
`define ETH_FIFO_XILINX |
//`define ETH_FIFO_RAMB18 |
|
// Ethernet implemented in Altera Chips (uncomment following lines) |
//`define ETH_ALTERA_ALTSYNCRAM |
|
// Ethernet implemented in ASIC with Virtual Silicon RAMs |
// `define ETH_VIRTUAL_SILICON_RAM // Virtual Silicon RAMS used storing buffer decriptors (ASIC implementation) |
|
// Ethernet implemented in ASIC with Artisan RAMs |
// `define ETH_ARTISAN_RAM // Artisan RAMS used storing buffer decriptors (ASIC implementation) |
|
// Uncomment when Avalon bus is used |
//`define ETH_AVALON_BUS |
|
`define ETH_MODER_ADR 8'h0 // 0x0 |
`define ETH_INT_SOURCE_ADR 8'h1 // 0x4 |
`define ETH_INT_MASK_ADR 8'h2 // 0x8 |
185,48 → 172,49
`define ETH_TX_FIFO_DATA_WIDTH 32 |
|
// Defines for ethernet TX fifo size - impacts FPGA resource usage |
//`define ETH_TX_FULL_PACKET_FIFO // Full 1500 byte TX buffer - uncomment this |
|
//`define ETH_TX_64BYTE_FIFO // 64 byte TX buffer - uncomment this |
//`define ETH_TX_128BYTE_FIFO // 128 byte TX buffer - uncomment this |
`define ETH_TX_256BYTE_FIFO // 256 byte TX buffer - uncomment this |
//`define ETH_TX_512BYTE_FIFO // 512 byte TX buffer - uncomment this |
//`define ETH_TX_1KBYTE_FIFO // 1024 byte TX buffer - uncomment this |
//`define ETH_TX_FULL_PACKET_FIFO // Full 1500 byte TX buffer - uncomment this |
|
`ifdef ETH_TX_FULL_PACKET_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 9 |
`define ETH_TX_FIFO_DEPTH 375 |
`else |
`ifdef ETH_TX_1KBYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 8 |
`define ETH_TX_FIFO_DEPTH 256 |
`else |
`ifdef ETH_TX_512BYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 7 |
`define ETH_TX_FIFO_DEPTH 128 |
`else |
`ifdef ETH_TX_256BYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 6 |
`define ETH_TX_FIFO_DEPTH 64 |
`else |
`ifdef ETH_TX_128BYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 5 |
`define ETH_TX_FIFO_DEPTH 32 |
`else |
// Default is 64 bytes |
`define ETH_TX_FIFO_CNT_WIDTH 4 |
`define ETH_TX_FIFO_DEPTH 16 |
`endif |
`endif |
`endif |
`endif // !`ifdef ETH_TX_512BYTE_FIFO |
`endif // !`ifdef ETH_TX_FULL_PACKET_FIFO |
`endif |
`ifdef ETH_TX_1KBYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 8 |
`define ETH_TX_FIFO_DEPTH 256 |
`endif |
`ifdef ETH_TX_512BYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 7 |
`define ETH_TX_FIFO_DEPTH 128 |
`endif |
`ifdef ETH_TX_256BYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 6 |
`define ETH_TX_FIFO_DEPTH 64 |
`endif |
`ifdef ETH_TX_128BYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 5 |
`define ETH_TX_FIFO_DEPTH 32 |
`endif |
`ifdef ETH_TX_128BYTE_FIFO |
`define ETH_TX_FIFO_CNT_WIDTH 4 |
`define ETH_TX_FIFO_DEPTH 16 |
`endif |
|
|
|
|
// Settings for RX FIFO |
//`define ETH_RX_FIFO_CNT_WIDTH 8 |
//`define ETH_RX_FIFO_DEPTH 256 |
//`define ETH_RX_FIFO_CNT_WIDTH 7 |
//`define ETH_RX_FIFO_DEPTH 128 |
`define ETH_RX_FIFO_DEPTH 128 |
`define ETH_RX_FIFO_CNT_WIDTH 6 |
`define ETH_RX_FIFO_DEPTH 64 |
//`define ETH_RX_FIFO_DEPTH 64 |
//`define ETH_RX_FIFO_CNT_WIDTH 5 |
//`define ETH_RX_FIFO_DEPTH 32 |
//`define ETH_RX_FIFO_CNT_WIDTH 4 |
/trunk/orpsocv2/boards/xilinx/ml501/rtl/verilog/include/orpsoc-defines.v
74,7 → 74,11
// Watchdog timeout: 2^(ARBITER_IBUS_WATCHDOG_TIMER_WIDTH+1) cycles |
// This has to be kind of long, as DDR2 initialisation can take a little while |
// and after reset, and if this is too short we'll always get bus error. |
`define ARBITER_IBUS_WATCHDOG_TIMER_WIDTH 20 |
`ifdef XILINX_DDR2 |
`define ARBITER_IBUS_WATCHDOG_TIMER_WIDTH 20 |
`else |
`define ARBITER_IBUS_WATCHDOG_TIMER_WIDTH 6 |
`endif |
|
// Data bus arbiter |
|
81,7 → 85,11
//`define ARBITER_DBUS_REGISTERING |
`define ARBITER_DBUS_WATCHDOG |
// Watchdog timeout: 2^(ARBITER_DBUS_WATCHDOG_TIMER_WIDTH+1) cycles |
`define ARBITER_DBUS_WATCHDOG_TIMER_WIDTH 20 |
`ifdef XILINX_DDR2 |
`define ARBITER_DBUS_WATCHDOG_TIMER_WIDTH 20 |
`else |
`define ARBITER_DBUS_WATCHDOG_TIMER_WIDTH 6 |
`endif |
|
// Byte bus (peripheral bus) arbiter |
// Don't really need the watchdog here - the databus will pick it up |
/trunk/orpsocv2/boards/xilinx/ml501/rtl/verilog/orpsoc_top/orpsoc_top.v
114,16 → 114,16
`endif |
`ifdef XILINX_SSRAM |
// ZBT SSRAM |
output sram_clk, |
input sram_clk_fb, |
output [21:1] sram_flash_addr, |
inout [31:0] sram_flash_data, |
output sram_cen, |
output sram_flash_oe_n, |
output sram_flash_we_n, |
output [3:0] sram_bw, |
output sram_adv_ld_n, |
output sram_mode, |
output sram_clk; |
input sram_clk_fb; |
output [21:1] sram_flash_addr; |
inout [31:0] sram_flash_data; |
output sram_cen; |
output sram_flash_oe_n; |
output sram_flash_we_n; |
output [3:0] sram_bw; |
output sram_adv_ld_n; |
output sram_mode; |
`endif |
`ifdef UART0 |
input uart0_srx_pad_i; |
/trunk/orpsocv2/boards/xilinx/ml501/backend/par/bin/Makefile
140,7 → 140,7
$(PARRED_NCD): $(MAPPED_NCD) |
@echo; echo "\t#### PAR'ing ####"; |
$(Q)( . $(XILINX_SETTINGS_SCRIPT) && \ |
par -w -pl high -rl high $(XILINX_FLAGS) $< $@ $(PCD_FILE) ) |
par -w -ol high $(XILINX_FLAGS) $< $@ $(PCD_FILE) ) |
|
#This target uses Xilinx tools to generate a bitstream for download |
$(BIT_FILE): $(PARRED_NCD) |
/trunk/orpsocv2/boards/xilinx/ml501/syn/xst/bin/Makefile
250,7 → 250,7
|
# Constraints file |
$(XCF_FILE): |
$(Q)echo; echo "\t#### Generating Xilinx PRJ file ####"; echo |
$(Q)echo; echo "\t#### Generating Xilinx XCF file ####"; echo |
$(Q)echo "# Autogenerated XST .prj file" > $@ |
$(Q)echo "#" >> $@ |
$(Q)echo "# Not much here, XST is smart enough to determine clocks through DCMs" >> $@ |
302,4 → 302,5
distclean: clean-sw clean |
|
|
.PRECIOUS : $(NGC_FILE) $(XST_FILE) $(XCF_FILE) |
.PRECIOUS : $(NGC_FILE) $(XST_FILE) $(XCF_FILE) |
|