URL
https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk
Subversion Repositories xulalx25soc
Compare Revisions
- This comparison shows the changes necessary to convert path
/xulalx25soc/trunk/rtl
- from Rev 114 to Rev 117
- ↔ Reverse comparison
Rev 114 → Rev 117
/builddate.v
File deleted
\ No newline at end of file
builddate.v
Property changes :
Deleted: svn:special
## -1 +0,0 ##
-*
\ No newline at end of property
Index: Makefile
===================================================================
--- Makefile (revision 114)
+++ 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 \
/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; |
/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 |
// |
// |
// |
/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; |
/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)); |
|
/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 |
/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; |
|
// |
/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 |
/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"), |
/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); |