URL
https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk
Subversion Repositories xulalx25soc
Compare Revisions
- This comparison shows the changes necessary to convert path
/xulalx25soc/trunk
- from Rev 116 to Rev 117
- ↔ Reverse comparison
Rev 116 → Rev 117
/Makefile
33,7 → 33,7
## |
## |
.PHONY: all |
all: datestamp verilated sw bench bit |
all: datestamp verilated sw bench |
# Could also depend upon load, if desired, but not necessary |
BENCH := `find bench -name Makefile` `find bench -name "*.cpp"` `find bench -name "*.h"` |
RTL := `find rtl -name "*.v"` `find rtl -name Makefile` |
65,8 → 65,8
cd rtl ; $(MAKE) --no-print-directory |
|
.PHONY: bench |
bench: |
cd bench ; $(MAKE) --no-print-directory |
bench: rtl |
cd bench/cpp ; $(MAKE) --no-print-directory |
|
.PHONY: sw |
sw: |
/README.md
0,0 → 1,59
# Description |
|
This project attempts to take two separate projects, the ZipCPU and Xess.com's XuLA2-LX25, and merge them together into a single system on a chip implementation. As currently implemented, this SoC offers the following peripherals to the ZipCPU within: |
|
- External peripherals |
|
- 14 GPIO inputs, 15 GPIO outputs |
- PWM output (can be swapped for an FM transmitter ...) |
- Rx and Tx UART ports |
- 1MB SPI flash, together with a read/write controller |
- 32MB SDRAM capable of non-stop pipeline reads and writes |
- SD Card, sharing the SPI wires of the flash |
|
- Internal peripherals |
|
- Real-time clock and date4 |
- Access to the FPGA configuration port, for unattended updates |
- ZipCPU debug/configuration port access from JTAG |
|
- ZipCPU peripherals |
|
- 3x timers, each of which can be programmed either in a one shot mode or as a repeating interval timer |
- A watchdog timer, and a wishbone bus watchdog timer |
- Two interrupt controllers |
- Direct Memory Access (DMA) controller for unattended memory movement |
|
# Current Status |
|
The SoC is fully functional. Keeping the project from being complete, however, |
is the lack of an integrated specification document. (Specification documents |
do exist, however, for many of the peripheral components.) |
|
# Unique Features |
|
This System on a Chip (SoC) controller has some unique features associated with |
it, above and beyond the peripherals listed above. Primary among those is the |
JTAG to 32-bit wishbone master conversion. This makes it possible for an |
external entity to read from or write to the wishbone bus. Uses include |
verifying whether or not peripherals work, as well as configuring the CPU, |
memory and flash for whatever purpose one might have. This particular |
capability was designed so that host (i.e. FPGA control) programs (external |
to the FPGA) can call a common set of bus interface functions to communicate |
with the FPGA, regardless of how the bus was implemented. |
|
A second unique feature is a PWM driver that spreads its digital energy into |
higher (non-auditory) frequencies which can then be filtered out easier |
with a simple low-pass filter. As an example, sending a zero, or half-pulse |
width, will result in alternating digital ones and zeros from the driver. While |
I expect this will have a pleasing effect on the ear, especially since these |
transactions will be outside of the normal hearing range, this is the first time |
I have tried it and the jury's still out regarding whether or not it works or |
even works well. |
|
Finally, while it may not really be that unique, this core does feature a fully |
functional SDRAM controller capable of sustaining one read cycle (or write |
cycle) every two clocks when pipelined. Unlike many other dynamic memory |
controllers, this one was _not_ created from a proprietary, closed source, |
memory interface generation facility--so it is available for anyone to examine, |
study, and even comment upon and improve--subject to the conditions of the GPL. |
/bench/cpp/pipecmdr.cpp
File deleted
/bench/cpp/Makefile
46,7 → 46,7
OBJDIR := obj-pc |
YYMMDD := `date +%Y%m%d` |
VOBJDR := ../../rtl/obj_dir |
VROOT := /usr/share/verilator |
VROOT ?= $(shell bash -c 'verilator -V|grep VERILATOR_ROOT | head -1 | sed -e " s/^.*=\s*//"') |
VINC := -I$(VROOT)/include -I$(VOBJDR) |
CFLAGS := -c -g -Wall -I. $(VINC) |
# Now return to the "all" target, and fill in some details |
/bench/cpp/busmaster_tb.cpp
116,6 → 116,8
#ifdef XULA25 |
sdcard_miso = m_sdcard(m_core->o_sd_cs_n, m_core->o_spi_sck, |
m_core->o_spi_mosi); |
#else |
sdcard_miso = 1; |
#endif |
|
if ((m_core->o_sf_cs_n)&&(m_core->o_sd_cs_n)) |
138,7 → 140,7
m_core->v__DOT__serialport__DOT__r_setup); |
PIPECMDR::tick(); |
|
// #define DEBUGGING_OUTPUT |
#define DEBUGGING_OUTPUT |
#ifdef DEBUGGING_OUTPUT |
bool writeout = false; |
/* |
154,8 → 156,8
writeout = true; |
*/ |
|
if ((m_core->v__DOT__wbu_cyc)&&(!m_core->v__DOT__wbu_we)) |
writeout = true; |
// if ((m_core->v__DOT__wbu_cyc)&&(!m_core->v__DOT__wbu_we)) |
// writeout = true; |
/* |
if ((m_core->v__DOT__wbu_cyc)&&(!m_core->v__DOT__wbu_we)) |
writeout = true; |
163,10 → 165,10
writeout = true; |
*/ |
|
if ((m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_early_branch) |
&&(m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction == 0x7883ffff)) |
m_busy+=2; |
else if (m_busy > 0) m_busy--; |
// if ((m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_early_branch) |
// &&(m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction == 0x7883ffff)) |
// m_busy+=2; |
// else if (m_busy > 0) m_busy--; |
#define v__DOT__wb_addr v__DOT__dwb_addr |
#define v__DOT__dwb_stall v__DOT__wb_stall |
#define v__DOT__dwb_ack v__DOT__wb_ack |
200,8 → 202,10
|((m_core->v__DOT__serialport__DOT__txmod__DOT__lcl_data)<<8) |
|((m_core->v__DOT__serialport__DOT__txmod__DOT__baud_counter&0x0f)<<4) |
|(m_core->v__DOT__serialport__DOT__txmod__DOT__state); |
/* |
if (tx_state != m_last_tx_state) |
writeout = true; |
*/ |
int bus_owner = m_core->v__DOT__wbu_zip_arbiter__DOT__r_a_owner; |
bus_owner |= (m_core->v__DOT__wbu_cyc)?2:0; |
bus_owner |= (m_core->v__DOT__dwb_cyc)?4:0; |
214,8 → 218,10
#ifdef XULA25 |
bus_owner |= (m_core->v__DOT__zippy__DOT__ext_cyc)?512:0; |
#endif |
/* |
if (bus_owner != m_last_bus_owner) |
writeout = true; |
*/ |
/* |
writeout = (writeout)||(m_core->i_rx_stb) |
||((m_core->o_tx_stb)&&(!m_core->i_tx_busy)); |
359,17 → 365,17
(m_core->v__DOT__zippy__DOT__thecpu__DOT__op_ce)?"k":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__op_stall)?"s":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__op_illegal)?"i":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__op_break)?"B":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__r_op_break)?"B":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__genblk5__DOT__r_op_lock)?"L":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__r_op_pipe)?"P":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__break_pending)?"p":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__op_gie)?"G":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__r_break_pending)?"p":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__r_op_gie)?"G":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__opvalid_alu)?"A":"-"); |
printf("|%s%s%s%s%s", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__alu_ce)?"a":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__alu_stall)?"s":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__doalu__DOT__genblk2__DOT__r_busy)?"B":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__alu_gie)?"G":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__r_alu_gie)?"G":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__r_alu_illegal)?"i":"-"); |
printf("|%s%s%s%2x %s%s%s %2d %2d", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__opvalid_mem)?"M":"-", |
408,9 → 414,9
(m_core->v__DOT__zippy__DOT__thecpu__DOT__opvalid)?'O':'-', |
m_core->v__DOT__zippy__DOT__thecpu__DOT__op_pc, |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__alu_valid)?'A':'-', |
m_core->v__DOT__zippy__DOT__thecpu__DOT__alu_pc); |
|
#ifdef XULA25 |
m_core->v__DOT__zippy__DOT__thecpu__DOT__r_alu_pc); |
|
/* |
// Prefetch debugging |
printf(" [PC%08x,LST%08x]->[%d%s%s](%d,%08x/%08x)->%08x@%08x", |
m_core->v__DOT__zippy__DOT__thecpu__DOT__pf_pc, |
427,23 → 433,16
m_core->v__DOT__zippy__DOT__thecpu__DOT__pf__DOT__r_last_cache, |
m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction, |
m_core->v__DOT__zippy__DOT__thecpu__DOT__instruction_pc); |
#else |
printf(" [PC%08x,R%08x]%s%s%s", |
m_core->v__DOT__zippy__DOT__thecpu__DOT__pf_pc, |
m_core->v__DOT__zippy__DOT__thecpu__DOT__pf__DOT__r_addr, |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__pf__DOT__w_pc_out_of_bounds)?"OOB":" ", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__pf__DOT__w_running_out_of_cache)?"RUN":" ", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__pf__DOT__w_ran_off_end_of_cache)?"END":" "); |
#endif |
*/ |
|
// Decode Stage debugging |
// (nothing) |
|
// Op Stage debugging |
printf(" Op(%02x,%02x->%02x)", |
m_core->v__DOT__zippy__DOT__thecpu__DOT__dcdOp, |
m_core->v__DOT__zippy__DOT__thecpu__DOT__opn, |
m_core->v__DOT__zippy__DOT__thecpu__DOT__opR); |
// printf(" Op(%02x,%02x->%02x)", |
// m_core->v__DOT__zippy__DOT__thecpu__DOT__dcdOp, |
// m_core->v__DOT__zippy__DOT__thecpu__DOT__opn, |
// m_core->v__DOT__zippy__DOT__thecpu__DOT__opR); |
|
printf(" %s[%02x]=%08x(%08x)", |
m_core->v__DOT__zippy__DOT__thecpu__DOT__wr_reg_ce?"WR":"--", |
466,6 → 465,7
m_core->v__DOT__zippy__DOT__thecpu__DOT__mem_wreg); |
|
// domem, the pipelined memory unit debugging |
/* |
printf(" M[%s@0x%08x]", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__opvalid_mem) |
?((m_core->v__DOT__zippy__DOT__thecpu__DOT__opn&1)?"W":"R") |
476,20 → 476,33
0 |
#endif |
); |
*/ |
|
/* |
printf("%s%s", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__domem__DOT__cyc)?"B":"-", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__mem_rdbusy)?"r":"-"); |
/* |
*/ |
#ifdef XULA25 |
printf(" %s-%s %04x/%04x", |
(m_core->v__DOT__zippy__DOT__genblk10__DOT__pic__DOT__r_any)?"PIC":"pic", |
(m_core->v__DOT__zippy__DOT__genblk10__DOT__pic__DOT__r_gie)?"INT":"( )", |
m_core->v__DOT__zippy__DOT__genblk10__DOT__pic__DOT__r_int_enable, |
m_core->v__DOT__zippy__DOT__genblk10__DOT__pic__DOT__r_int_state); |
*/ |
#else |
printf(" %s-%s %04x/%04x", |
(m_core->v__DOT__runio__DOT__intcontroller__DOT__r_any)?"PIC":"pic", |
(m_core->v__DOT__runio__DOT__intcontroller__DOT__r_gie)?"INT":"( )", |
m_core->v__DOT__runio__DOT__intcontroller__DOT__r_int_enable, |
m_core->v__DOT__runio__DOT__intcontroller__DOT__r_int_state); |
#endif |
|
|
/* |
printf(" %s", |
(m_core->v__DOT__zippy__DOT__thecpu__DOT__cc_invalid_for_dcd)?"CCI":" "); |
*/ |
|
/* |
// Illegal instruction debugging |
printf(" ILL[%s%s%s%s%s%s]", |
581,12 → 594,16
|
|
/* |
printf(" DMAC[%d]: %08x/%08x/%08x(%03x) -- (%d,%d,%c)%c%c:@%08x-[%4d,%4d/%4d,%4d-#%4d]%08x", |
printf(" DMAC[%d]: %08x/%08x/%08x(%03x)%d%d%d%d -- (%d,%d,%c)%c%c:@%08x-[%4d,%4d/%4d,%4d-#%4d]%08x", |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__dma_state, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__cfg_waddr, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__cfg_raddr, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__cfg_len, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__cfg_blocklen_sub_one, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__last_read_request, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__last_read_ack, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__last_write_request, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__last_write_ack, |
m_core->v__DOT__zippy__DOT__dc_cyc, |
// m_core->v__DOT__zippy__DOT__dc_stb, |
(m_core->v__DOT__zippy__DOT__dma_controller__DOT__dma_state == 2)?1:0, |
604,12 → 621,16
m_core->v__DOT__zippy__DOT__dma_controller__DOT__nwacks, |
m_core->v__DOT__zippy__DOT__dma_controller__DOT__nwritten, |
m_core->v__DOT__zippy__DOT__dc_data); |
*/ |
|
#ifdef OPT_ZIPSYSTEM |
printf(" %08x-PIC%08x", |
m_core->v__DOT__zippy__DOT__main_int_vector, |
m_core->v__DOT__zippy__DOT__pic_data); |
*/ |
#endif |
|
printf(" R0 = %08x", m_core->v__DOT__zippy__DOT__thecpu__DOT__regset[0]); |
|
printf("\n"); fflush(stdout); |
} m_last_writeout = writeout; |
|
628,13 → 649,15
#endif // DEBUGGING_OUTPUT |
} |
|
#ifdef DEBUGGING_OUTPUT |
bool dcd_ce(void) { |
if (!m_core->v__DOT__zippy__DOT__thecpu__DOT__r_dcdvalid) |
return true; |
if (!m_core->v__DOT__zippy__DOT__thecpu__DOT__op_stall) |
return true; |
// if (!m_core->v__DOT__zippy__DOT__thecpu__DOT__op_stall) |
// return true; |
return false; |
} |
#endif |
|
}; |
|
/doc/wishbone.html
45,6 → 45,32
<TR><TD><TT>1100_0000_0000_0000_0000_0000_0000_1111</TT></TD><TH align=right>1</TH><TD>User Instruction Counter</TD></TR> |
<TR><TD><TT>1100_0000_0000_0000_0000_0000_0001_00xx</TT></TD><TH align=right>1</TH><TD>DMA Controller</TD></TR> |
</TABLE> |
<!-- |
<TABLE align=center> |
<TR><TD><TT>1xxxxxx</TT></TD><TD>SDRAM</TD></TR> |
<TR><TD><TT>01xxxxx</TT></TD><TD>Flash</TD></TR> |
<TR><TD><TT>001xxxx</TT></TD><TD>Block RAM</TD></TR> |
<TR><TD><TT>00011xx</TT></TD><TD>ICAPE</TD></TR> |
<TR><TD><TT>000101x</TT></TD><TD>SD Card control</TD></TR> |
<TR><TD><TT>00010011</TT></TD><TD>Scope</TD></TR> |
<TR><TD><TT>00010010xxx</TT></TD><TD>RTC</TD></TR> |
<TR><TD><TT>00010001xxx</TT></TD><TD>PWM/UART/Flash Control</TD></TR> |
<TR><TD><TT>00010000xxx</TT></TD><TD>Other I/O</TD></TR> |
<TR><TD><TT>0000xxxxxxx</TT></TD><TD>Bus Error</TD></TR> |
</TABLE> |
<TABLE align=center> |
<TR><TD><TT>1xxxxxx</TT></TD><TD>SDRAM</TD></TR> |
<TR><TD><TT>01xxxxx</TT></TD><TD>Flash</TD></TR> |
<TR><TD><TT>00111xx</TT></TD><TD>Block RAM</TD></TR> |
<TR><TD><TT>00110xx_xxxx</TT></TD><TD>ICAPE</TD></TR> |
<TR><TD><TT>00101xx_xxx</TT></TD><TD>SD Card control</TD></TR> |
<TR><TD><TT>00100yy_yyxx</TT></TD><TD>Scope</TD></TR> |
<TR><TD><TT>00011yy_yxxx</TT></TD><TD>RTC</TD></TR> |
<TR><TD><TT>00010yy_yfux</TT></TD><TD>PWM/UART/Flash Control</TD></TR> |
<TR><TD><TT>00001yy_yxxx</TT></TD><TD>Other I/O</TD></TR> |
<TR><TD><TT>00000</TT></TD><TD>Bus Error</TD></TR> |
</TABLE> |
--> |
|
<h1 align=center>Primary (ZipSystem) Interrupt Controller Assignments</H1> |
<TABLE align=center> |
/rtl/builddate.v
File deleted
\ No newline at end of file
rtl/builddate.v
Property changes :
Deleted: svn:special
## -1 +0,0 ##
-*
\ No newline at end of property
Index: rtl/Makefile
===================================================================
--- rtl/Makefile (revision 116)
+++ rtl/Makefile (revision 117)
@@ -41,7 +41,7 @@
test: $(VDIRFB)/Vbusmaster__ALL.a
CPUDR := cpu
-CPUSOURCESnD := zipcpu.v cpuops.v pipefetch.v \
+CPUSOURCESnD := zipcpu.v cpuops.v cpudefs.v pipefetch.v \
pfcache.v idecode.v \
pipemem.v prefetch.v wbpriarbiter.v \
zipsystem.v zipcounter.v zipjiffies.v ziptimer.v zipbones.v \
/rtl/busmaster.v
89,10 → 89,10
// |
`ifdef XULA25 |
`ifdef FANCY_ICAP_ACCESS |
`define CFG_SCOPE // Only defined if we have the access ... |
// `define CFG_SCOPE // Only defined if we have the access ... |
`else |
`ifdef SDCARD_ACCESS |
`define SDCARD_SCOPE |
// `define SDCARD_SCOPE |
`endif |
`endif |
`endif |
109,7 → 109,7
`define ZIP_SCOPE |
`else // VERILATOR |
`ifdef XULA25 |
`define ZIP_SCOPE |
// `define ZIP_SCOPE |
`endif // XULA25 |
`endif // VERILATOR |
`endif // INCLUDE_ZIPCPU |
234,7 → 234,7
`endif |
); |
`else |
zipbones #(24'h2000,ZA,8,1) |
zipbones #(24'h2000,ZA,10,1) |
zippy(i_clk, 1'b0, |
// Zippys wishbone interface |
zip_cyc, zip_stb, zip_we, w_zip_addr, zip_data, |
333,6 → 333,11
assign dwb_we = wbu_we; |
assign dwb_stb = (wbu_stb); |
assign dwb_cyc = (wbu_cyc); |
assign wb_cyc = dwb_cyc; |
assign wb_stb = dwb_stb; |
assign wb_we = dwb_we; |
assign wb_addr = dwb_addr; |
assign wb_data = dwb_odata; |
assign wbu_ack = dwb_ack; |
assign wbu_stall = dwb_stall; |
assign dwb_idata = wb_idata; |
/rtl/cpu/cpudefs.v
63,8 → 63,8
// illegal instructions are quietly ignored and their behaviour is ... |
// undefined. (Many get treated like NOOPs ...) |
// |
// I recommend setting this flag, although it can be taken out if area is |
// critical ... |
// I recommend setting this flag so highly, that I'm likely going to remove |
// the option to turn this off in future versions of this CPU. |
// |
`define OPT_ILLEGAL_INSTRUCTION |
// |
191,9 → 191,7
// |
// If you have the fabric to support this option, I recommend including it. |
// |
`ifdef XULA25 |
`define OPT_TRADITIONAL_PFCACHE |
`endif |
// |
// |
// |
/rtl/cpu/wbarbiter.v
56,7 → 56,7
// |
`define WBA_ALTERNATING |
module wbarbiter(i_clk, i_rst, |
// Bus A |
// Bus A -- gets priority when not alternating |
i_a_adr, i_a_dat, i_a_we, i_a_stb, i_a_cyc, o_a_ack, o_a_stall, o_a_err, |
// Bus B |
i_b_adr, i_b_dat, i_b_we, i_b_stb, i_b_cyc, o_b_ack, o_b_stall, o_b_err, |
114,10 → 114,6
wire w_a_owner, w_b_owner; |
`ifdef WBA_ALTERNATING |
reg r_a_last_owner; |
// Stall must be asserted on the same cycle the input master asserts |
// the bus, if the bus isn't granted to him. |
assign o_a_stall = (w_a_owner) ? i_stall : 1'b1; |
assign o_b_stall = (w_b_owner) ? i_stall : 1'b1; |
|
`endif |
always @(posedge i_clk) |
175,6 → 171,11
assign o_a_ack = (w_a_owner) ? i_ack : 1'b0; |
assign o_b_ack = (w_b_owner) ? i_ack : 1'b0; |
|
// Stall must be asserted on the same cycle the input master asserts |
// the bus, if the bus isn't granted to him. |
assign o_a_stall = (w_a_owner) ? i_stall : 1'b1; |
assign o_b_stall = (w_b_owner) ? i_stall : 1'b1; |
|
// |
// |
assign o_a_err = (w_a_owner) ? i_err : 1'b0; |
/rtl/cpu/wbdmac.v
189,7 → 189,7
// When the slave wishbone writes, and we are in this |
// (ready) configuration, then allow the DMA to be controlled |
// and thus to start. |
if ((i_swb_cyc)&&(i_swb_stb)&&(i_swb_we)) |
if ((i_swb_stb)&&(i_swb_we)) |
begin |
case(i_swb_addr) |
2'b00: begin |
340,8 → 340,7
always @(posedge i_clk) |
if (dma_state == `DMA_IDLE) |
begin |
if ((i_swb_cyc)&&(i_swb_stb)&&(i_swb_we) |
&&(i_swb_addr==2'b00)) |
if ((i_swb_stb)&&(i_swb_we)&&(i_swb_addr==2'b00)) |
cfg_err <= 1'b0; |
end else if (((i_mwb_err)&&(o_mwb_cyc))||(abort)) |
cfg_err <= 1'b1; |
366,7 → 365,7
always @(posedge i_clk) |
if ((dma_state == `DMA_READ_REQ)||(dma_state == `DMA_READ_ACK)) |
begin |
if (i_mwb_ack) |
if ((i_mwb_ack)&&((~o_mwb_stb)||(i_mwb_stall))) |
last_read_ack <= (nread+2 == nracks); |
else |
last_read_ack <= (nread+1 == nracks); |
390,7 → 389,7
always @(posedge i_clk) |
if((dma_state == `DMA_WRITE_REQ)||(dma_state == `DMA_WRITE_ACK)) |
begin |
if (i_mwb_ack) |
if ((i_mwb_ack)&&((~o_mwb_stb)||(i_mwb_stall))) |
last_write_ack <= (nwacks+2 == nwritten); |
else |
last_write_ack <= (nwacks+1 == nwritten); |
457,13 → 456,13
// but ack it anyway. In other words, before writing to the device, |
// double check that it isn't busy, and then write. |
always @(posedge i_clk) |
o_swb_ack <= (i_swb_cyc)&&(i_swb_stb); |
o_swb_ack <= (i_swb_stb); |
|
assign o_swb_stall = 1'b0; |
|
initial abort = 1'b0; |
always @(posedge i_clk) |
abort <= (i_rst)||((i_swb_cyc)&&(i_swb_stb)&&(i_swb_we) |
abort <= (i_rst)||((i_swb_stb)&&(i_swb_we) |
&&(i_swb_addr == 2'b00) |
&&(i_swb_data == 32'hffed0000)); |
|
/rtl/cpu/zipcounter.v
64,7 → 64,7
initial o_int = 0; |
initial o_wb_data = 32'h00; |
always @(posedge i_clk) |
if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we)) |
if ((i_wb_stb)&&(i_wb_we)) |
{ o_int, o_wb_data } <= { 1'b0, i_wb_data }; |
else if (i_ce) |
{ o_int, o_wb_data } <= o_wb_data+{{(BW-1){1'b0}},1'b1}; |
73,6 → 73,6
|
initial o_wb_ack = 1'b0; |
always @(posedge i_clk) |
o_wb_ack <= (i_wb_cyc)&&(i_wb_stb); |
o_wb_ack <= (i_wb_stb); |
assign o_wb_stall = 1'b0; |
endmodule |
/rtl/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 |
137,7 → 140,7
`endif |
); |
parameter RESET_ADDRESS=32'h0100000, ADDRESS_WIDTH=24, |
LGICACHE=6; |
LGICACHE=8; |
`ifdef OPT_MULTIPLY |
parameter IMPLEMENT_MPY = `OPT_MULTIPLY; |
`else |
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; |
|
|
|
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 |
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); // &&(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; |
1329,6 → 1395,7
assign wr_write_ucc = (wr_reg_id[4:0] == {1'b1, `CPU_CC_REG}); |
// Are we writing to the PC? |
assign wr_write_pc = (wr_reg_id[3:0] == `CPU_PC_REG); |
|
// What value to write? |
assign wr_gpreg_vl = ((mem_valid) ? mem_result |
:((div_valid|fpu_valid)) |
1394,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) |
1736,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 |
1749,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 |
1758,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 |
1768,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; |
|
// |
/rtl/cpu/zipsystem.v
317,7 → 317,7
else if ((cmd_step)||(cpu_break)) |
cmd_halt <= 1'b1; |
|
initial cmd_clear_pf_cache = 1'b0; |
initial cmd_clear_pf_cache = 1'b1; |
always @(posedge i_clk) |
cmd_clear_pf_cache = (~i_rst)&&(dbg_cmd_write) |
&&((dbg_idata[11])||(dbg_idata[6])); |
557,7 → 557,7
wire ctri_sel, ctri_stall; |
reg ctri_ack; |
wire [31:0] ctri_data; |
assign ctri_sel = (sys_cyc)&&(sys_stb)&&(sys_addr == `CTRINT); |
assign ctri_sel = (sys_stb)&&(sys_addr == `CTRINT); |
always @(posedge i_clk) |
ctri_ack <= ctri_sel; |
assign ctri_stall = 1'b0; |
661,7 → 661,7
assign pic_stall = 1'b0; |
reg pic_ack; |
always @(posedge i_clk) |
pic_ack <= (sys_cyc)&&(sys_stb)&&(sys_addr == `INTCTRL); |
pic_ack <= (sys_stb)&&(sys_addr == `INTCTRL); |
|
// |
// The CPU itself |
/rtl/toplevel.v
88,7 → 88,7
.CLKFX_DIVIDE(3), |
.CLKFX_MULTIPLY(20), |
.CLKIN_DIVIDE_BY_2("FALSE"), |
.CLKIN_PERIOD(82.0), // 12MHz clock period in ns |
.CLKIN_PERIOD(83.0), // 12MHz clock period in ns |
.CLKOUT_PHASE_SHIFT("NONE"), |
.CLK_FEEDBACK("1X"), |
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), |
/rtl/txuart.v
227,7 → 227,7
|
|
initial zero_baud_counter = 1'b1; |
initial baud_counter = 28'd80000; // 1ms |
initial baud_counter = 28'd200000; // 1ms @ 200MHz |
always @(posedge i_clk) |
begin |
zero_baud_counter <= (baud_counter == 28'h01); |
/sw/Makefile
32,7 → 32,7
## |
## |
.PHONY: all |
PROGRAMS := $(OBJDIR) usbtst wbregs netusb wbsettime dumpflash \ |
PROGRAMS := $(OBJDIR) wbregs netusb wbsettime dumpflash \ |
dumpsdram ziprun ramscope zipstate zipdbg cfgscope loadmem \ |
sdcardscop uartscope |
all: $(PROGRAMS) |
/xilinx/Makefile
64,16 → 64,16
JTAGBUS := wbufifo.v wbubus.v wbucompactlines.v wbucompress.v \ |
wbudecompress.v wbudeword.v wbuexec.v wbuidleint.v wbuinput.v \ |
wbuoutput.v wbureadcw.v wbusixchar.v wbutohex.v |
PERIPHERALS: wbgpio.v wbpwmaudio.v rxuart.v txuart.v uartdev.v \ |
rtcdate.v rtclight.v |
PERIPHERALS:= wbgpio.v wbpwmaudio.v rxuart.v txuart.v uartdev.v \ |
rtcdate.v rtclight.v sdspi.v spiarbiter.v |
CPUSRC := zipsystem.v \ |
busdelay.v wbarbiter.v wbdblpriarb.v \ |
busdelay.v wbarbiter.v wbdblpriarb.v icontrol.v \ |
zipcpu.v cpuops.v pfcache.v idecode.v pipemem.v pipefetch.v div.v \ |
zipcounter.v zipjiffies.v ziptimer.v wbdmac.v wbwatchdog.v |
SOURCES := toplevel.v jtagser.v busmaster.v \ |
ioslave.v memdev.v hexmap.v icontrol.v builddate.v \ |
wbspiflash.v lldspi.v \ |
wbsdramng.v wbscope.v wbscopc.v $(JTAGBUS) |
ioslave.v memdev.v builddate.v \ |
wbspiflash.v lldspi.v sdspi.v wbgpio.v \ |
wbsdram.v wbscope.v wbscopc.v $(JTAGBUS) |
|
RTLFILES := $(addprefix $(SRCDIR)/,$(SOURCES)) $(addprefix $(CPUDIR)/,$(CPUSRC)) |
|
84,6 → 84,7
objdir: |
@bash -c "if [ ! -e $(OBJDIR)/ ]; then $(MKDIR) -p $(OBJDIR)/; fi" |
|
# Synthesize |
$(OBJDIR)/$(PROJECT).ngc: $(RTLFILES) $(PROJECT).xst |
$(MKDIR) -p xst/projnav.tmp/ |
xst -intstyle ise -ifn $(PROJECT).xst -ofn $(OBJDIR)/$(PROJECT).syr |
90,23 → 91,24
mv $(PROJECT).ngc $(OBJDIR)/$(PROJECT).ngc |
mv $(PROJECT).ngr $(OBJDIR)/$(PROJECT).ngr |
|
# Translate |
$(OBJDIR)/$(PROJECT).ngd: $(OBJDIR)/$(PROJECT).ngc |
ngdbuild -intstyle ise -dd _ngo -nt timestamp \ |
-uc $(UCFFILE) -p $(PART) $(OBJDIR)/$(PROJECT).ngc $(OBJDIR)/$(PROJECT).ngd |
|
# Map |
MAPOPTS := -w -logic_opt on -ol high -xe n -t 1 -xt 0 -r 4 \ |
-global_opt speed -equivalent_register_removal on -mt 2 -detail \ |
-ir off -ignore_keep_hierarchy -pr off -lc area -power off |
$(OBJDIR)/$(PROJECT).ncd: $(OBJDIR)/$(PROJECT).ngd |
$(OBJDIR)/$(PROJECT)_map.ncd: $(OBJDIR)/$(PROJECT).ngd |
map -intstyle ise -p $(PART) $(MAPOPTS) \ |
-o $(OBJDIR)/$(PROJECT)_map.ncd $(OBJDIR)/$(PROJECT).ngd $(OBJDIR)/$(PROJECT).pcf |
|
$(OBJDIR)/$(PROJECT).ncd: $(OBJDIR)/$(PROJECT)_map.ncd |
# Place and Route / Generate Programming File |
$(PROJECT).bit: $(OBJDIR)/$(PROJECT)_map.ncd |
par -w -intstyle ise -ol std -mt 4 $(OBJDIR)/$(PROJECT)_map.ncd $(OBJDIR)/$(PROJECT).ncd $(OBJDIR)/$(PROJECT).pcf |
bitgen -f $(PROJECT).ut $(OBJDIR)/$(PROJECT).ncd $(PROJECT).bit $(OBJDIR)/$(PROJECT).pcf |
|
$(PROJECT).bit: $(OBJDIR)/$(PROJECT).ncd |
bitgen -f $(PROJECT).ut $(OBJDIR)/$(PROJECT).ncd $(PROJECT).bit |
|
timing: $(OBJDIR)/$(PROJECT).ncd $(OBJDIR)/$(PROJECT).pcf |
trce -intstyle ise -v 3 -s 2 -n 3 -fastpaths -xml $(OBJDIR)/$(PROJECT).twx -o $(OBJDIR)/$(PROJECT).ncd -o $(OBJDIR)/$(PROJECT).twr $(OBJDIR)/$(PROJECT).pcf |
|
/xilinx/toplevel.bit
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/xula.ucf
140,7 → 140,7
############################## |
NET "i_clk_12mhz" TNM_NET = "i_clk_12mhz"; |
NET "i_ram_feedback_clk" TNM_NET = "i_ram_feedback_clk"; |
TIMESPEC "TSi_clk_12mhz" = PERIOD "i_clk_12mhz" 82.0 ns HIGH 50%; |
TIMESPEC "TSi_clk_12mhz" = PERIOD "i_clk_12mhz" 83.0 ns HIGH 50%; |
# TIMESPEC "TSi_clk_12mhz" = PERIOD "i_clk_12mhz" 83.333333 ns HIGH 50%; |
# TIMESPEC "TSi_ram_feedback_clk" = PERIOD "i_ram_feedback_clk" 10.0 ns HIGH 50%; |
TIMESPEC "TSi_ram_feedback_clk" = PERIOD "i_ram_feedback_clk" 11.3 ns HIGH 50%; |