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

Subversion Repositories openarty

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openarty/trunk/rtl
    from Rev 27 to Rev 30
    Reverse comparison

Rev 27 → Rev 30

/Makefile
46,10 → 46,10
test: $(VDIRFB)/Vbusmaster__ALL.a
 
CPUDR := cpu
CPUSOURCESnD := zipcpu.v fastops.v pfcache.v pipemem.v \
pfcache.v ifastdec.v wbpriarbiter.v zipbones.v \
CPUSOURCESnD := zipcpu.v cpuops.v pfcache.v pipemem.v \
pfcache.v idecode.v wbpriarbiter.v zipbones.v \
zipsystem.v zipcounter.v zipjiffies.v ziptimer.v \
wbdmac.v icontrol.v wbwatchdog.v
wbdmac.v icontrol.v wbwatchdog.v busdelay.v cpudefs.v
CPUSOURCES := $(addprefix $(CPUDR)/,$(CPUSOURCESnD))
 
JTAGBUS := wbufifo.v wbubus.v wbucompactlines.v \
56,10 → 56,11
wbucompress.v wbudecompress.v wbudeword.v wbuexec.v \
wbuidleint.v wbuinput.v wbuoutput.v wbureadcw.v wbusixchar.v \
wbutohex.v
PERIPHERALS:= enetctrl.v fastio.v rtcdate.v rtcgps.v \
PERIPHERALS:= enetctrl.v enetpackets.v fastio.v rtcdate.v rtcgps.v \
rxuart.v txuart.v eqspiflash.v lleqspi.v flash_config.v \
wbicapetwo.v sdspi.v gpsclock_tb.v gpsclock.v wboled.v lloled.v \
wbscopc.v wbscope.v memdev.v wbddrsdram.v
wbscopc.v wbscope.v memdev.v addepreamble.v addemac.v addecrc.v \
addepad.v rxecrc.v rxepreambl.v rxehwmac.v rxewrite.v
BIGMATH:= bigadd.v bigsmpy.v bigsub.v
SOURCES := fastmaster.v builddate.v \
$(CPUSOURCES) $(JTAGBUS) $(PERIPHERALS) $(BIGMATH)
/addecrc.v
0,0 → 1,104
////////////////////////////////////////////////////////////////////////////////
//
// Filename: addecrc.v
//
// Project: OpenArty, an entirely open SoC based upon the Arty platform
//
// Purpose: To (optionally) add a CRC to a stream of nibbles. The CRC
// is calculated from the stream.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
module addecrc(i_clk, i_ce, i_en, i_cancel, i_v, i_d, o_v, o_d);
localparam INVERT = 1; // Proper operation requires INVERT=1
input i_clk, i_ce, i_en, i_cancel;
input i_v;
input [3:0] i_d;
output reg o_v;
output reg [3:0] o_d;
 
reg [7:0] r_p;
reg [31:0] r_crc;
wire [3:0] lownibble;
wire [31:0] shifted_crc;
 
assign lownibble = r_crc[3:0] ^ i_d;
assign shifted_crc = { 4'h0, r_crc[31:4] };
 
initial o_v = 1'b0;
always @(posedge i_clk)
if (i_ce)
begin
if (((!i_v)&&(!o_v))||(i_cancel))
begin
r_crc <= (INVERT==0)? 32'h00 : 32'hffffffff;
r_p <= 8'hff;
end else if (i_v)
begin
o_v <= i_v;
r_p <= 8'hff;
o_d <= i_d;
 
`define CRCBIT8 32'hedb88320
`define CRCBIT4 32'h76dc4190
`define CRCBIT2 32'h3b6e20c8
`define CRCBIT1 32'h1db71064
 
// 0xedb88320 . 76dc4190 . 3b6e20c8 . 1db71064 . 0edb8832
case(lownibble)
4'h0: r_crc <= shifted_crc;
4'h1: r_crc <= shifted_crc ^ `CRCBIT1;
4'h2: r_crc <= shifted_crc ^ `CRCBIT2;
4'h3: r_crc <= shifted_crc ^ `CRCBIT2 ^ `CRCBIT1;
4'h4: r_crc <= shifted_crc ^ `CRCBIT4;
4'h5: r_crc <= shifted_crc ^ `CRCBIT4 ^ `CRCBIT1;
4'h6: r_crc <= shifted_crc ^ `CRCBIT4 ^ `CRCBIT2;
4'h7: r_crc <= shifted_crc ^ `CRCBIT4 ^ `CRCBIT2 ^ `CRCBIT1;
4'h8: r_crc <= shifted_crc ^ `CRCBIT8;
4'h9: r_crc <= shifted_crc ^ `CRCBIT8 ^ `CRCBIT1;
4'ha: r_crc <= shifted_crc ^ `CRCBIT8 ^ `CRCBIT2;
4'hb: r_crc <= shifted_crc ^ `CRCBIT8 ^ `CRCBIT2 ^ `CRCBIT1;
4'hc: r_crc <= shifted_crc ^ `CRCBIT8 ^ `CRCBIT4;
4'hd: r_crc <= shifted_crc ^ `CRCBIT8 ^ `CRCBIT4 ^ `CRCBIT1;
4'he: r_crc <= shifted_crc ^ `CRCBIT8 ^ `CRCBIT4 ^ `CRCBIT2;
4'hf: r_crc <= shifted_crc ^ `CRCBIT8 ^ `CRCBIT4 ^ `CRCBIT2 ^ `CRCBIT1;
 
default: r_crc <= { 4'h0, r_crc[31:4] };
endcase
end else begin
r_p <= { r_p[6:0], 1'b0 };
o_v <= (i_en)?r_p[7]:1'b0;
o_d <= r_crc[3:0] ^ ((INVERT==0)? 4'h0:4'hf);
r_crc <= { 4'h0, r_crc[31:4] };
end
end
 
endmodule
 
/addemac.v
0,0 → 1,122
////////////////////////////////////////////////////////////////////////////////
//
// Filename: addemac.v
//
// Project: OpenArty, an entirely open SoC based upon the Arty platform
//
// Purpose: To add the device hardware MAC address into a data stream
// that doesn't have it.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
module addemac(i_clk, i_ce, i_en, i_cancel, i_hw_mac,
i_v, i_nibble, o_v, o_nibble);
input i_clk, i_ce, i_en, i_cancel;
input [47:0] i_hw_mac;
input i_v;
input [3:0] i_nibble;
output reg o_v;
output reg [3:0] o_nibble;
 
wire [47:0] mac_remapped;
assign mac_remapped[47:44] = i_hw_mac[43:40];
assign mac_remapped[43:40] = i_hw_mac[47:44];
assign mac_remapped[39:36] = i_hw_mac[35:32];
assign mac_remapped[35:32] = i_hw_mac[39:36];
assign mac_remapped[31:28] = i_hw_mac[27:24];
assign mac_remapped[27:24] = i_hw_mac[31:28];
assign mac_remapped[23:20] = i_hw_mac[19:16];
assign mac_remapped[19:16] = i_hw_mac[23:20];
assign mac_remapped[15:12] = i_hw_mac[11: 8];
assign mac_remapped[11: 8] = i_hw_mac[15:12];
assign mac_remapped[ 7: 4] = i_hw_mac[ 3: 0];
assign mac_remapped[ 3: 0] = i_hw_mac[ 7: 4];
 
reg [47:0] r_hw;
reg [59:0] r_buf;
reg [5:0] r_pos;
 
always @(posedge i_clk)
if (i_ce)
begin
r_buf <= { r_buf[54:0], i_v, i_nibble };
 
if (((!i_v)&&(!o_v))||(i_cancel))
begin
r_buf[ 4] <= 1'b0;
r_buf[ 9] <= 1'b0;
r_buf[14] <= 1'b0;
r_buf[19] <= 1'b0;
r_buf[24] <= 1'b0;
r_buf[29] <= 1'b0;
r_buf[34] <= 1'b0;
r_buf[39] <= 1'b0;
r_buf[44] <= 1'b0;
r_buf[49] <= 1'b0;
r_buf[54] <= 1'b0;
r_buf[59] <= 1'b0;
end
 
if ((!i_v)||(i_cancel))
r_hw <= mac_remapped;
else
r_hw <= { r_hw[43:0], r_hw[47:44] };
 
if (((!i_v)&&(!o_v))||(i_cancel))
r_pos <= 6'h0;
else if ((r_pos < 6'h18 )&&(i_en))
r_pos <= r_pos + 6'h1;
else if ((r_pos < 6'h20 )&&(!i_en))
r_pos <= r_pos + 6'h1;
 
if (i_en)
begin
if (((!i_v)&&(!o_v))||(i_cancel))
begin
o_v <= 1'b0;
end else begin
if (r_pos < 6'hc) // six bytes, but counted as
begin // nibbles
{ o_v, o_nibble } <= { i_v, i_nibble };
end else if (r_pos < 6'h18)
begin
{ o_v, o_nibble } <= { 1'b1, r_hw[47:44] };
end else
{ o_v, o_nibble } <= r_buf[59:55];
end
end else if (r_pos < 6'h20)
{ o_v, o_nibble } <= r_buf[19:15];
else
{ o_v, o_nibble } <= { i_v, i_nibble };
if(i_cancel)
o_v <= 1'b0;
end
 
endmodule
/addepad.v
0,0 → 1,77
////////////////////////////////////////////////////////////////////////////////
//
// Filename: addepad.v
//
// Project: OpenArty, an entirely open SoC based upon the Arty platform
//
// Purpose: To force the minimum packet size of an ethernet frame to be
// a minimum of 64 bytes. This assumes that the CRC will be
// adding 32-bits to the packet after us, so instead of padding to
// 64 bytes, we'll pad to 60 bytes instead. If the user is providing
// their own CRC, they'll need to adjust the padding themselves.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
module addepad(i_clk, i_ce, i_en, i_cancel, i_v, i_d, o_v, o_d);
input i_clk, i_ce, i_en, i_cancel;
input i_v; // Valid
input [3:0] i_d; // Data nibble
output reg o_v;
output reg [3:0] o_d;
 
// 60 bytes translates to 120 nibbles, so let's keep track of our
// minimum number of nibbles to transmit
reg [119:0] r_v;
 
initial r_v = 120'hff_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
initial o_v = 1'b0;
always @(posedge i_clk)
if (i_ce)
begin
if (((!i_v)&&(!o_v))||(i_cancel))
begin
r_v <= 120'hff_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
o_v <= 1'b0;
end else if (i_v)
begin
o_v <= i_v;
r_v <= { r_v[118:0], 1'b0 };
end else begin
o_v <= r_v[119];
r_v <= { r_v[118:0], 1'b0 };
end
 
if (i_v)
o_d <= i_d;
else
o_d <= 4'h0;
end
 
endmodule
/addepreamble.v
0,0 → 1,88
////////////////////////////////////////////////////////////////////////////////
//
// Filename: addepreamble.v
//
// Project: OpenArty, an entirely open SoC based upon the Arty platform
//
// Purpose: To add the ethernet preamble to a stream of values (i.e., to
// an ethernet packet ...)
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
module addepreamble(i_clk, i_ce, i_en, i_cancel, i_v, i_d, o_v, o_d);
input i_clk, i_ce, i_en, i_cancel;
input i_v; // Valid
input [3:0] i_d; // Data nibble
output wire o_v;
output wire [3:0] o_d;
 
reg [84:0] shiftreg;
reg r_v;
reg [3:0] r_d;
 
initial r_v = 1'b0;
always @(posedge i_clk)
if (i_ce)
begin
shiftreg <= { shiftreg[79:0], { i_v, i_d }};
r_v <= shiftreg[84];
r_d <= shiftreg[83:80];
if (((!i_v)&&(!o_v))||(i_cancel))
begin
shiftreg <= { 5'h00, 5'h15, 5'h15, 5'h15, 5'h15,
5'h15, 5'h15, 5'h15, 5'h15,
5'h15, 5'h15, 5'h15, 5'h15,
5'h15, 5'h15, 5'h15, 5'h1d };
if (!i_en)
begin
shiftreg[ 4] <= 1'b0;
shiftreg[ 9] <= 1'b0;
shiftreg[14] <= 1'b0;
shiftreg[19] <= 1'b0;
shiftreg[24] <= 1'b0;
shiftreg[29] <= 1'b0;
shiftreg[34] <= 1'b0;
shiftreg[39] <= 1'b0;
shiftreg[44] <= 1'b0;
shiftreg[49] <= 1'b0;
shiftreg[54] <= 1'b0;
shiftreg[59] <= 1'b0;
shiftreg[64] <= 1'b0;
shiftreg[69] <= 1'b0;
shiftreg[74] <= 1'b0;
shiftreg[79] <= 1'b0;
end
end
end
 
assign o_v = r_v;
assign o_d = r_d;
 
endmodule
/builddate.v
38,4 → 38,4
////////////////////////////////////////////////////////////////////////////////
//
//
`define DATESTAMP 32'h20160909
`define DATESTAMP 32'h20161015
/busmaster.v
74,10 → 74,11
// SCOPE POSITION ZERO
//
`ifdef FLASH_ACCESS
`define FLASH_SCOPE // Position zero
`else
// `define FLASH_SCOPE // Position zero
`endif
`ifdef ZIPCPU
// `define CPU_SCOPE // Position zero
`ifndef FLASH_SCOPE
`define CPU_SCOPE // Position zero
`endif
`endif
//
84,18 → 85,24
// SCOPE POSITION ONE
//
// `define GPS_SCOPE // Position one
`ifdef ICAPE_ACCESS
`define CFG_SCOPE // Position one
`endif
// `ifdef ICAPE_ACCESS
// `define CFG_SCOPE // Position one
// `endif
// `define WBU_SCOPE
//
// SCOPE POSITION TWO
//
`ifdef SDRAM_ACCESS
`define SDRAM_SCOPE // Position two
// `define SDRAM_SCOPE // Position two
`endif
// `define ENET_SCOPE
//
// SCOPE POSITION THREE
//
`ifdef ETHERNET_ACCESS
`define ENET_SCOPE
`endif
//
//
module busmaster(i_clk, i_rst,
// CNC
i_rx_stb, i_rx_data, o_tx_stb, o_tx_data, i_tx_busy,
119,6 → 126,10
i_ram_dbg,
// The SD Card
o_sd_sck, o_sd_cmd, o_sd_data, i_sd_cmd, i_sd_data, i_sd_detect,
// Ethernet control (packets) lines
o_net_reset_n, i_net_rx_clk, i_net_col, i_net_crs, i_net_dv,
i_net_rxd, i_net_rxerr,
i_net_tx_clk, o_net_tx_en, o_net_txd,
// Ethernet control (MDIO) lines
o_mdclk, o_mdio, o_mdwe, i_mdio,
// OLED Control interface (roughly SPI)
127,7 → 138,7
// The GPS PMod
i_gps_pps, i_gps_3df
);
parameter ZA=24, ZIPINTS=14;
parameter ZA=28, ZIPINTS=14, RESET_ADDRESS=28'h04e0000;
input i_clk, i_rst;
// The bus commander, via an external uart port
input i_rx_stb;
182,6 → 193,14
input i_sd_cmd;
input [3:0] i_sd_data;
input i_sd_detect;
// Ethernet control
output wire o_net_reset_n;
input i_net_rx_clk, i_net_col, i_net_crs, i_net_dv;
input [3:0] i_net_rxd;
input i_net_rxerr;
input i_net_tx_clk;
output wire o_net_tx_en;
output wire [3:0] o_net_txd;
// Ethernet control (MDIO)
output wire o_mdclk, o_mdio, o_mdwe;
input i_mdio;
226,6 → 245,9
// Oh, and the debug control for the ZIP CPU
wire wbu_zip_sel, zip_dbg_ack, zip_dbg_stall;
wire [31:0] zip_dbg_data;
`ifdef WBU_SCOPE
wire [31:0] wbu_debug;
`endif
wbubus genbus(i_clk, i_rx_stb, i_rx_data,
wbu_cyc, wbu_stb, wbu_we, wbu_addr, wbu_data,
(wbu_zip_sel)?zip_dbg_ack:wbu_ack,
233,9 → 255,18
wbu_err,
(wbu_zip_sel)?zip_dbg_data:wbu_idata,
w_interrupt,
o_tx_stb, o_tx_data, i_tx_busy);
o_tx_stb, o_tx_data, i_tx_busy
// , wbu_debug
);
 
`ifdef WBU_SCOPE
// assign o_dbg = (wbu_ack)&&(wbu_cyc);
assign wbu_debug = { wbu_cyc, wbu_stb, wbu_we, wbu_ack, wbu_stall,
wbu_err, wbu_zip_sel,
wbu_addr[8:0],
wbu_data[7:0],
wbu_idata[7:0] };
`endif
 
wire zip_cpu_int; // True if the CPU suddenly halts
`ifdef ZIPCPU
264,7 → 295,7
gpsrx_int, rtc_pps
};
 
zipsystem #( .RESET_ADDRESS(24'h0480000),
zipsystem #( .RESET_ADDRESS(RESET_ADDRESS),
.ADDRESS_WIDTH(ZA),
.LGICACHE(10),
.START_HALTED(1),
280,13 → 311,13
((wbu_stb)&&(wbu_zip_sel)),wbu_we, wbu_addr[0],
wbu_data,
zip_dbg_ack, zip_dbg_stall, zip_dbg_data
`ifdef CPU_DEBUG
`ifdef CPU_SCOPE
, zip_scope_data
`endif
);
`else // ZIP_SYSTEM
wire w_zip_cpu_int_ignored;
zipbones #( .RESET_ADDRESS(24'h08000),
zipbones #( .RESET_ADDRESS(RESET_ADDRESS),
.ADDRESS_WIDTH(ZA),
.LGICACHE(10),
.START_HALTED(1),
301,7 → 332,7
((wbu_stb)&&(wbu_zip_sel)),wbu_we, wbu_addr[0],
wbu_data,
zip_dbg_ack, zip_dbg_stall, zip_dbg_data
`ifdef CPU_DEBUG
`ifdef CPU_SCOPE
, zip_scope_data
`endif
);
328,7 → 359,7
zip_cyc, zip_stb, zip_we, zip_addr, zip_data,
zip_ack, zip_stall, zip_err,
// The UART interface Master
(wbu_cyc)&&(~wbu_zip_sel), (wbu_stb)&&(~wbu_zip_sel), wbu_we,
(wbu_cyc)&&(!wbu_zip_sel), (wbu_stb)&&(!wbu_zip_sel), wbu_we,
wbu_addr, wbu_data,
wbu_ack, wbu_stall, wbu_err,
// Common bus returns
423,26 → 454,24
// line.
wire io_ack, oled_ack,
rtc_ack, sdcard_ack,
netp_ack, gps_ack, mio_ack, cfg_ack, netb_ack,
net_ack, gps_ack, mio_ack, cfg_ack,
mem_ack, flash_ack, ram_ack;
reg many_ack, slow_many_ack;
reg slow_ack, scop_ack;
wire [5:0] ack_list;
assign ack_list = { ram_ack, flash_ack, mem_ack, netb_ack, netp_ack, slow_ack };
wire [4:0] ack_list;
assign ack_list = { ram_ack, flash_ack, mem_ack, net_ack, slow_ack };
initial many_ack = 1'b0;
always @(posedge i_clk)
many_ack <= ((ack_list != 6'h20)
&&(ack_list != 6'h10)
&&(ack_list != 6'h8)
&&(ack_list != 6'h4)
&&(ack_list != 6'h2)
&&(ack_list != 6'h1)
&&(ack_list != 6'h0));
many_ack <= ((ack_list != 5'h10)
&&(ack_list != 5'h8)
&&(ack_list != 5'h4)
&&(ack_list != 5'h2)
&&(ack_list != 5'h1)
&&(ack_list != 5'h0));
/*
assign many_ack = ( { 2'h0, ram_ack}
+{2'h0, flash_ack }
+{2'h0, mem_ack }
+{2'h0, netb_ack }
+{2'h0, slow_ack } > 3'h1 );
*/
 
471,7 → 500,7
//
wire [31:0] io_data, oled_data,
rtc_data, sdcard_data,
netp_data, gps_data, mio_data, cfg_data, netb_data,
net_data, gps_data, mio_data, cfg_data,
mem_data, flash_data, ram_data;
reg [31:0] slow_data, scop_data;
 
479,10 → 508,10
always @(posedge i_clk)
if ((ram_ack)||(flash_ack))
wb_idata <= (ram_ack)?ram_data:flash_data;
else if ((mem_ack)||(netb_ack))
wb_idata <= (mem_ack)?mem_data:netb_data;
else if ((mem_ack)||(net_ack))
wb_idata <= (mem_ack)?mem_data:net_data;
else
wb_idata <= (netp_ack)?netp_data: slow_data;
wb_idata <= slow_data;
 
// 7 control lines, 8x32 data lines
always @(posedge i_clk)
503,7 → 532,7
//
wire io_stall, scop_stall, oled_stall,
rtc_stall, sdcard_stall,
netp_stall, gps_stall, mio_stall, cfg_stall, netb_stall,
net_stall, gps_stall, mio_stall, cfg_stall, netb_stall,
mem_stall, flash_stall, ram_stall,
many_stall;
assign wb_stall = (wb_cyc)&&(
511,12 → 540,12
||((scop_sel)&&(scop_stall)) // Never stalls
||((rtc_sel)&&(rtc_stall)) // Never stalls
||((sdcard_sel)&&(sdcard_stall))// Never stalls
||((netp_sel)&&(netp_stall))
||((netp_sel)&&(net_stall)) // Never stalls
||((gps_sel)&&(gps_stall)) //(maybe? never stalls?)
||((oled_sel)&&(oled_stall)) // Never stalls
||((mio_sel)&&(mio_stall))
||((cfg_sel)&&(cfg_stall))
||((netb_sel)&&(netb_stall)) // Never stalls
||((netb_sel)&&(net_stall)) // Never stalls
||((mem_sel)&&(mem_stall)) // Never stalls
||((flash_sel|flctl_sel)&&(flash_stall))
||((ram_sel)&&(ram_stall)));
741,7 → 770,7
//
`ifdef OLEDRGB_ACCESS
wboled
.#( .CBITS(4))// Div ck by 2^4=16, words take 200ns@81.25MHz
#( .CBITS(4))// Div ck by 2^4=16, words take 200ns@81.25MHz
rgbctrl(i_clk,
wb_cyc, (wb_stb)&&(oled_sel), wb_we,
wb_addr[1:0], wb_data,
837,39 → 866,39
// ETHERNET DEVICE ACCESS
//
`ifdef ETHERNET_ACCESS
reg r_mio_ack, r_netb_ack, r_netp_ack;
always @(posedge i_clk)
r_mio_ack <= (wb_stb)&&(mio_sel);
always @(posedge i_clk)
r_netp_ack <= (wb_stb)&&(netp_sel);
assign mio_ack = r_mio_ack;
assign netp_ack = r_netp_ack;
`ifdef ENET_SCOPE
wire [31:0] txnet_data;
`endif
 
assign mio_data = 32'h00;
assign netp_data = 32'h00;
assign mio_stall = 1'b0;
assign netp_stall= 1'b0;
assign enet_rx_int = 1'b0;
assign enet_tx_int = 1'b0;
enetpackets #(12)
netctrl(i_clk, i_rst, wb_cyc,(wb_stb)&&((netp_sel)||(netb_sel)),
wb_we, { (netb_sel), wb_addr[10:0] }, wb_data,
net_ack, net_stall, net_data,
o_net_reset_n,
i_net_rx_clk, i_net_col, i_net_crs, i_net_dv, i_net_rxd,
i_net_rxerr,
i_net_tx_clk, o_net_tx_en, o_net_txd,
enet_rx_int, enet_tx_int
`ifdef ENET_SCOPE
, txnet_data
`endif
);
 
wire [31:0] mdio_debug;
enetctrl #(2)
mdio(i_clk, i_rst, wb_cyc, (wb_stb)&&(netb_sel), wb_we,
wb_addr[4:0], wb_data[15:0],
netb_ack, netb_stall, netb_data,
o_mdclk, o_mdio, i_mdio, o_mdwe);
mdio(i_clk, i_rst, wb_cyc, (wb_stb)&&(mio_sel), wb_we,
wb_addr[4:0], wb_data[15:0],
mio_ack, mio_stall, mio_data,
o_mdclk, o_mdio, i_mdio, o_mdwe,
mdio_debug);
`else
reg r_mio_ack, r_netb_ack, r_netp_ack;
reg r_mio_ack;
always @(posedge i_clk)
r_mio_ack <= (wb_stb)&&(mio_sel);
always @(posedge i_clk)
r_netp_ack <= (wb_stb)&&(netp_sel);
assign mio_ack = r_mio_ack;
assign netp_ack = r_netp_ack;
 
assign mio_data = 32'h00;
assign netp_data = 32'h00;
assign mio_stall = 1'b0;
assign netp_stall= 1'b0;
assign enet_rx_int = 1'b0;
assign enet_tx_int = 1'b0;
 
880,8 → 909,8
// consumes resources for us so we have an idea of what might be
// available when we do have ETHERNET_ACCESS defined.
//
memdev #(11) enet_buffers(i_clk, wb_cyc, (wb_stb)&&(netb_sel), wb_we,
wb_addr[10:0], wb_data, netb_ack, netb_stall, netb_data);
memdev #(11) enet_buffers(i_clk, wb_cyc, (wb_stb)&&((netb_sel)||(netp_sel)), wb_we,
wb_addr[10:0], wb_data, net_ack, net_stall, net_data);
assign o_mdclk = 1'b1;
assign o_mdio = 1'b1;
assign o_mdwe = 1'b1;
921,9 → 950,9
// FLASH MEMORY ACCESS
//
`ifdef FLASH_ACCESS
`ifdef FLASH_SCOPE
// `ifdef FLASH_SCOPE
wire [31:0] flash_debug;
`endif
// `endif
wire w_ignore_cmd_accepted;
eqspiflash flashmem(i_clk, i_rst,
wb_cyc,(wb_stb)&&(flash_sel),(wb_stb)&&(flctl_sel),wb_we,
931,9 → 960,9
flash_ack, flash_stall, flash_data,
o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat, i_qspi_dat,
flash_int, w_ignore_cmd_accepted
`ifdef FLASH_SCOPE
// `ifdef FLASH_SCOPE
, flash_debug
`endif
// `endif
);
`else
assign o_qspi_sck = 1'b1;
1028,15 → 1057,16
wire [31:0] scop_cpu_data;
wire scop_cpu_ack, scop_cpu_stall, scop_cpu_interrupt;
wire scop_cpu_trigger;
// assign scop_cpu_trigger = zip_scope_data[30];
assign scop_cpu_trigger = (wb_stb)&&(mem_sel)&&(~wb_we)
&&(wb_err)||(zip_scope_data[31]);
wbscope #(5'd13) cpuscope(i_clk, 1'b1,(scop_cpu_trigger), zip_scope_data,
// Wishbone interface
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)),
wb_we, wb_addr[0], wb_data,
scop_cpu_ack, scop_cpu_stall, scop_cpu_data,
scop_cpu_interrupt);
assign scop_cpu_trigger = (zip_scope_data[31]);
wbscope #( .LGMEM(5'd13),
.DEFAULT_HOLDOFF(32))
cpuscope(i_clk, 1'b1,(scop_cpu_trigger),zip_scope_data,
// Wishbone interface
i_clk, wb_cyc,
((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)),
wb_we, wb_addr[0], wb_data,
scop_cpu_ack, scop_cpu_stall, scop_cpu_data,
scop_cpu_interrupt);
 
assign scop_a_data = scop_cpu_data;
assign scop_a_ack = scop_cpu_ack;
1047,9 → 1077,8
wire [31:0] scop_flash_data;
wire scop_flash_ack, scop_flash_stall, scop_flash_interrupt;
wire scop_flash_trigger;
// assign scop_cpu_trigger = zip_scope_data[30];
assign scop_flash_trigger = (wb_stb)&&((flash_sel)||(flctl_sel));
wbscope #(5'd13) flashscope(i_clk, 1'b1,
wbscope #(5'd11) flashscope(i_clk, 1'b1,
(scop_flash_trigger), flash_debug,
// Wishbone interface
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)),
1120,6 → 1149,22
assign scop_b_ack = scop_cfg_ack;
assign scop_b_interrupt = scop_cfg_interrupt;
`else
`ifdef WBU_SCOPE
wire [31:0] scop_wbu_data;
wire scop_wbu_ack, scop_wbu_stall, scop_wbu_interrupt;
wbscope #(5'd10,32,1) wbuscope(i_clk, 1'b1, (flash_sel)&&(wb_stb),
wbu_debug,
// Wishbone interface
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b01)),
wb_we, wb_addr[0], wb_data,
scop_wbu_ack, scop_wbu_stall, scop_wbu_data,
scop_wbu_interrupt);
 
assign scop_b_data = scop_wbu_data;
assign scop_b_stall = scop_wbu_stall;
assign scop_b_ack = scop_wbu_ack;
assign scop_b_interrupt = scop_wbu_interrupt;
`else
assign scop_b_data = 32'h00;
assign scop_b_stall = 1'b0;
assign scop_b_interrupt = 1'b0;
1130,6 → 1175,7
assign scop_b_ack = r_scop_b_ack;
`endif
`endif
`endif
 
//
// SCOPE C
1145,7 → 1191,7
assign sdram_trigger = (ram_sel)&&(wb_stb);
assign sdram_debug= i_ram_dbg;
 
wbscope #(5'd10,32,1) ramscope(i_clk, 1'b1, sdram_trigger, sdram_debug,
wbscope #(5'd9,32,1) ramscope(i_clk, 1'b1, sdram_trigger, sdram_debug,
// Wishbone interface
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b10)),
wb_we, wb_addr[0], wb_data,
1173,7 → 1219,37
wire [31:0] scop_d_data;
wire scop_d_ack, scop_d_stall, scop_d_interrupt;
//
//`else
`ifdef ENET_SCOPE
wire [31:0] scop_net_data;
wire scop_net_ack, scop_net_stall, scop_net_interrupt;
 
/*
wbscope #(5'd8,32,1)
net_scope(i_clk, 1'b1, !mdio_debug[1], mdio_debug,
// Wishbone interface
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b11)),
wb_we, wb_addr[0], wb_data,
scop_net_ack, scop_net_stall, scop_net_data,
scop_net_interrupt);
*/
 
// 5'd8 is sufficient for small packets, and indeed the minimum for
// watching any packets--as the minimum packet size is 64 bytes, or
// 128 nibbles.
wbscope #(5'd9,32,0)
net_scope(i_net_rx_clk, 1'b1, txnet_data[31], txnet_data,
// Wishbone interface
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b11)),
wb_we, wb_addr[0], wb_data,
scop_net_ack, scop_net_stall, scop_net_data,
scop_net_interrupt);
 
assign scop_d_ack = scop_net_ack;
assign scop_d_stall = scop_net_stall;
assign scop_d_data = scop_net_data;
assign scop_d_interrupt = scop_net_interrupt;
`else
assign scop_d_data = 32'h00;
assign scop_d_stall = 1'b0;
assign scop_d_interrupt = 1'b0;
1182,7 → 1258,7
always @(posedge i_clk)
r_scop_d_ack <= (wb_stb)&&(scop_sel)&&(wb_addr[2:1] == 2'b11);
assign scop_d_ack = r_scop_d_ack;
//`endif
`endif
 
reg all_scope_interrupts;
always @(posedge i_clk)
/cpu/busdelay.v
1,20 → 1,41
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: busdelay.v
//
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
//
// Purpose: Delay any access to the wishbone bus by a single clock. This
// particular version of the busdelay builds off of some previous
// work, but also delays and buffers the stall line as well. It is
// designed to allow pipelined accesses (1 access/clock) to still work,
// while also providing for single accesses.
// Purpose: Delay any access to the wishbone bus by a single clock.
//
// When the first Zip System would not meet the timing requirements of
// the board it was placed upon, this bus delay was added to help out.
// It may no longer be necessary, having cleaned some other problems up
// first, but it will remain here as a means of alleviating timing
// problems.
//
// The specific problem takes place on the stall line: a wishbone master
// *must* know on the first clock whether or not the bus will stall.
//
//
// After a period of time, I started a new design where the timing
// associated with this original bus clock just wasn't ... fast enough.
// I needed to delay the stall line as well. A new busdelay was then
// written and debugged whcih delays the stall line. (I know, you aren't
// supposed to delay the stall line--but what if you *have* to in order
// to meet timing?) This new logic has been merged in with the old,
// and the DELAY_STALL line can be set to non-zero to use it instead
// of the original logic. Don't use it if you don't need it: it will
// consume resources and slow your bus down more, but if you do need
// it--don't be afraid to use it.
//
// Both versions of the bus delay will maintain a single access per
// clock when pipelined, they only delay the time between the strobe
// going high and the actual command being accomplished.
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
32,7 → 53,7
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
module busdelay(i_clk,
// The input bus
41,7 → 62,7
// The delayed bus
o_dly_cyc, o_dly_stb, o_dly_we, o_dly_addr, o_dly_data,
i_dly_ack, i_dly_stall, i_dly_data, i_dly_err);
parameter AW=32, DW=32;
parameter AW=32, DW=32, DELAY_STALL = 0;
input i_clk;
// Input/master bus
input i_wb_cyc, i_wb_stb, i_wb_we;
48,12 → 69,11
input [(AW-1):0] i_wb_addr;
input [(DW-1):0] i_wb_data;
output reg o_wb_ack;
output reg o_wb_stall;
output wire o_wb_stall;
output reg [(DW-1):0] o_wb_data;
output reg o_wb_err;
output wire o_wb_err;
// Delayed bus
output reg o_dly_cyc, o_dly_we;
output wire o_dly_stb;
output reg o_dly_cyc, o_dly_stb, o_dly_we;
output reg [(AW-1):0] o_dly_addr;
output reg [(DW-1):0] o_dly_data;
input i_dly_ack;
61,36 → 81,100
input [(DW-1):0] i_dly_data;
input i_dly_err;
 
reg loaded;
initial o_dly_cyc = 1'b0;
initial loaded = 1'b0;
generate
if (DELAY_STALL != 0)
begin
reg r_stb, r_we, r_rtn_stall, r_rtn_err;
reg [(DW-1):0] r_data;
reg [(AW-1):0] r_addr;
 
always @(posedge i_clk)
o_wb_stall <= (loaded)&&(i_dly_stall);
initial o_dly_cyc = 1'b0;
initial r_rtn_stall= 1'b0;
initial r_stb = 1'b0;
always @(posedge i_clk)
begin
o_dly_cyc <= (i_wb_cyc);
if (!i_dly_stall)
begin
r_we <= i_wb_we;
r_addr <= i_wb_addr;
r_data <= i_wb_data;
 
initial o_dly_cyc = 1'b0;
always @(posedge i_clk)
o_dly_cyc <= (i_wb_cyc);
// Add the i_wb_cyc criteria here, so we can simplify the o_wb_stall
// criteria below, which would otherwise *and* these two.
always @(posedge i_clk)
loaded <= (i_wb_stb)||((loaded)&&(i_dly_stall)&&(~i_dly_err)&&(i_wb_cyc));
assign o_dly_stb = loaded;
always @(posedge i_clk)
if (~i_dly_stall)
o_dly_we <= i_wb_we;
always @(posedge i_clk)
if (~i_dly_stall)
o_dly_addr<= i_wb_addr;
always @(posedge i_clk)
if (~i_dly_stall)
o_dly_data <= i_wb_data;
always @(posedge i_clk)
o_wb_ack <= (i_dly_ack)&&(o_dly_cyc)&&(i_wb_cyc);
always @(posedge i_clk)
o_wb_data <= i_dly_data;
if (r_stb)
begin
o_dly_we <= r_we;
o_dly_addr <= r_addr;
o_dly_data <= r_data;
o_dly_stb <= 1'b1;
r_rtn_stall <= 1'b0;
r_stb <= 1'b0;
end else begin
o_dly_we <= i_wb_we;
o_dly_addr <= i_wb_addr;
o_dly_data <= i_wb_data;
o_dly_stb <= i_wb_stb;
r_stb <= 1'b0;
r_rtn_stall <= 1'b0;
end
end else if ((!r_stb)&&(!o_wb_stall))
begin
r_we <= i_wb_we;
r_addr <= i_wb_addr;
r_data <= i_wb_data;
r_stb <= i_wb_stb;
 
always @(posedge i_clk)
o_wb_err <= (i_dly_err)&&(o_dly_cyc)&&(i_wb_cyc);
r_rtn_stall <= i_wb_stb;
end
 
if (!i_wb_cyc)
begin
o_dly_stb <= 1'b0;
r_stb <= 1'b0;
r_rtn_stall <= 1'b0;
end
 
o_wb_ack <= (i_dly_ack)&&(i_wb_cyc)&&(o_dly_cyc);
o_wb_data <= i_dly_data;
r_rtn_err <= (i_dly_err)&&(i_wb_cyc)&&(o_dly_cyc);
end
 
assign o_wb_stall = r_rtn_stall;
assign o_wb_err = r_rtn_err;
 
end else begin
 
initial o_dly_cyc = 1'b0;
initial o_dly_stb = 1'b0;
 
always @(posedge i_clk)
o_dly_cyc <= i_wb_cyc;
// Add the i_wb_cyc criteria here, so we can simplify the
// o_wb_stall criteria below, which would otherwise *and*
// these two.
always @(posedge i_clk)
if (~o_wb_stall)
o_dly_stb <= ((i_wb_cyc)&&(i_wb_stb));
always @(posedge i_clk)
if (~o_wb_stall)
o_dly_we <= i_wb_we;
always @(posedge i_clk)
if (~o_wb_stall)
o_dly_addr<= i_wb_addr;
always @(posedge i_clk)
if (~o_wb_stall)
o_dly_data <= i_wb_data;
always @(posedge i_clk)
o_wb_ack <= (i_dly_ack)&&(o_dly_cyc)&&(i_wb_cyc);
always @(posedge i_clk)
o_wb_data <= i_dly_data;
 
// Our only non-delayed line, yet still really delayed. Perhaps
// there's a way to register this?
// o_wb_stall <= (i_wb_cyc)&&(i_wb_stb) ... or some such?
// assign o_wb_stall=((i_wb_cyc)&&(i_dly_stall)&&(o_dly_stb));//&&o_cyc
assign o_wb_stall = ((i_dly_stall)&&(o_dly_stb));//&&o_cyc
assign o_wb_err = i_dly_err;
end endgenerate
 
endmodule
/cpu/cpudefs.v
97,7 → 97,7
// mode.
//
//
// `define OPT_DIVIDE
`define OPT_DIVIDE
//
//
//
273,6 → 273,6
`define INCLUDE_ACCOUNTING_COUNTERS
//
//
// `define DEBUG_SCOPE
`define DEBUG_SCOPE
//
`endif // CPUDEFS_H
/cpu/zipcpu.v
7,7 → 7,9
// Purpose: This is the top level module holding the core of the Zip CPU
// together. The Zip CPU is designed to be as simple as possible.
// (actual implementation aside ...) The instruction set is about as
// RISC as you can get, there are only 16 instruction types supported.
// RISC as you can get, with only 26 instruction types currently supported.
// (There are still 8-instruction Op-Codes reserved for floating point,
// and 5 which can be used for transactions not requiring registers.)
// Please see the accompanying spec.pdf file for a description of these
// instructions.
//
26,10 → 28,11
//
// 4. Write-back Results
//
// Further information about the inner workings of this CPU may be
// found in the spec.pdf file. (The documentation within this file
// had become out of date and out of sync with the spec.pdf, so look
// to the spec.pdf for accurate and up to date information.)
// Further information about the inner workings of this CPU, such as
// what causes pipeline stalls, may be found in the spec.pdf file. (The
// documentation within this file had become out of date and out of sync
// with the spec.pdf, so look to the spec.pdf for accurate and up to date
// information.)
//
//
// In general, the pipelining is controlled by three pieces of logic
103,8 → 106,8
//
`define CPU_CC_REG 4'he
`define CPU_PC_REG 4'hf
`define CPU_CLRCACHE_BIT 14 // Floating point error flag, set on error
`define CPU_PHASE_BIT 13 // Floating point error flag, set on error
`define CPU_CLRCACHE_BIT 14 // Set to clear the I-cache, automatically clears
`define CPU_PHASE_BIT 13 // Set if we are executing the latter half of a VLIW
`define CPU_FPUERR_BIT 12 // Floating point error flag, set on error
`define CPU_DIVERR_BIT 11 // Divide error flag, set on divide by zero
`define CPU_BUSERR_BIT 10 // Bus error flag, set on error
206,8 → 209,8
// (BUS, TRAP,ILL,BREAKEN,STEP,GIE,SLEEP ), V, N, C, Z
reg [3:0] flags, iflags;
wire [14:0] w_uflags, w_iflags;
reg trap, break_en, step, gie, sleep, r_halted,
break_pending;
reg trap, break_en, step, gie, sleep, r_halted;
wire break_pending;
wire w_clear_icache;
`ifdef OPT_ILLEGAL_INSTRUCTION
reg ill_err_u, ill_err_i;
279,13 → 282,14
//
// Now, let's read our operands
reg [4:0] alu_reg;
reg [3:0] opn;
reg [4:0] opR;
wire [3:0] opn;
wire [4:0] opR;
reg [31:0] r_opA, r_opB;
reg [(AW-1):0] op_pc;
wire [31:0] w_opA, w_opB;
wire [31:0] opA_nowait, opB_nowait, opA, opB;
reg opR_wr, opR_cc, opF_wr, op_gie;
reg opR_wr, opF_wr;
wire op_gie, opR_cc;
wire [14:0] opFl;
reg [5:0] r_opF;
wire [7:0] opF;
301,7 → 305,7
wire op_illegal;
assign op_illegal = 1'b0;
`endif
reg op_break;
wire op_break;
wire op_lock;
 
 
311,7 → 315,7
// Variable declarations
//
//
reg [(AW-1):0] alu_pc;
wire [(AW-1):0] alu_pc;
reg r_alu_pc_valid, mem_pc_valid;
wire alu_pc_valid;
wire alu_phase;
320,9 → 324,8
wire [3:0] alu_flags;
wire alu_valid, alu_busy;
wire set_cond;
reg alu_wr, alF_wr, alu_gie;
wire alu_illegal_op;
wire alu_illegal;
reg alu_wr, alF_wr;
wire alu_gie, alu_illegal_op, alu_illegal;
 
 
 
473,7 → 476,7
`ifdef OPT_PIPELINED
assign alu_stall = (((~master_ce)||(mem_rdbusy)||(alu_busy))&&(opvalid_alu)) //Case 1&2
||((opvalid)&&(op_lock)&&(op_lock_stall))
||((opvalid)&&(op_break))
||((opvalid)&&(op_break)) // || op_illegal
||(wr_reg_ce)&&(wr_write_cc)
||(div_busy)||(fpu_busy);
assign alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)
744,14 → 747,19
`endif
 
always @(posedge i_clk)
`ifdef OPT_PIPELINED
if (op_change_data_ce)
`endif
begin
`ifdef OPT_PIPELINED
if ((wr_reg_ce)&&(wr_reg_id == dcdA))
r_opA <= wr_gpreg_vl;
else if (dcdA_pc)
else
`endif
if (dcdA_pc)
r_opA <= w_pcA_v;
else if (dcdA_cc)
r_opA <= { w_cpu_info, w_opA[22:15], (dcdA[4])?w_uflags:w_iflags };
r_opA <= { w_cpu_info, w_opA[22:16], 1'b0, (dcdA[4])?w_uflags:w_iflags };
else
r_opA <= w_opA;
`ifdef OPT_PIPELINED
775,18 → 783,22
endgenerate
 
assign w_opBnI = (~dcdB_rd) ? 32'h00
: (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_gpreg_vl
`ifdef OPT_PIPELINED
: ((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_gpreg_vl
`endif
: ((dcdB_pc) ? w_pcB_v
: ((dcdB_cc) ? { w_cpu_info, w_opB[22:15], // w_opB[31:14],
(dcdB[4])?w_uflags:w_iflags}
: w_opB)));
: ((dcdB_cc) ? { w_cpu_info, w_opB[22:16], // w_opB[31:14],
1'b0, (dcdB[4])?w_uflags:w_iflags}
: w_opB));
 
always @(posedge i_clk)
`ifdef OPT_PIPELINED
if (op_change_data_ce)
r_opB <= w_opBnI + dcdI;
`ifdef OPT_PIPELINED
else if ((wr_reg_ce)&&(opB_id == wr_reg_id)&&(opB_rd))
r_opB <= wr_gpreg_vl;
`else
r_opB <= w_opBnI + dcdI;
`endif
 
// The logic here has become more complex than it should be, no thanks
799,9 → 811,11
// below, arriving at what we finally want in the (now wire net)
// opF.
always @(posedge i_clk)
`ifdef OPT_PIPELINED
if (op_ce) // Cannot do op_change_data_ce here since opF depends
// upon being either correct for a valid op, or correct
// for the last valid op
`endif
begin // Set the flag condition codes, bit order is [3:0]=VNCZ
case(dcdF[2:0])
3'h0: r_opF <= 6'h00; // Always
836,7 → 850,7
initial opvalid_div = 1'b0;
initial opvalid_fpu = 1'b0;
always @(posedge i_clk)
if (i_rst)
if ((i_rst)||(clear_pipeline))
begin
opvalid <= 1'b0;
opvalid_alu <= 1'b0;
865,7 → 879,7
opvalid_div <= (dcdDV)&&(w_opvalid);
opvalid_fpu <= (dcdFP)&&(w_opvalid);
`endif
end else if ((clear_pipeline)||(adf_ce_unconditional)||(mem_ce))
end else if ((adf_ce_unconditional)||(mem_ce))
begin
opvalid <= 1'b0;
opvalid_alu <= 1'b0;
883,12 → 897,19
// to be, step through it, and then replace it back. In this fashion,
// a debugger can step through code.
// assign w_op_break = (dcd_break)&&(r_dcdI[15:0] == 16'h0001);
initial op_break = 1'b0;
`ifdef OPT_PIPELINED
reg r_op_break;
 
initial r_op_break = 1'b0;
always @(posedge i_clk)
if (i_rst) op_break <= 1'b0;
else if (op_ce) op_break <= (dcd_break); // &&(dcdvalid)
if (i_rst) r_op_break <= 1'b0;
else if (op_ce) r_op_break <= (dcd_break); //||dcd_illegal &&(dcdvalid)
else if ((clear_pipeline)||(~opvalid))
op_break <= 1'b0;
r_op_break <= 1'b0;
assign op_break = r_op_break;
`else
assign op_break = dcd_break;
`endif
 
`ifdef OPT_PIPELINED
generate
935,13 → 956,14
`else
op_illegal <= (dcdvalid)&&((dcd_illegal)||(dcd_lock));
`endif
`endif
else if(alu_ce)
op_illegal <= 1'b0;
`endif
 
// No generate on EARLY_BRANCHING here, since if EARLY_BRANCHING is not
// set, dcd_early_branch will simply be a wire connected to zero and
// this logic should just optimize.
`ifdef OPT_PIPELINED
always @(posedge i_clk)
if (op_ce)
begin
949,22 → 971,47
&&(~dcd_early_branch)&&(~dcd_illegal);
opR_wr <= (dcdR_wr)&&(~dcd_early_branch)&&(~dcd_illegal);
end
`else
always @(posedge i_clk)
begin
opF_wr <= (dcdF_wr)&&((~dcdR_cc)||(~dcdR_wr))
&&(~dcd_early_branch)&&(~dcd_illegal);
opR_wr <= (dcdR_wr)&&(~dcd_early_branch)&&(~dcd_illegal);
end
`endif
 
`ifdef OPT_PIPELINED
reg [3:0] r_opn;
reg [4:0] r_opR;
reg r_opR_cc;
reg r_op_gie;
always @(posedge i_clk)
if (op_change_data_ce)
begin
opn <= dcdOp; // Which ALU operation?
r_opn <= dcdOp; // Which ALU operation?
// opM <= dcdM; // Is this a memory operation?
// What register will these results be written into?
opR <= dcdR;
opR_cc <= (dcdR_cc)&&(dcdR_wr)&&(dcdR[4]==dcd_gie);
r_opR <= dcdR;
r_opR_cc <= (dcdR_cc)&&(dcdR_wr)&&(dcdR[4]==dcd_gie);
// User level (1), vs supervisor (0)/interrupts disabled
op_gie <= dcd_gie;
r_op_gie <= dcd_gie;
 
 
//
op_pc <= (dcd_early_branch)?dcd_branch_pc:dcd_pc;
end
assign opn = r_opn;
assign opR = r_opR;
assign op_gie = r_op_gie;
assign opR_cc = r_opR_cc;
`else
assign opn = dcdOp;
assign opR = dcdR;
assign op_gie = dcd_gie;
// With no pipelining, there is no early branching. We keep it
always @(posedge i_clk)
op_pc <= (dcd_early_branch)?dcd_branch_pc:dcd_pc;
`endif
assign opFl = (op_gie)?(w_uflags):(w_iflags);
 
`ifdef OPT_VLIW
1166,11 → 1213,19
assign alu_phase = 1'b0;
`endif
 
`ifdef OPT_PIPELINED
always @(posedge i_clk)
if (adf_ce_unconditional)
alu_reg <= opR;
else if ((i_halt)&&(i_dbg_we))
alu_reg <= i_dbg_reg;
`else
always @(posedge i_clk)
if ((i_halt)&&(i_dbg_we))
alu_reg <= i_dbg_reg;
else
alu_reg <= opR;
`endif
 
//
// DEBUG Register write access starts here
1182,14 → 1237,25
reg [31:0] dbg_val;
always @(posedge i_clk)
dbg_val <= i_dbg_data;
`ifdef OPT_PIPELINED
reg r_alu_gie;
 
always @(posedge i_clk)
if ((adf_ce_unconditional)||(mem_ce))
alu_gie <= op_gie;
r_alu_gie <= op_gie;
assign alu_gie = r_alu_gie;
 
reg [(AW-1):0] r_alu_pc;
always @(posedge i_clk)
if ((adf_ce_unconditional)
||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)
&&(~mem_stalled)))
alu_pc <= op_pc;
r_alu_pc <= op_pc;
assign alu_pc = r_alu_pc;
`else
assign alu_gie = op_gie;
assign alu_pc = op_pc;
`endif
 
`ifdef OPT_ILLEGAL_INSTRUCTION
reg r_alu_illegal;
1395,14 → 1461,21
else if ((wr_reg_ce)&&(wr_write_scc))
break_en <= wr_spreg_vl[`CPU_BREAK_BIT];
 
initial break_pending = 1'b0;
`ifdef OPT_PIPELINED
reg r_break_pending;
 
initial r_break_pending = 1'b0;
always @(posedge i_clk)
if ((i_rst)||(clear_pipeline)||(~opvalid))
break_pending <= 1'b0;
r_break_pending <= 1'b0;
else if (op_break)
break_pending <= (~alu_busy)&&(~div_busy)&&(~fpu_busy)&&(~mem_busy);
r_break_pending <= (~alu_busy)&&(~div_busy)&&(~fpu_busy)&&(~mem_busy);
else
break_pending <= 1'b0;
r_break_pending <= 1'b0;
assign break_pending = r_break_pending;
`else
assign break_pending = op_break;
`endif
 
 
assign o_break = ((break_en)||(~op_gie))&&(break_pending)
1737,6 → 1810,7
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
begin
o_dbg_reg[14:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
o_dbg_reg[15] <= 1'b0;
o_dbg_reg[31:23] <= w_cpu_info;
o_dbg_reg[`CPU_GIE_BIT] <= gie;
end
1750,6 → 1824,7
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
begin
o_dbg_reg[14:0] <= (i_dbg_reg[4])?w_uflags:w_iflags;
o_dbg_reg[15] <= 1'b0;
o_dbg_reg[31:23] <= w_cpu_info;
o_dbg_reg[`CPU_GIE_BIT] <= gie;
end
1759,6 → 1834,7
always @(posedge i_clk)
o_dbg_cc <= { o_break, bus_err, gie, sleep };
 
`ifdef OPT_PIPELINED
always @(posedge i_clk)
r_halted <= (i_halt)&&(
// To be halted, any long lasting instruction must
1769,6 → 1845,10
&&((opvalid)||(i_rst)||(dcd_illegal))
// Decode stage must be either valid, in reset, or ill
&&((dcdvalid)||(i_rst)||(pf_illegal)));
`else
always @(posedge i_clk)
r_halted <= (i_halt)&&((opvalid)||(i_rst));
`endif
assign o_dbg_stall = ~r_halted;
 
//
1782,85 → 1862,41
assign o_i_count = (alu_pc_valid)&&(~clear_pipeline);
 
`ifdef DEBUG_SCOPE
reg [31:0] r_stack;
// CLRPIP: If clear_pipeline, produce address ... can be 28 bits
// DATWR: If write value, produce 4-bits of register ID, 27 bits of value
// STALL: If neither, produce pipeline stall information
// ADDR: If bus is valid, no ack, return the bus address
reg debug_trigger;
initial debug_trigger = 1'b0;
always @(posedge i_clk)
if ((wr_reg_ce)&&(wr_reg_id == 5'h0d))
r_stack <= wr_gpreg_vl;
reg r_stack_pre, r_stack_post;
always @(posedge i_clk)
r_stack_pre <= (r_stack == 32'h03fff);
always @(posedge i_clk)
r_stack_post <= (r_stack == 32'h03eeb);
debug_trigger <= (!i_halt)&&(o_break);
 
wire [31:0] debug_flags;
assign debug_flags = { debug_trigger, 3'b101,
master_ce, i_halt, o_break, sleep,
gie, ibus_err_flag, trap, ill_err_i,
r_clear_icache, pf_valid, pf_illegal, dcd_ce,
dcdvalid, dcd_stalled, op_ce, opvalid,
op_pipe, alu_ce, alu_busy, alu_wr,
alu_illegal, alF_wr, mem_ce, mem_we,
mem_busy, mem_pipe_stalled, (new_pc), (dcd_early_branch) };
always @(posedge i_clk)
o_debug <= {
/*
o_break, i_wb_err, pf_pc[1:0],
flags,
pf_valid, dcdvalid, opvalid, alu_valid, mem_valid,
op_ce, alu_ce, mem_ce,
//
master_ce, opvalid_alu, opvalid_mem,
//
alu_stall, mem_busy, op_pipe, mem_pipe_stalled,
mem_we,
// ((opvalid_alu)&&(alu_stall))
// ||((opvalid_mem)&&(~op_pipe)&&(mem_busy))
// ||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled)));
// opA[23:20], opA[3:0],
gie, sleep, wr_reg_ce, wr_gpreg_vl[4:0]
*/
/*
i_rst, master_ce, (new_pc),
((dcd_early_branch)&&(dcdvalid)),
pf_valid, pf_illegal,
op_ce, dcd_ce, dcdvalid, dcd_stalled,
pf_cyc, pf_stb, pf_we, pf_ack, pf_stall, pf_err,
pf_pc[7:0], pf_addr[7:0]
*/
 
(i_wb_err)||(r_stack_post), (gie)||(r_stack_pre), (alu_illegal)||(r_stack_post),
(new_pc)||((dcd_early_branch)&&(~clear_pipeline)),
mem_busy,
(mem_busy)?{ (o_wb_gbl_stb|o_wb_lcl_stb), o_wb_we,
o_wb_addr[8:0] }
: { instruction[31:21] },
pf_valid, (pf_valid) ? alu_pc[14:0]
:{ pf_cyc, pf_stb, pf_pc[12:0] }
 
/*
i_wb_err, gie, new_pc, dcd_early_branch, // 4
pf_valid, pf_cyc, pf_stb, instruction_pc[0], // 4
instruction[30:27], // 4
dcd_gie, mem_busy, o_wb_gbl_cyc, o_wb_gbl_stb, // 4
dcdvalid,
((dcd_early_branch)&&(~clear_pipeline)) // 15
? dcd_branch_pc[14:0]:pf_pc[14:0]
*/
};
begin
if ((i_halt)||(!master_ce)||(debug_trigger)||(o_break))
o_debug <= debug_flags;
else if ((mem_valid)||((~clear_pipeline)&&(~alu_illegal)
&&(((alu_wr)&&(alu_valid))
||(div_valid)||(fpu_valid))))
o_debug <= { debug_trigger, 1'b0, wr_reg_id[3:0], wr_gpreg_vl[25:0]};
else if (clear_pipeline)
o_debug <= { debug_trigger, 3'b100, pf_pc[27:0] };
else if ((o_wb_gbl_stb)|(o_wb_lcl_stb))
o_debug <= {debug_trigger, 2'b11, o_wb_gbl_stb, o_wb_we,
(o_wb_we)?o_wb_data[26:0] : o_wb_addr[26:0] };
else
o_debug <= debug_flags;
end
`endif
 
/*
always @(posedge i_clk)
o_debug <= {
// External control interaction (4b)
i_halt, i_rst, i_clear_cache, o_break,
// Bus interaction (8b)
pf_cyc,(o_wb_gbl_cyc|o_wb_lcl_cyc), o_wb_gbl_stb, o_wb_lcl_stb,
o_wb_we, i_wb_ack, i_wb_stall, i_wb_err,
// PC control (4b)
gie, new_pc, dcd_early_branch, 1'b0,
// Our list of pipeline stage values (8b)
pf_valid, pf_illegal, dcdvalid, opvalid, alu_valid, mem_valid,
alu_pc_valid, mem_pc_valid,
// Our list of circuit enables ... (8b)
(new_pc)||((dcd_early_branch)&&(~clear_pipeline)),
dcd_ce, op_ce, alu_ce, mem_ce, wr_reg_ce, wr_flags_ce,
1'b0,
// Useful PC values (64b)
((dcd_early_branch)&&(~clear_pipeline))
? dcd_branch_pc[15:0]:pf_pc[15:0],
(gie)?upc[15:0]:ipc[15:0], instruction_pc[15:0], instruction[31:16] };
*/
endmodule
/enetctrl.v
47,7 → 47,8
module enetctrl(i_clk, i_rst,
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
o_wb_ack, o_wb_stall, o_wb_data,
o_mdclk, o_mdio, i_mdio, o_mdwe);
o_mdclk, o_mdio, i_mdio, o_mdwe,
o_debug);
parameter CLKBITS=3; // = 3 for 200MHz source clock, 2 for 100 MHz
input i_clk, i_rst;
input i_wb_cyc, i_wb_stb, i_wb_we;
60,6 → 61,8
output wire o_mdclk;
output reg o_mdio, o_mdwe;
//
output wire [31:0] o_debug;
//
parameter PHYADDR = 5'h01;
 
 
83,7 → 86,7
reg rclk, zclk;
initial zclk = 0;
always @(posedge i_clk)
zclk <= &clk_counter;
zclk <= (&clk_counter[(CLKBITS-1):1])&&(!clk_counter[0]);
initial rclk = 0;
always @(posedge i_clk)
rclk <= (~clk_counter[(CLKBITS-1)])&&(&clk_counter[(CLKBITS-2):0]);
90,6 → 93,7
 
// Step 3: Read from our input port
// Note: I read on the falling edge, he changes on the rising edge
reg in_idle;
always @(posedge i_clk)
if (zclk)
read_reg <= { read_reg[14:0], i_mdio };
107,7 → 111,6
if (zclk)
o_mdio <= write_reg[15];
 
reg in_idle;
initial in_idle = 1'b0;
always @(posedge i_clk)
in_idle <= (ctrl_state == `ECTRL_IDLE);
145,7 → 148,7
always @(posedge i_clk)
begin
o_wb_ack <= 1'b0;
if ((zclk)&&(~zreg_pos))
if ((zclk)&&(!zreg_pos))
reg_pos <= reg_pos - 1;
if (zclk)
write_reg <= { write_reg[14:0], 1'b1 };
165,12 → 168,16
o_mdwe <= 1'b1; // Write
write_reg <= { 4'he, PHYADDR, r_addr, 2'b11 };
if (write_pending)
begin
write_reg[15:12] <= { 4'h5 };
else if (read_pending)
write_reg[0] <= 1'b0;
end else if (read_pending)
write_reg[15:12] <= { 4'h6 };
if (read_pending || write_pending)
if (!zclk)
write_reg[15] <= 1'b1;
reg_pos <= 6'h0f;
if ((zclk)&&(read_pending || write_pending))
begin
reg_pos <= 6'h0f;
ctrl_state <= `ECTRL_ADDRESS;
end end
`ECTRL_ADDRESS: begin
206,4 → 213,12
endcase
end
 
assign o_debug = {
o_wb_stall,i_wb_stb,i_wb_we, i_wb_addr, // 8 bits
o_wb_ack, rclk, o_wb_data[5:0], // 8 bits
zreg_pos, zclk, reg_pos, // 8 bits
read_pending, ctrl_state, // 4 bits
o_mdclk, o_mdwe, o_mdio, i_mdio // 4 bits
};
 
endmodule
/enetpackets.v
0,0 → 1,757
////////////////////////////////////////////////////////////////////////////////
//
// Filename: enetpackets.v
//
// Project: OpenArty, an entirely open SoC based upon the Arty platform
//
// Purpose: To communicate between the Ethernet PHY, and thus to coordinate
// (and direct/arrange for) the transmission, and receiption, of
// packets via the Ethernet interface.
//
//
// Using this interface requires four registers to be properly configured.
// These are the receive and transmit control registers, as well as the
// hardware MAC register(s).
//
//
// To use the interface, after the system has been alive for a full
// second, drop the reset line. Do this by writing to the transmit
// register a value with zero length, zero command, and the RESET bit as
// zero.
//
// This interface is big endian. Therefore, the most significant byte
// in each word will be transmitted first. If the interface references
// a number of octets less than a multiple of four, the least significant
// octets in the last word will not be transmitted/were not received.
//
// To transmit,
// 1. set the source MAC address in the two mac registers. These
// are persistent across packets, so once set (whether for
// transmit or receive) they need not be set again.
// 2. Fill the packet buffer with your packet. In general, the
// first 32-bit word must contain the hardware MAC address
// of your destination, spilling into the 16-bits of the
// next word. The bottom 16-bits of that second word
// must also contain the EtherType (0x0800 for IP,
// 0x0806 for ARP, etc.) The third word will begin your
// user data.
// 3. Write a 0x4000 plus the number of bytes in your buffer to
// the transmit command register. If your packet is less
// than 64 bytes, it will automatically be paddedd to 64
// bytes before being sent.
// 4. Once complete, the controller will raise an interrupt
// line to note that the interface is idle.
// OPTIONS:
// You can turn off the internal insertion of the hardware source
// MAC by turning the respective bit on in the transmit command
// register. If you do this, half of the second word and all the
// third word must contain the hardware MAC. The third word must
// contain the EtherType, both in the top and bottom sixteen bits.
// The Fourth word will begin user data.
//
// You can also turn off the automatic insertion of the FCS, or
// ethernet CRC. Doing this means that you will need to both
// guarantee for yourself that the packet has a minimum of 64
// bytes in length, and that the last four bytes contain the
// CRC.
//
// To Receive:
// The receiver is always on. Receiving is really just a matter
// of pulling the received packet from the interface, and resetting
// the interface for the next packet.
//
// If the VALID bit is set, the receive interface has a valid
// packet within it. Write a zero to this bit to reset the
// interface to accept the next packet.
//
// If a packet with a CRC error is received, the CRC error bit
// will be set. Likewise if a packet has been missed, usually
// because the buffer was full when it started, the miss bit
// will be set. Finally, if an error occurrs while receiving
// a packet, the error bit will be set. These bits may be cleared
// by writing a one to each of them--something that may be done
// when clearing the interface for the next packet.
// OPTIONS:
// The same options that apply to the transmitter apply to the
// receiver:
//
// HWMAC. If the hardware MAC is turned on, the receiver will
// only accept packets to either 1) our network address, or 2)
// a broadcast address. Further, the first two words will be
// adjusted to contain the source MAC and the EtherType, so that
// the user information begins on the third word. If this feature
// is turned off, all packets will be received, and the first
// three words will contain the destination and then source
// MAC. The fourth word will contain the EtherType in the lowest,
// 16 bits, meaning user data will begin on the fifth word.
//
// HWCRC. If the HWCRC is turned on, the receiver will only
// detect packets that pass their CRC check. Further, the packet
// length (always in octets) will not include the CRC. However,
// the CRC will still be left/written to packet memory either way.
//
// Registers:
// 0 Receiver control
// 13'h0 |CRCerr|MISS|ERR|BUSY|VALID |14-bit length (in octets)|
//
// 1 Transmitter control
// 14'h0 |NET_RST|SW-MAC-CHK|SW-CRCn|BUSY/CMD | 14 bit length(in octets)|
//
// 2 // MAC address (high) ??
// 3 // MAC address (low) ??
// 4 Number of receive packets missed (buffer was full)
// 5 Number of receive packets ending in error
// 6 Number of receive packets with invalid CRCs
// 7 (Number of transmit collisions ??)
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
// `define RX_SYNCHRONOUS_WITH_WB_CLK
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
`define RXCLK i_wb_clk
`else
`define RXCLK i_net_rx_clk
`endif
// `define TX_SYNCHRONOUS_WITH_WB_CLK
`ifdef TX_SYNCHRONOUS_WITH_WB_CLK
`define TXCLK i_wb_clk
`else
`define TXCLK i_net_tx_clk
`endif
module enetpackets(i_wb_clk, i_reset,
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
o_wb_ack, o_wb_stall, o_wb_data,
//
o_net_reset_n,
i_net_rx_clk, i_net_col, i_net_crs, i_net_dv, i_net_rxd, i_net_rxerr,
i_net_tx_clk, o_net_tx_en, o_net_txd,
//
o_rx_int, o_tx_int,
//
o_debug
);
parameter MEMORY_ADDRESS_WIDTH = 12; // Log_2 octet width:11..14
localparam MAW =((MEMORY_ADDRESS_WIDTH>14)? 14: // width of words
((MEMORY_ADDRESS_WIDTH<11)? 11:MEMORY_ADDRESS_WIDTH))-2;
input i_wb_clk, i_reset;
//
input i_wb_cyc, i_wb_stb, i_wb_we;
input [(MAW+1):0] i_wb_addr; // 1-bit for ctrl/data, 1 for tx/rx
input [31:0] i_wb_data;
//
output reg o_wb_ack;
output wire o_wb_stall;
output reg [31:0] o_wb_data;
//
output reg o_net_reset_n;
//
input i_net_rx_clk, i_net_col, i_net_crs, i_net_dv;
input [3:0] i_net_rxd;
input i_net_rxerr;
//
input i_net_tx_clk;
output wire o_net_tx_en;
output wire [3:0] o_net_txd;
//
output wire o_rx_int, o_tx_int;
//
output wire [31:0] o_debug;
 
reg wr_ctrl;
reg [2:0] wr_addr;
reg [31:0] wr_data;
always @(posedge i_wb_clk)
begin
wr_ctrl<=((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b00));
wr_addr <= i_wb_addr[2:0];
wr_data <= i_wb_data;
end
 
reg [31:0] txmem [0:((1<<MAW)-1)];
reg [31:0] rxmem [0:((1<<MAW)-1)];
 
reg [(MAW+1):0] tx_len;
 
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
wire [(MAW+1):0] rx_len;
`else
(* ASYNC_REG = "TRUE" *) reg [(MAW+1):0] rx_len;
`endif
 
reg tx_cmd, tx_cancel;
`ifdef TX_SYNCHRONOUS_WITH_WB_CLK
wire tx_busy, tx_complete;
`else
reg tx_busy, tx_complete;
`endif
reg config_hw_crc, config_hw_mac;
reg rx_crcerr, rx_err, rx_miss, rx_clear;
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
wire rx_valid, rx_busy;
`else
reg rx_valid, rx_busy;
`endif
reg rx_wb_valid, pre_ack, pre_cmd, tx_nzero_cmd;
reg [4:0] caseaddr;
reg [31:0] rx_wb_data, tx_wb_data;
reg rx_err_stb, rx_miss_stb, rx_crc_stb;
 
reg [47:0] hw_mac;
reg p_rx_clear;
reg [7:0] clear_pipe;
 
initial config_hw_crc = 0;
initial config_hw_mac = 0;
initial o_net_reset_n = 1'b0;
initial tx_cmd = 1'b0;
initial tx_cancel = 1'b0;
initial rx_crcerr = 1'b0;
initial rx_err = 1'b0;
initial rx_miss = 1'b0;
initial rx_clear = 1'b0;
always @(posedge i_wb_clk)
begin
// if (i_wb_addr[(MAW+1):MAW] == 2'b10)
// Writes to rx memory not allowed here
if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11))
txmem[i_wb_addr[(MAW-1):0]] <= i_wb_data;
 
// Set the err bits on these conditions (filled out below)
if (rx_err_stb)
rx_err <= 1'b1;
if (rx_miss_stb)
rx_miss <= 1'b1;
if (rx_crc_stb)
rx_crcerr <= 1'b1;
 
if ((wr_ctrl)&&(wr_addr==3'b000))
begin // RX command register
rx_crcerr<= (!wr_data[18])&&(!rx_crcerr);
rx_err <= (!wr_data[17])&&(!rx_err);
rx_miss <= (!wr_data[16])&&(!rx_miss);
// busy bit cannot be written to
rx_clear <= rx_clear || (wr_data[14]);
// Length bits are cleared when invalid
end else if (!rx_valid)
rx_clear <= 1'b0;
 
clear_pipe <= { clear_pipe[6:0], rx_clear };
p_rx_clear <= |clear_pipe;
 
if ((tx_busy)||(tx_cancel))
tx_cmd <= 1'b0;
if (!tx_busy)
tx_cancel <= 1'b0;
pre_cmd <= 1'b0;
if ((wr_ctrl)&&(wr_addr==3'b001))
begin // TX command register
 
// Reset bit must be held down to be valid
o_net_reset_n <= (!wr_data[17]);
config_hw_mac <= (!wr_data[16]);
config_hw_crc <= (!wr_data[15]);
pre_cmd <= (wr_data[14]);
tx_cancel <= (tx_busy)&&(!wr_data[14]);
// 14'h0 | SW-CRCn |NET-RST|BUSY/CMD | 14 bit length(in octets)|
tx_len <= wr_data[(MAW+1):0];
end
tx_nzero_cmd <= ((pre_cmd)&&(tx_len != 0));
if (tx_nzero_cmd)
tx_cmd <= 1'b1;
if (!o_net_reset_n)
tx_cancel <= 1'b1;
if (!o_net_reset_n)
tx_cmd <= 1'b0;
 
if ((wr_ctrl)&&(wr_addr==3'b010))
hw_mac[47:32] <= wr_data[15:0];
if ((wr_ctrl)&&(wr_addr==3'b011))
hw_mac[31:0] <= wr_data[31:0];
end
 
wire [31:0] w_tx_ctrl;
wire [31:0] w_rx_ctrl;
wire [3:0] w_maw;
 
assign w_maw = MAW+2; // Number of bits in the packet length field
assign w_rx_ctrl = { 4'h0, w_maw, {(24-19){1'b0}}, rx_crcerr, rx_err,
rx_miss, rx_busy, (rx_valid)&&(!rx_clear),
{(14-MAW-2){1'b0}}, rx_len };
 
assign w_tx_ctrl = { 4'h0, w_maw, {(24-18){1'b0}},
!o_net_reset_n,!config_hw_mac,
!config_hw_crc, tx_busy,
{(14-MAW-2){1'b0}}, tx_len };
 
reg [31:0] counter_rx_miss, counter_rx_err, counter_rx_crc;
initial counter_rx_miss = 32'h00;
initial counter_rx_err = 32'h00;
initial counter_rx_crc = 32'h00;
 
// Reads from the bus ... always done, regardless of i_wb_we
always @(posedge i_wb_clk)
begin
rx_wb_data <= rxmem[i_wb_addr[(MAW-1):0]];
rx_wb_valid <= (i_wb_addr[(MAW-1):0] <= { rx_len[(MAW+1):2] });
tx_wb_data <= txmem[i_wb_addr[(MAW-1):0]];
pre_ack <= i_wb_stb;
caseaddr <= {i_wb_addr[(MAW+1):MAW], i_wb_addr[2:0] };
 
casez(caseaddr)
5'h00: o_wb_data <= w_rx_ctrl;
5'h01: o_wb_data <= w_tx_ctrl;
5'h02: o_wb_data <= {16'h00, hw_mac[47:32] };
5'h03: o_wb_data <= hw_mac[31:0];
5'h04: o_wb_data <= counter_rx_miss;
5'h05: o_wb_data <= counter_rx_err;
5'h06: o_wb_data <= counter_rx_crc;
5'h07: o_wb_data <= 32'h00;
5'b10???: o_wb_data <= (rx_wb_valid)?rx_wb_data:32'h00;
5'b11???: o_wb_data <= tx_wb_data;
default: o_wb_data <= 32'h00;
endcase
o_wb_ack <= pre_ack;
end
 
/////////////////////////////////////
//
//
//
// Transmitter code
//
//
//
/////////////////////////////////////
`ifdef TX_SYNCHRONOUS_WITH_WB_CLK
reg [(MAW+1):0] n_tx_len;
wire n_tx_cmd, n_tx_cancel;
assign n_tx_cmd = tx_cmd;
assign n_tx_cancel = tx_cancel;
`else
(* ASYNC_REG = "TRUE" *) reg [(MAW+1):0] n_tx_len;
(* ASYNC_REG = "TRUE" *) reg r_tx_cmd, r_tx_cancel;
reg n_tx_cmd, n_tx_cancel;
always @(posedge `TXCLK)
begin
r_tx_cmd <= tx_cmd;
r_tx_cancel <= tx_cancel;
 
n_tx_cmd <= r_tx_cmd;
n_tx_cancel <= r_tx_cancel;
end
`endif
 
`ifdef TX_SYNCHRONOUS_WITH_WB_CLK
reg last_tx_clk, tx_clk_stb;
(* ASYNC_REG = "TRUE" *) reg r_tx_clk;
always @(posedge i_wb_clk)
r_tx_clk <= i_net_tx_clk;
always @(posedge i_wb_clk)
last_tx_clk <= r_tx_clk;
always @(posedge i_wb_clk)
tx_clk_stb <= (r_tx_clk)&&(!last_tx_clk);
`else
wire tx_clk_stb, last_tx_clk;
 
assign tx_clk_stb = 1'b1;
assign last_tx_clk= 1'b0;
`endif
 
wire [(MAW+2):0] rd_tx_addr;
assign rd_tx_addr = (n_tx_addr+8);
 
reg [(MAW+2):0] n_tx_addr;
reg [31:0] n_tx_data, n_next_tx_data;
reg n_tx_complete;
`ifdef TX_SYNCHRONOUSH_WITH_WB
reg n_tx_busy, n_tx_config_hw_mac, n_tx_config_hw_crc;
`else
(* ASYNC_REG = "TRUE" *) reg n_tx_busy,
n_tx_config_hw_mac, n_tx_config_hw_crc;
`endif
(* ASYNC_REG = "TRUE" *) reg r_tx_crs;
reg n_tx_crs;
always @(posedge `TXCLK)
begin
r_tx_crs <= i_net_crs;
n_tx_crs <= r_tx_crs;
end
 
wire [31:0] n_remap_tx_data;
assign n_remap_tx_data[31:28] = n_next_tx_data[27:24];
assign n_remap_tx_data[27:24] = n_next_tx_data[31:28];
assign n_remap_tx_data[23:20] = n_next_tx_data[19:16];
assign n_remap_tx_data[19:16] = n_next_tx_data[23:20];
assign n_remap_tx_data[15:12] = n_next_tx_data[11: 8];
assign n_remap_tx_data[11: 8] = n_next_tx_data[15:12];
assign n_remap_tx_data[ 7: 4] = n_next_tx_data[ 3: 0];
assign n_remap_tx_data[ 3: 0] = n_next_tx_data[ 7: 4];
 
reg r_txd_en;
reg [3:0] r_txd;
initial r_txd_en = 1'b0;
 
initial n_tx_busy = 1'b0;
initial n_tx_complete = 1'b0;
always @(posedge `TXCLK)
begin
if (tx_clk_stb)
begin
// While this operation doesn't strictly need to
// operate *only* if tx_clk_stb is true, by doing so
// our code stays compatible with both synchronous
// to wishbone and synchronous to tx clk options.
n_next_tx_data <= txmem[(!n_tx_busy)?0:rd_tx_addr[(MAW+2):3]];
end
 
 
if (n_tx_cancel)
n_tx_busy <= 1'b0;
else if (!n_tx_busy)
n_tx_busy <= (n_tx_cmd)&&(!i_net_crs);
else if (n_tx_addr >= { n_tx_len,1'b0 })
n_tx_busy <= 1'b0;
 
if (!n_tx_busy)
begin
n_tx_addr <= {{(MAW+2){1'b0}},1'b1};
n_tx_data <= { n_remap_tx_data[27:0], 4'h0 };
if (n_tx_complete)
n_tx_complete <= (!n_tx_cmd);
r_txd_en <= (!n_tx_complete)&&(n_tx_cmd)&&(!i_net_crs);
r_txd <= n_remap_tx_data[31:28];
n_tx_config_hw_mac <= config_hw_mac;
n_tx_config_hw_crc <= config_hw_crc;
n_tx_len <= tx_len;
end else if (!r_txd_en)
r_txd_en <= (!n_tx_crs);
else if (tx_clk_stb) begin
n_tx_addr <= n_tx_addr + 1'b1;
r_txd <= n_tx_data[31:28];
if (n_tx_addr[2:0] == 3'h7)
n_tx_data <= n_remap_tx_data;
else
n_tx_data <= { n_tx_data[27:0], 4'h0 };
if (n_tx_addr >= { n_tx_len,1'b0 })
n_tx_complete <= 1'b1;
r_txd_en <= (n_tx_addr < { n_tx_len, 1'b0 });
end
end
 
wire n_tx_config_hw_preamble;
assign n_tx_config_hw_preamble = 1'b1;
 
wire w_macen, w_paden, w_txcrcen;
wire [3:0] w_macd, w_padd, w_txcrcd;
 
`ifndef TX_BYPASS_HW_MAC
addemac txmaci(`TXCLK, tx_clk_stb, n_tx_config_hw_mac, n_tx_cancel,
hw_mac, r_txd_en, r_txd, w_macen, w_macd);
`else
assign w_macen = r_txd_en;
assign w_macd = r_txd;
`endif
 
`ifndef TX_BYPASS_PADDING
addepad txpadi(`TXCLK, tx_clk_stb, 1'b1, n_tx_cancel,
w_macen, w_macd, w_paden, w_padd);
`else
assign w_paden = w_macen;
assign w_padd = w_macd;
`endif
 
`ifndef TX_BYPASS_HW_CRC
addecrc txcrci(`TXCLK, tx_clk_stb, n_tx_config_hw_crc, n_tx_cancel,
w_paden, w_padd, w_txcrcen, w_txcrcd);
`else
assign w_txcrcen = w_macen;
assign w_txcrcd = w_macd;
`endif
 
addepreamble txprei(`TXCLK, tx_clk_stb, n_tx_config_hw_preamble, n_tx_cancel,
w_txcrcen, w_txcrcd, o_net_tx_en, o_net_txd);
 
`ifdef TX_SYNCRONOUS_WITH_WB_CLK
assign tx_busy = n_tx_busy;
assign tx_complete = n_tx_complete;
`else
(* ASYNC_REG = "TRUE" *) reg r_tx_busy, r_tx_complete;
always @(posedge i_wb_clk)
begin
r_tx_busy <= (n_tx_busy || o_net_tx_en || w_txcrcen || w_macen || w_paden);
tx_busy <= r_tx_busy;
 
r_tx_complete <= n_tx_complete;
tx_busy <= r_tx_busy;
end
`endif
 
 
 
 
 
/////////////////////////////////////
//
//
//
// Receiver code
//
//
//
/////////////////////////////////////
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
reg last_rx_clk, rx_clk_stb;
(* ASYNC_REG="TRUE" *) reg r_rx_clk;
always @(posedge i_wb_clk)
r_rx_clk <= i_net_rx_clk;
always @(posedge i_wb_clk)
last_rx_clk <= r_rx_clk;
always @(posedge i_wb_clk)
rx_clk_stb <= (r_rx_clk)&&(!last_rx_clk);
 
`else
wire rx_clk_stb, last_rx_clk;
assign rx_clk_stb = 1'b1;
assign last_rx_clk = 1'b0;
`endif
 
 
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
wire n_rx_clear;
reg n_rx_config_hw_mac, n_rx_config_hw_crc;
assign n_rx_clear = rx_clear;
`else
(* ASYNC_REG = "TRUE" *) reg n_rx_config_hw_mac, n_rx_config_hw_crc;
(* ASYNC_REG = "TRUE" *) reg r_rx_clear;
reg n_rx_clear;
always @(posedge `RXCLK)
begin
r_rx_clear <= (p_rx_clear)||(!o_net_reset_n);
n_rx_clear <= r_rx_clear;
end
`endif
 
 
reg n_rx_net_err;
wire w_npre, w_rxmin, w_rxcrc, w_rxmac, w_rxip;
wire [3:0] w_npred, w_rxmind, w_rxcrcd, w_rxmacd, w_rxipd;
wire w_minerr, w_rxcrcerr, w_macerr, w_broadcast, w_iperr;
`ifndef RX_BYPASS_HW_PREAMBLE
rxepreambl rxprei(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
i_net_dv, i_net_rxd, w_npre, w_npred);
`else
assign w_npre = i_net_dv;
assign w_npred = i_net_rxerr;
`endif
 
`ifdef RX_HW_MINLENGTH
// Insist on a minimum of 64-byte packets
rxeminlen rxmini(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
w_npre, w_npred, w_rxmin, w_rxmind, w_minerr);
`else
assign w_rxmin = w_npre;
assign w_rxmind= w_npred;
assign w_minerr= 1'b0;
`endif
 
`ifndef RX_BYPASS_HW_CRC
rxecrc rxcrci(`RXCLK, rx_clk_stb, n_rx_config_hw_crc, (n_rx_net_err),
w_rxmin, w_rxmind, w_rxcrc, w_rxcrcd, w_rxcrcerr);
`else
assign w_rxcrc = w_rxmin;
assign w_rxcrcd = w_rxmind;
assign w_rxcrcerr= 1'b0;
`endif
 
`ifndef RX_BYPASS_HW_RMMAC
rxehwmac rxmaci(`RXCLK, rx_clk_stb, n_rx_config_hw_mac, (n_rx_net_err), hw_mac,
w_rxcrc, w_rxcrcd,
w_rxmac, w_rxmacd,
w_macerr, w_broadcast);
`else
assign w_rxmac = w_rxcrc;
assign w_rxmacd = w_rxcrcd;
`endif
 
`ifdef RX_HW_IPCHECK
// Check: if this packet is an IP packet, is the IP header checksum
// valid?
`else
assign w_rxip = w_rxmac;
assign w_rxipd = w_rxmacd;
assign w_iperr = 1'b0;
`endif
 
wire w_rxwr;
wire [(MAW-1):0] w_rxaddr;
wire [31:0] w_rxdata;
wire [(MAW+1):0] w_rxlen;
 
rxewrite #(MAW) rxememi(`RXCLK, 1'b1, (n_rx_net_err), w_rxip, w_rxipd,
w_rxwr, w_rxaddr, w_rxdata, w_rxlen);
 
reg last_rxwr, n_rx_valid, n_rxmiss, n_eop, n_rx_busy, n_rx_crcerr,
n_rx_err, n_rx_broadcast, n_rx_miss;
reg [(MAW+1):0] n_rx_len;
 
initial n_rx_valid = 1'b0;
initial n_rx_clear = 1'b1;
initial n_rx_miss = 1'b0;
always @(posedge `RXCLK)
begin
if ((w_rxwr)&&(!n_rx_valid))
rxmem[w_rxaddr] <= w_rxdata;
 
// n_rx_net_err goes true as soon as an error is detected,
// and stays true as long as valid data is coming in
n_rx_net_err <= (i_net_dv)&&((i_net_rxerr)||(i_net_col)
||(w_minerr)||(w_macerr)||(w_rxcrcerr)
||(n_rx_net_err)
||((w_rxwr)&&(n_rx_valid)));
 
last_rxwr <= w_rxwr;
n_eop <= (!w_rxwr)&&(last_rxwr)&&(!n_rx_net_err);
 
n_rx_busy <= (!n_rx_net_err)&&((i_net_dv)||(w_npre)||(w_rxmin)
||(w_rxcrc)||(w_rxmac)||(w_rxip)||(w_rxwr));
 
// Oops ... we missed a packet
n_rx_miss <= (n_rx_valid)&&(w_rxwr)||
((n_rx_miss)&&(!n_rx_clear));
 
n_rx_crcerr <= ((w_rxcrcerr)&&(!n_rx_net_err))
||((n_rx_crcerr)&&(!n_rx_clear));
 
n_rx_err <= ((n_rx_err)&&(!n_rx_clear))
||((i_net_rxerr)||(i_net_col)||(w_minerr));
 
n_rx_broadcast <= (w_broadcast)||((n_rx_broadcast)&&(!n_rx_clear));
 
if (n_rx_clear)
begin
n_rx_valid <= 1'b0;
n_rx_len <= 0;
end else if (n_eop)
begin
n_rx_valid <= 1'b1;
n_rx_len <= w_rxlen - ((n_rx_config_hw_crc)?{{(MAW-1){1'b0}},3'h4}:0);
end
// else n_rx_valid = n_rx_valid;
 
if ((!i_net_dv)||(n_rx_clear))
begin
n_rx_config_hw_mac <= config_hw_mac;
n_rx_config_hw_crc <= config_hw_crc;
end
end
 
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
assign rx_busy = n_rx_busy;
assign rx_valid = n_rx_valid;
assign rx_len = n_rx_len;
`else
reg r_rx_busy, r_rx_valid;
always @(posedge i_wb_clk)
begin
r_rx_valid <= n_rx_valid;
rx_valid <= r_rx_valid;
 
r_rx_busy <= n_rx_busy;
rx_busy <= r_rx_busy;
 
rx_len <= n_rx_len;
end
 
`endif
 
reg [3:0] rx_err_pipe, rx_miss_pipe, rx_crc_pipe;
always @(posedge i_wb_clk)
begin
rx_err_pipe <= { rx_err_pipe[ 2:0],(n_rx_err)&&(rx_clk_stb) };
rx_miss_pipe <= { rx_miss_pipe[2:0],(n_rx_miss)&&(rx_clk_stb) };
rx_crc_pipe <= { rx_crc_pipe[ 2:0],(n_rx_crcerr)&&(rx_clk_stb) };
rx_err_stb <= (rx_err_pipe[ 3:2] == 2'b01);
rx_miss_stb <= (rx_miss_pipe[3:2] == 2'b01);
rx_crc_stb <= (rx_crc_pipe[ 3:2] == 2'b01);
end
 
always @(posedge i_wb_clk)
if (o_net_reset_n)
counter_rx_miss <= 32'h0;
else if (rx_miss_stb)
counter_rx_miss <= counter_rx_miss + 32'h1;
always @(posedge i_wb_clk)
if (o_net_reset_n)
counter_rx_err <= 32'h0;
else if (rx_err_stb)
counter_rx_err <= counter_rx_err + 32'h1;
always @(posedge i_wb_clk)
if (o_net_reset_n)
counter_rx_crc <= 32'h0;
else if (rx_crc_stb)
counter_rx_crc <= counter_rx_crc + 32'h1;
 
assign o_tx_int = !tx_busy;
assign o_rx_int = (rx_valid)&&(!rx_clear);
assign o_wb_stall = 1'b0;
 
wire [31:0] rxdbg;
wire rx_trigger; // reg rx_trigger;
/*
always @(posedge `RXCLK)
begin
if ((n_rx_clear)&&(!rx_trigger))
rx_trigger <= 1'b1;
else if (!n_rx_clear)
rx_trigger <= 1'b0;
end
*/
assign rx_trigger = i_net_dv;
 
assign rxdbg = { rx_trigger, n_eop, w_rxwr,
w_npre, w_npred,
w_rxcrc, w_rxcrcd,
w_macerr, w_broadcast, w_rxmac, w_rxmacd,
n_rx_clear, i_net_rxerr, n_rx_miss, n_rx_net_err,// 4 bits
n_rx_valid, n_rx_busy, i_net_crs, i_net_dv, // 4 bits
i_net_rxd }; // 4 bits
 
 
wire [31:0] txdbg;
assign txdbg = { n_tx_cmd, i_net_dv, rx_busy, n_rx_err, i_net_rxd,
{(24-(MAW+3)-10){1'b0}},
n_tx_addr[(MAW+2):0],
tx_clk_stb, n_tx_cancel,
n_tx_cmd, n_tx_complete, n_tx_busy, o_net_tx_en,
o_net_txd
};
 
assign o_debug = rxdbg;
endmodule
/fastmaster.v
219,12 → 219,12
gpsrx_int, rtc_pps
};
 
zipsystem #( .RESET_ADDRESS(24'h08000),
zipsystem #( .RESET_ADDRESS(24'h0480000),
.ADDRESS_WIDTH(ZA),
.LGICACHE(10),
.START_HALTED(1),
.START_HALTED(0),
.EXTERNAL_INTERRUPTS(ZIPINTS),
.HIGHSPEED_CPU(1))
.HIGHSPEED_CPU(0))
zippy(i_clk, i_rst,
// Zippys wishbone interface
zip_cyc, zip_stb, zip_we, w_zip_addr, zip_data,
349,13 → 349,14
assign mem_sel = (skipaddr[4:2]==3'b001);
assign netb_sel = (skipaddr[4:1]==4'b0001);
assign io_sel = (~|skipaddr)&&(wb_addr[7:5]==3'b000);
assign scop_sel = (~|skipaddr)&&(wb_addr[7:3]==5'b00100);
assign rtc_sel = (~|skipaddr)&&(wb_addr[7:2]==6'b001010);
assign sdcard_sel= (~|skipaddr)&&(wb_addr[7:2]==6'b001011);
assign netp_sel = (~|skipaddr)&&(wb_addr[7:2]==6'b001101);
assign oled_sel = (~|skipaddr)&&(wb_addr[7:2]==6'b001110);
assign gps_sel = (~|skipaddr)&&( (wb_addr[7:2]==6'b001100)
|| (wb_addr[7:3]==5'b01000));
assign scop_sel = (~|skipaddr)&&(wb_addr[7:3]==5'b0010_0);
assign rtc_sel = (~|skipaddr)&&(wb_addr[7:2]==6'b0010_10);
assign sdcard_sel= (~|skipaddr)&&(wb_addr[7:2]==6'b0010_11);
//assign gps_sel = (~|skipaddr)&&(wb_addr[7:2]==6'b0011_00);
assign oled_sel = (~|skipaddr)&&(wb_addr[7:2]==6'b0011_01);
assign netp_sel = (~|skipaddr)&&(wb_addr[7:3]==5'b0011_1);
assign gps_sel = (~|skipaddr)&&( (wb_addr[7:2]==6'b0011_00)
|| (wb_addr[7:3]==5'b0100_0));
assign mio_sel = (~|skipaddr)&&(wb_addr[7:5]==3'b101);
assign flctl_sel = (~|skipaddr)&&(wb_addr[7:5]==3'b110);
assign cfg_sel = (~|skipaddr)&&(wb_addr[7:5]==3'b111);
547,7 → 548,7
||((single_sel_a)&&(single_sel_b))
||((single_sel_a)&&(many_sel_a))
||((single_sel_b)&&(many_sel_b));
assign wb_err = (wb_cyc)&&(sel_err || many_ack || slow_many_ack);
assign wb_err = (wb_cyc)&&(sel_err || many_ack || slow_many_ack||ram_err);
 
 
// Finally, if we ever encounter a bus error, knowing the address of
623,18 → 624,9
(!dbg_counter_cyc[25])|w_led[1],
(!dbg_counter_err[25])|w_led[0] };
*/
assign o_led = w_led;
 
reg [25:0] dbg_counter_sdram;
always @(posedge i_clk)
if ((ram_sel)&&(wb_stb))
dbg_counter_sdram <= 0;
else if (wb_stb)
dbg_counter_sdram[25] <= 1'b1;
else if (!dbg_counter_sdram[25])
dbg_counter_sdram <= dbg_counter_sdram+26'h1;
assign o_led = { w_led[3:1], w_led[0] | (!dbg_counter_sdram[25]) };
 
 
//
//
// Real Time Clock (RTC) device level access
643,7 → 635,9
wire gps_tracking, ck_pps;
wire [63:0] gps_step;
`ifdef RTC_ACCESS
rtcgps #(32'h15798f) // 2^48 / 200MHz
rtcgps
// #(32'h15798f) // 2^48 / 200MHz
#(32'h1a6e3a) // 2^48 / 162.5 MHz
thertc(i_clk,
wb_cyc, (wb_stb)&&(rtc_sel), wb_we,
wb_addr[1:0], wb_data,
698,7 → 692,9
//
//
`ifdef OLEDRGB_ACCESS
wboled rgbctrl(i_clk,
wboled
.#( .CBITS(5))// Div ck by 2^5=32, words take 200ns@162.5MHz
rgbctrl(i_clk,
wb_cyc, (wb_stb)&&(oled_sel), wb_we,
wb_addr[1:0], wb_data,
oled_ack, oled_stall, oled_data,
754,7 → 750,9
//
// GPS CLOCK CONTROL
//
gpsclock ppsck(i_clk, 1'b0, gps_pps, ck_pps, gps_led,
gpsclock #(
.DEFAULT_STEP(32'h81a6e39b) // 162.5 MHz
) ppsck(i_clk, 1'b0, gps_pps, ck_pps, gps_led,
(wb_stb)&&(gps_sel)&&(~wb_addr[3]),
wb_we, wb_addr[1:0],
wb_data, gck_ack, gck_stall, gck_data,
865,7 → 863,8
//
// There is no option to turn this off--this RAM must always be
// present in the design.
memdev #(15) // 32kW, or 128kB, 15 address lines
memdev #(.AW(15),
.EXTRACLOCK(1)) // 32kW, or 128kB, 15 address lines
blkram(i_clk, wb_cyc, (wb_stb)&&(mem_sel), wb_we, wb_addr[14:0],
wb_data, mem_ack, mem_stall, mem_data);
 
962,8 → 961,8
&&(wb_err)||(zip_scope_data[31]);
wbscope #(5'd13) cpuscope(i_clk, 1'b1,(scop_cpu_trigger), zip_scope_data,
// Wishbone interface
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)), wb_we, wb_addr[0],
wb_data,
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)),
wb_we, wb_addr[0], wb_data,
scop_cpu_ack, scop_cpu_stall, scop_cpu_data,
scop_cpu_interrupt);
 
981,8 → 980,8
wbscope #(5'd13) flashscope(i_clk, 1'b1,
(scop_flash_trigger), flash_debug,
// Wishbone interface
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)), wb_we, wb_addr[0],
wb_data,
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)),
wb_we, wb_addr[0], wb_data,
scop_flash_ack, scop_flash_stall, scop_flash_data,
scop_flash_interrupt);
 
1131,7 → 1130,7
// else.
assign scop_stall = ((wb_addr[2:1]==2'b0)?scop_a_stall
: ((wb_addr[2:1]==2'b01)?scop_b_stall
: ((wb_addr[2:1]==2'b11)?scop_c_stall
: ((wb_addr[2:1]==2'b10)?scop_c_stall
: scop_d_stall))); // Will always be 1'b0;
initial scop_ack = 1'b0;
always @(posedge i_clk)
/flash_config.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: flashconfig.v
//
14,7 → 14,7
// Creator: Dan Gisselquist
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
37,7 → 37,7
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
`ifndef FLASH_CONFIG_V
`define FLASH_CONFIG_V
/lleqspi.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: lleqspi.v
//
13,7 → 13,7
// Creator: Dan Gisselquist
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
36,7 → 36,7
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
`define EQSPI_IDLE 3'h0
`define EQSPI_START 3'h1
`define EQSPI_BITS 3'h2
/memdev.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: memdev.v
//
16,7 → 16,7
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
34,7 → 34,7
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
module memdev(i_clk, i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
/rtcdate.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: rtcdate.v
//
26,7 → 26,7
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
49,7 → 49,7
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
module rtcdate(i_clk, i_ppd, i_wb_cyc, i_wb_stb, i_wb_we, i_wb_data,
o_wb_ack, o_wb_stall, o_wb_data);
input i_clk;
/rtcgps.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: rtcgps.v
//
15,7 → 15,7
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
38,7 → 38,9
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
module rtcgps(i_clk,
// Wishbone interface
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
/toplevel.v
54,7 → 54,11
i_uart_rx, o_uart_tx,
// Quad-SPI Flash control
o_qspi_sck, o_qspi_cs_n, io_qspi_dat,
// Missing: Ethernet
// Ethernet
o_eth_rstn, o_eth_ref_clk,
i_eth_rx_clk, i_eth_col, i_eth_crs, i_eth_rx_dv, i_eth_rxd, i_eth_rxerr,
i_eth_tx_clk, o_eth_tx_en, o_eth_txd,
// Ethernet (MDIO)
o_eth_mdclk, io_eth_mdio,
// Memory
ddr3_reset_n, ddr3_cke, ddr3_ck_p, ddr3_ck_n,
84,7 → 88,14
// Quad SPI flash
output wire o_qspi_sck, o_qspi_cs_n;
inout [3:0] io_qspi_dat;
// Ethernet // Not yet implemented
// Ethernet
output wire o_eth_rstn, o_eth_ref_clk;
input i_eth_rx_clk, i_eth_col, i_eth_crs, i_eth_rx_dv;
input [3:0] i_eth_rxd;
input i_eth_rxerr;
input i_eth_tx_clk;
output wire o_eth_tx_en;
output [3:0] o_eth_txd;
// Ethernet control (MDIO)
output wire o_eth_mdclk;
inout wire io_eth_mdio;
118,6 → 129,15
input i_aux_rx, i_aux_rts;
output wire o_aux_tx, o_aux_cts;
 
wire eth_tx_clk, eth_rx_clk;
`ifdef VERILATOR
wire s_clk, s_reset;
assign s_clk = sys_clk_i;
 
assign eth_tx_clk = i_eth_tx_clk;
assign eth_rx_clk = i_eth_rx_clk;
 
`else
// Build our master clock
wire s_clk, sys_clk, mem_clk_200mhz,
clk1_unused, clk2_unused, enet_clk, clk4_unnused,
130,8 → 150,8
.CLKFBOUT_MULT(8), // Multiply value for all CLKOUT (2-64)
.CLKOUT0_DIVIDE(8), // 100 MHz (Clock for MIG)
.CLKOUT1_DIVIDE(4), // 200 MHz (MIG Reference clock)
.CLKOUT2_DIVIDE(32), // 50 MHz (Unused)
.CLKOUT3_DIVIDE(64), // 25 MHz (Unused/Ethernet clock)
.CLKOUT2_DIVIDE(16), // 50 MHz (Unused)
.CLKOUT3_DIVIDE(32), // 25 MHz (Ethernet reference clk)
.CLKOUT4_DIVIDE(32), // 50 MHz (Unused clock?)
.CLKOUT5_DIVIDE(24), // 66 MHz
// CLKOUT0_DUTY_CYCLE -- Duty cycle for each CLKOUT
171,6 → 191,14
// BUFG memref_buffer(.I(mem_clk_200mhz_nobuf),.O(mem_clk_200mhz));
IBUF sysclk_buf(.I(sys_clk_i[0]), .O(sys_clk));
 
BUFG eth_rx(.I(i_eth_rx_clk), .O(eth_rx_clk));
// assign eth_rx_clk = i_eth_rx_clk;
 
 
BUFG eth_tx(.I(i_eth_tx_clk), .O(eth_tx_clk));
// assign eth_tx_clk = i_eth_tx_clk;
`endif
 
//
//
// UART interface
194,6 → 222,7
// logic fashion, we synchronize this wire by registering it first
// to pre_reset, and then to pwr_reset (the actual reset wire).
//
wire s_reset; // Ultimate system reset wire
reg [7:0] pre_reset;
reg pwr_reset;
// Since all our stuff is synchronous to the clock that comes out of
213,10 → 242,14
initial pwr_reset = 1'b0;
always @(posedge sys_clk)
pwr_reset <= pre_reset[7];
`ifdef VERILATOR
assign s_reset = pwr_reset;
`else
//
// Of course, this only goes into the memory controller. The true
// device reset comes out of that memory controller, synchronized to
// our memory generator provided clock(s)
`endif
 
wire w_ck_uart, w_uart_tx;
rxuart rcv(s_clk, s_reset, bus_uart_setup, i_uart_rx,
286,6 → 319,11
ram_dbg,
// SD Card
o_sd_sck, w_sd_cmd, w_sd_data, io_sd_cmd, io_sd, i_sd_cs,
// Ethernet
o_eth_rstn,
eth_rx_clk, i_eth_col, i_eth_crs, i_eth_rx_dv,
i_eth_rxd, i_eth_rxerr,
eth_tx_clk, o_eth_tx_en, o_eth_txd,
// Ethernet control (MDIO) lines
o_eth_mdclk, w_mdio, w_mdwe, io_eth_mdio,
// OLEDRGB PMod wires
322,6 → 360,13
//
wire [3:0] i_qspi_pedge, i_qspi_nedge;
 
`ifdef VERILATOR
assign o_qspi_sck = w_qspi_sck;
assign o_qspi_cs_n = w_qspi_cs_n;
;
();
[*];
`else
xoddr xqspi_sck( s_clk, { w_qspi_sck, w_qspi_sck }, o_qspi_sck);
xoddr xqspi_csn( s_clk, { w_qspi_cs_n, w_qspi_cs_n },o_qspi_cs_n);
//
337,8 → 382,12
xioddr xqspi_d3( s_clk, (qspi_bmod!=2'b11),
(qspi_bmod[1])?{ qspi_dat[3], qspi_dat[3] }:2'b11,
{ i_qspi_pedge[3], i_qspi_nedge[3] }, io_qspi_dat[3]);
`endif
reg [3:0] r_qspi_dat;
always @(posedge s_clk)
r_qspi_dat <= i_qspi_pedge;
assign i_qspi_dat = r_qspi_dat;
 
assign i_qspi_dat = i_qspi_pedge;
//
// Proposed QSPI mode select, to allow dual I/O mode
// 000 Normal SPI mode
352,6 → 401,17
 
//
//
// Generate a reference clock for the network
//
//
`ifdef VERILATOR
assign o_eth_ref_clk = i_eth_tx_clk;
`else
xoddr e_ref_clk( enet_clk, { 1'b1, 1'b0 }, o_eth_ref_clk );
`endif
 
//
//
// Wires for setting up the SD Card Controller
//
//
375,7 → 435,7
// Now, to set up our memory ...
//
//
migsdram rami(
migsdram #(.AXIDWIDTH(5)) rami(
.i_clk(mem_clk_nobuf), .i_clk_200mhz(mem_clk_200mhz_nobuf),
.o_sys_clk(s_clk), .i_rst(pwr_reset), .o_sys_reset(s_reset),
.i_wb_cyc(ram_cyc), .i_wb_stb(ram_stb), .i_wb_we(ram_we),
/wbicapetwo.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: wbicapetwo.v
//
68,9 → 68,9
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
86,8 → 86,9
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
`define MBOOT_IDLE 5'h00
`define MBOOT_START 5'h01
`define MBOOT_READ 5'h06
/wbqspiflash.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: wbspiflash.v
//
27,7 → 27,7
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
50,8 → 50,9
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
`include "flash_config.v"
//
`define WBQSPI_RESET 0
/wbscopc.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: wbscopc.v
//
61,7 → 61,7
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
84,7 → 84,7
// http://www.gnu.org/licenses/gpl.html
//
//
/////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
module wbscopc(i_clk, i_ce, i_trigger, i_data,
/wbscope.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: wbscope.v
//
58,7 → 58,7
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
81,12 → 81,15
// http://www.gnu.org/licenses/gpl.html
//
//
/////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
module wbscope(i_clk, i_ce, i_trigger, i_data,
i_wb_clk, i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
o_wb_ack, o_wb_stall, o_wb_data,
o_interrupt);
parameter LGMEM = 5'd10, BUSW = 32, SYNCHRONOUS=1;
parameter LGMEM = 5'd10, BUSW = 32, SYNCHRONOUS=1,
DEFAULT_HOLDOFF = ((1<<(LGMEM-1))-4);
// The input signals that we wish to record
input i_clk, i_ce, i_trigger;
input [(BUSW-1):0] i_data;
109,7 → 112,7
bw_disable_trigger, bw_reset_complete;
reg [22:0] br_config;
wire [19:0] bw_holdoff;
initial br_config = ((1<<(LGMEM-1))-4);
initial br_config = DEFAULT_HOLDOFF;
always @(posedge i_wb_clk)
if ((i_wb_cyc)&&(i_wb_stb)&&(~i_wb_addr))
begin
135,7 → 138,8
assign bw_reset_complete = bw_reset_request;
end else begin
reg r_reset_complete;
reg [2:0] r_iflags, q_iflags;
(* ASYNC_REG = "TRUE" *) reg [2:0] q_iflags;
reg [2:0] r_iflags;
 
// Resets are synchronous to the bus clock, not the data clock
// so do a clock transfer here
152,7 → 156,8
assign dw_manual_trigger = r_iflags[1];
assign dw_disable_trigger = r_iflags[0];
 
reg q_reset_complete, qq_reset_complete;
(* ASYNC_REG = "TRUE" *) reg q_reset_complete;
reg qq_reset_complete;
// Pass an acknowledgement back from the data clock to the bus
// clock that the reset has been accomplished
initial q_reset_complete = 1'b0;
190,7 → 195,7
//
// Writes take place on the data clock
reg dr_stopped;
reg [19:0] counter; // This is unsigned
(* ASYNC_REG="TRUE" *) reg [19:0] counter;// This is unsigned
initial dr_stopped = 1'b0;
initial counter = 20'h0000;
always @(posedge i_clk)
252,7 → 257,8
// for many clocks. Swapping is thus easy--two flip flops to
// protect against meta-stability and we're done.
//
reg [2:0] q_oflags, r_oflags;
(* ASYNC_REG = "TRUE" *) reg [2:0] q_oflags;
reg [2:0] r_oflags;
initial q_oflags = 3'h0;
initial r_oflags = 3'h0;
always @(posedge i_wb_clk)
/wbufifo.v
33,7 → 33,7
//
//
module wbufifo(i_clk, i_rst, i_wr, i_data, i_rd, o_data, o_empty_n, o_err);
parameter BW=66, LGFLEN=10, FLEN=(1<<LGFLEN);
parameter BW=66, LGFLEN=10;
input i_clk, i_rst;
input i_wr;
input [(BW-1):0] i_data;
42,6 → 42,8
output reg o_empty_n;
output wire o_err;
 
localparam FLEN=(1<<LGFLEN);
 
reg [(BW-1):0] fifo[0:(FLEN-1)];
reg [(LGFLEN-1):0] r_first, r_last;
 
/wbureadcw.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Filename: wbureadcw.v
//
15,7 → 15,7
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
33,7 → 33,7
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Goal: single clock pipeline, 50 slices or less
/wbusixchar.v
1,4 → 1,4
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename: wbusixchar.v
21,7 → 21,7
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
39,7 → 39,7
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//

powered by: WebSVN 2.1.0

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