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

Subversion Repositories openarty

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openarty
    from Rev 48 to Rev 49
    Reverse comparison

Rev 48 → Rev 49

/trunk/bench/cpp/fastmaster_tb.cpp
233,6 → 233,7
 
 
/*
// GPS Tracking triggers
if (m_core->v__DOT__ppsck__DOT__err_tick)
writeout = true;
if (m_core->v__DOT__ppsck__DOT__sub_tick)
256,6 → 257,7
// if (m_core->v__DOT__dwb_cyc)
// writeout = true;
 
// CPU Debugging triggers
// Write out if the CPU is active at all
if (m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__master_ce)
writeout = true;
304,7 → 306,6
(m_core->v__DOT____Vcellinp__genbus____pinNumber10)?'s':' ',
(m_core->v__DOT__wb_err)?'E':'.');
 
/*
// CPU Pipeline debugging
printf("%s%s%s%s%s%s%s%s%s%s%s",
// (m_core->v__DOT__zippy__DOT__dbg_ack)?"A":"-",
314,7 → 315,7
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__r_halted)?"Z":"-",
(m_core->v__DOT__zippy__DOT__cpu_break)?"!":"-",
(m_core->v__DOT__zippy__DOT__cmd_halt)?"H":"-",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__gie)?"G":"-",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__r_gie)?"G":"-",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__pf_cyc)?"P":"-",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__pf_valid)?"V":"-",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__pf_illegal)?"i":" ",
353,7 → 354,7
(m_core->v__DOT__zippy__DOT__cmd_addr),
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__bus_err)?"BE":" ",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__ibus_err_flag)?"IB":" ",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__ubus_err_flag)?"UB":" ",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__r_ubus_err_flag)?"UB":" ",
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__domem__DOT__rdaddr,
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__domem__DOT__wraddr);
printf("|%s%s",
366,16 → 367,18
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__wr_gpreg_vl);
 
// Program counter debugging
printf(" PC0x%08x/%08x/%08x-%08x %s0x%08x",
printf(" PC0x%08x/%08x/%08x-I:%08x %s0x%08x%s",
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__pf_pc,
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__ipc,
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__upc,
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__r_upc,
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__instruction,
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_early_branch)?"EB":" ",
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_branch_pc
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_early_branch)?"EB":
((m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_ljmp)?"JM":" "),
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__instruction_decoder__DOT__genblk3__DOT__r_branch_pc,
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__r_clear_icache)?"-CLRC":" "
);
// More in-depth
printf("[%c%08x,%c%08x,%c%08x]",
printf(" [%c%08x,%c%08x,%c%08x]",
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__r_dcdvalid)?'D':'-',
m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__dcd_pc,
(m_core->v__DOT__zippy__DOT__genblk11__DOT__thecpu__DOT__opvalid)?'O':'-',
440,7 → 443,6
m_core->v__DOT__zip_dbg_data);
 
printf(" %s,0x%08x", (m_core->i_ram_ack)?"RCK":" ", m_core->i_ram_rdata);
*/
 
 
/*
/trunk/doc/spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/trunk/doc/src/spec.tex
288,6 → 288,16
serial ports, while replacing the registers with read--only memory values of
zero.
 
The {\tt arty.xdc} file is designed so that these PMods can be connected as
shown in Fig.~\ref{fig:pmod-pic}.
\begin{figure}\begin{center}
\includegraphics[width=4in]{../gfx/openarty.eps}
\caption{Showing how the PMods are Connected}\label{fig:pmod-pic}
\end{center}\end{figure}
In this example, the PModOLED is connected to PMod port JB, and the PModSD is
connected to PMod port JD. Both the PModGPS and the PModUSBUART are both
connected to port JC, with the GPS connected on top and the USBUART on the
bottom.
 
\section{Testing the peripherals}
OpenArty has been designed so that all of the peripherals live on a
/trunk/rtl/builddate.v
38,4 → 38,4
////////////////////////////////////////////////////////////////////////////////
//
//
`define DATESTAMP 32'h20161102
`define DATESTAMP 32'h20161123
/trunk/rtl/busmaster.v
671,7 → 671,8
wb_cyc, (io_sel)&&(wb_stb), wb_we, wb_addr[4:0],
wb_data, io_ack, io_stall, io_data,
rtc_ppd,
bus_err_addr, gps_now[63:32], gps_step[47:16], master_ints, w_interrupt,
bus_err_addr, gps_now[63:32], gps_step[47:16],
master_ints, w_interrupt,
board_ints);
assign { gpio_int, auxrx_int, auxtx_int, gpsrx_int, gpstx_int, sw_int, btn_int } = board_ints;
 
/trunk/rtl/cpu/cpudefs.v
281,4 → 281,7
//
`define DEBUG_SCOPE
//
// The following is experimental:
// `define OPT_NO_USERMODE // Savings: about 143 LUTs or so
//
`endif // CPUDEFS_H
/trunk/rtl/cpu/idecode.v
96,13 → 96,14
 
 
wire [4:0] w_op;
wire w_ldi, w_mov, w_cmptst, w_ldilo, w_ALU, w_brev, w_noop;
wire w_ldi, w_mov, w_cmptst, w_ldilo, w_ALU, w_brev, w_noop,
w_mpy;
wire [4:0] w_dcdR, w_dcdB, w_dcdA;
wire w_dcdR_pc, w_dcdR_cc;
wire w_dcdA_pc, w_dcdA_cc;
wire w_dcdB_pc, w_dcdB_cc;
wire [3:0] w_cond;
wire w_wF, w_dcdM, w_dcdDV, w_dcdFP;
wire w_wF, w_dcdM, w_dcdDV, w_dcdFP, w_sto;
wire w_wR, w_rA, w_rB, w_wR_n;
wire w_ljmp, w_ljmp_dly;
wire [31:0] iword;
133,16 → 134,21
assign w_brev = (w_op == 5'hc);
assign w_cmptst = (w_op[4:1] == 4'h8);
assign w_ldilo = (w_op[4:0] == 5'h9);
assign w_mpy = ((w_op[4:1]==4'h5)||(w_op[4:0]==5'h08));
assign w_ALU = (~w_op[4]);
 
// 4 LUTs
//
// Two parts to the result register: the register set, given for
// moves in i_word[18] but only for the supervisor, and the other
// moves in iword[18] but only for the supervisor, and the other
// four bits encoded in the instruction.
//
`ifdef OPT_NO_USERMODE
assign w_dcdR = { 1'b0, iword[30:27] };
`else
assign w_dcdR = { ((~iword[31])&&(w_mov)&&(~i_gie))?iword[18]:i_gie,
iword[30:27] };
`endif
// 2 LUTs
//
// If the result register is either CC or PC, and this would otherwise
152,9 → 158,13
((IMPLEMENT_FPU>0)&&(w_dcdR[3:1] == 3'h7))
||(IMPLEMENT_FPU==0));
 
`ifdef OPT_NO_USERMODE
assign w_dcdB = { 1'b0, iword[17:14] };
`else
// 4 LUTs
assign w_dcdB = { ((~iword[31])&&(w_mov)&&(~i_gie))?iword[13]:i_gie,
iword[17:14] };
`endif
 
// 0 LUTs
assign w_dcdA = w_dcdR;
180,6 → 190,7
 
// 1 LUT
assign w_dcdM = (w_op[4:1] == 4'h9);
assign w_sto = (w_dcdM)&&(w_op[0]);
// 1 LUT
assign w_dcdDV = (w_op[4:1] == 4'ha);
// 1 LUT
191,18 → 202,17
||(w_dcdDV)
// ALU read's A, unless it's a MOV to A
// This includes LDIHI/LDILO
||((~w_op[4])&&(w_op[3:0]!=4'hf))
||((~w_op[4])&&(w_op[3:0]!=4'hf)&&(!w_brev))
// STO's read A
||((w_dcdM)&&(w_op[0]))
// Test/compares
||(w_op[4:1]== 4'h8);
||(w_cmptst);
// 1 LUTs -- do we read a register for operand B? Specifically, do
// we need to stall if the register is not (yet) ready?
assign w_rB = (w_mov)||((iword[18])&&(~w_ldi));
// 1 LUT: All but STO, NOOP/BREAK/LOCK, and CMP/TST write back to w_dcdR
assign w_wR_n = ((w_dcdM)&&(w_op[0]))
||((w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7))
||(w_cmptst);
assign w_wR_n = (w_sto)||(w_cmptst)
||((w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7));
assign w_wR = ~w_wR_n;
//
// 1-output bit (5 Opcode bits, 4 out-reg bits, 3 condition bits)
279,7 → 289,7
`else
o_illegal <= ((i_illegal) || (i_instruction[31]));
`endif
if ((IMPLEMENT_MPY==0)&&((w_op[4:1]==4'h5)||(w_op[4:0]==5'h08)))
if ((IMPLEMENT_MPY==0)&&(w_mpy))
o_illegal <= 1'b1;
 
if ((IMPLEMENT_DIVIDE==0)&&(w_dcdDV))
425,7 → 435,7
begin
if (r_ljmp)
r_branch_pc <= iword[(AW-1):0];
else if (w_op[4:1] == 4'hb) // LDI
else if (w_ldi) // LDI
r_branch_pc <= {{(AW-23){iword[22]}},iword[22:0]};
else // Add x,PC
r_branch_pc <= i_pc
/trunk/rtl/cpu/memops.v
44,7 → 44,8
o_wb_stb_gbl, o_wb_stb_lcl,
o_wb_we, o_wb_addr, o_wb_data,
i_wb_ack, i_wb_stall, i_wb_err, i_wb_data);
parameter ADDRESS_WIDTH=24, IMPLEMENT_LOCK=0, AW=ADDRESS_WIDTH;
parameter ADDRESS_WIDTH=32, IMPLEMENT_LOCK=0;
localparam AW=ADDRESS_WIDTH;
input i_clk, i_rst;
input i_stb, i_lock;
// CPU interface
72,8 → 73,8
 
reg r_wb_cyc_gbl, r_wb_cyc_lcl;
wire gbl_stb, lcl_stb;
assign lcl_stb = (i_stb)&&(i_addr[31:8]==24'hc00000)&&(i_addr[7:5]==3'h0);
assign gbl_stb = (i_stb)&&((i_addr[31:8]!=24'hc00000)||(i_addr[7:5]!=3'h0));
assign lcl_stb = (i_stb)&&(i_addr[31:24]==8'hff);
assign gbl_stb = (i_stb)&&(i_addr[31:24]!=8'hff);
 
initial r_wb_cyc_gbl = 1'b0;
initial r_wb_cyc_lcl = 1'b0;
/trunk/rtl/cpu/pipemem.v
42,7 → 42,8
o_wb_stb_gbl, o_wb_stb_lcl,
o_wb_we, o_wb_addr, o_wb_data,
i_wb_ack, i_wb_stall, i_wb_err, i_wb_data);
parameter ADDRESS_WIDTH=32, IMPLEMENT_LOCK=0, AW=ADDRESS_WIDTH;
parameter ADDRESS_WIDTH=32, IMPLEMENT_LOCK=0;
localparam AW=ADDRESS_WIDTH;
input i_clk, i_rst;
input i_pipe_stb, i_lock;
// CPU interface
90,7 → 91,7
assign nxt_rdaddr = rdaddr + 4'h1;
 
wire gbl_stb, lcl_stb;
assign lcl_stb = (i_addr[31:8]==24'hc00000)&&(i_addr[7:5]==3'h0);
assign lcl_stb = (i_addr[31:24]==8'hff);
assign gbl_stb = (~lcl_stb);
//= ((i_addr[31:8]!=24'hc00000)||(i_addr[7:5]!=3'h0));
 
/trunk/rtl/cpu/zipcpu.v
203,22 → 203,26
// that logic.
//
(* ram_style = "distributed" *)
`ifdef OPT_NO_USERMODE
reg [31:0] regset [0:15];
`else
reg [31:0] regset [0:31];
`endif
 
// Condition codes
// (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;
wire break_pending;
wire w_clear_icache;
reg break_en, step, sleep, r_halted;
wire break_pending, trap, gie, ubreak;
wire w_clear_icache, ill_err_u;
`ifdef OPT_ILLEGAL_INSTRUCTION
reg ill_err_u, ill_err_i;
reg ill_err_i;
`else
wire ill_err_u, ill_err_i;
wire ill_err_i;
`endif
reg ubreak;
reg ibus_err_flag, ubus_err_flag;
reg ibus_err_flag;
wire ubus_err_flag;
wire idiv_err_flag, udiv_err_flag;
wire ifpu_err_flag, ufpu_err_flag;
wire ihalt_phase, uhalt_phase;
330,9 → 334,7
 
 
wire mem_ce, mem_stalled;
`ifdef OPT_PIPELINED_BUS_ACCESS
wire mem_pipe_stalled;
`endif
wire mem_valid, mem_ack, mem_stall, mem_err, bus_err,
mem_cyc_gbl, mem_cyc_lcl, mem_stb_gbl, mem_stb_lcl, mem_we;
wire [4:0] mem_wreg;
369,7 → 371,8
wire [4:0] wr_reg_id;
wire [31:0] wr_gpreg_vl, wr_spreg_vl;
wire w_switch_to_interrupt, w_release_from_interrupt;
reg [(AW-1):0] upc, ipc;
reg [(AW-1):0] ipc;
wire [(AW-1):0] upc;
 
 
 
445,7 → 448,7
// CC register
||(dcdF_stall)
);
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~op_stall)&&(~clear_pipeline);
assign op_ce = ((dcdvalid)||(dcd_illegal)||(dcd_early_branch))&&(~op_stall)&&(~clear_pipeline);
 
 
// BUT ... op_ce is too complex for many of the data operations. So
456,7 → 459,7
assign op_change_data_ce = (~op_stall);
`else
assign op_stall = (opvalid)&&(~master_ce);
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~clear_pipeline);
assign op_ce = ((dcdvalid)||(dcd_illegal)||(dcd_early_branch))&&(~clear_pipeline);
assign op_change_data_ce = 1'b1;
`endif
 
476,7 → 479,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)) // || op_illegal
||((opvalid)&&(op_break))
||(wr_reg_ce)&&(wr_write_cc)
||(div_busy)||(fpu_busy);
assign alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)
594,7 → 597,11
(mem_cyc_lcl)||(mem_cyc_gbl),
pf_illegal);
`endif
`ifdef OPT_NO_USERMODE
assign instruction_gie = 1'b0;
`else
assign instruction_gie = gie;
`endif
 
initial r_dcdvalid = 1'b0;
always @(posedge i_clk)
673,8 → 680,13
// PIPELINE STAGE #3 :: Read Operands (Registers)
//
//
`ifdef OPT_NO_USERMODE
assign w_opA = regset[dcdA[3:0]];
assign w_opB = regset[dcdB[3:0]];
`else
assign w_opA = regset[dcdA];
assign w_opB = regset[dcdB];
`endif
 
wire [8:0] w_cpu_info;
assign w_cpu_info = {
843,7 → 855,7
assign opF = { r_opF[3], r_opF[5], r_opF[1], r_opF[4:0] };
 
wire w_opvalid;
assign w_opvalid = (~clear_pipeline)&&(dcdvalid)&&(~dcd_ljmp);
assign w_opvalid = (~clear_pipeline)&&(dcdvalid)&&(~dcd_ljmp)&&(!dcd_early_branch);
initial opvalid = 1'b0;
initial opvalid_alu = 1'b0;
initial opvalid_mem = 1'b0;
867,14 → 879,15
// Hence, the test on dcd_stalled here. If we must
// wait until our operands are valid, then we aren't
// valid yet until then.
opvalid<= (w_opvalid)||(dcd_illegal)&&(dcdvalid);
opvalid<= (w_opvalid)||(dcd_illegal)&&(dcdvalid)||(dcd_early_branch);
`ifdef OPT_ILLEGAL_INSTRUCTION
opvalid_alu <= (w_opvalid)&&((dcdALU)||(dcd_illegal));
opvalid_alu <= (w_opvalid)&&((dcdALU)||(dcd_illegal)
||(dcd_early_branch));
opvalid_mem <= (dcdM)&&(~dcd_illegal)&&(w_opvalid);
opvalid_div <= (dcdDV)&&(~dcd_illegal)&&(w_opvalid);
opvalid_fpu <= (dcdFP)&&(~dcd_illegal)&&(w_opvalid);
`else
opvalid_alu <= (dcdALU)&&(w_opvalid);
opvalid_alu <= (dcdALU)&&(w_opvalid)||(dcd_early_branch);
opvalid_mem <= (dcdM)&&(w_opvalid);
opvalid_div <= (dcdDV)&&(w_opvalid);
opvalid_fpu <= (dcdFP)&&(w_opvalid);
903,7 → 916,7
initial r_op_break = 1'b0;
always @(posedge i_clk)
if (i_rst) r_op_break <= 1'b0;
else if (op_ce) r_op_break <= (dcd_break); //||dcd_illegal &&(dcdvalid)
else if (op_ce) r_op_break <= (dcd_break);
else if ((clear_pipeline)||(~opvalid))
r_op_break <= 1'b0;
assign op_break = r_op_break;
988,7 → 1001,9
always @(posedge i_clk)
if (op_change_data_ce)
begin
r_opn <= dcdOp; // Which ALU operation?
// Which ALU operation? Early branches are
// unimplemented moves
r_opn <= (dcd_early_branch) ? 4'hf : dcdOp;
// opM <= dcdM; // Is this a memory operation?
// What register will these results be written into?
r_opR <= dcdR;
996,18 → 1011,25
// User level (1), vs supervisor (0)/interrupts disabled
r_op_gie <= dcd_gie;
 
 
//
op_pc <= (dcd_early_branch)?dcd_branch_pc:dcd_pc;
end
assign opn = r_opn;
assign opR = r_opR;
`ifdef OPT_NO_USERMODE
assign op_gie = 1'b0;
`else
assign op_gie = r_op_gie;
`endif
assign opR_cc = r_opR_cc;
`else
assign opn = dcdOp;
assign opR = dcdR;
`ifdef OPT_NO_USERMODE
assign op_gie = 1'b0;
`else
assign op_gie = dcd_gie;
`endif
// 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;
1229,6 → 1251,9
reg [31:0] dbg_val;
always @(posedge i_clk)
dbg_val <= i_dbg_data;
`ifdef OPT_NO_USERMODE
assign alu_gie = 1'b0;
`else
`ifdef OPT_PIPELINED
reg r_alu_gie;
 
1236,7 → 1261,12
if ((adf_ce_unconditional)||(mem_ce))
r_alu_gie <= op_gie;
assign alu_gie = r_alu_gie;
`else
assign alu_gie = op_gie;
`endif
`endif
 
`ifdef OPT_PIPELINED
reg [(AW-1):0] r_alu_pc;
always @(posedge i_clk)
if ((adf_ce_unconditional)
1245,7 → 1275,6
r_alu_pc <= op_pc;
assign alu_pc = r_alu_pc;
`else
assign alu_gie = op_gie;
assign alu_pc = op_pc;
`endif
 
1321,6 → 1350,7
mem_stb_gbl, mem_stb_lcl,
mem_we, mem_addr, mem_data,
mem_ack, mem_stall, mem_err, i_wb_data);
assign mem_pipe_stalled = 1'b0;
`endif // PIPELINED_BUS_ACCESS
assign mem_rdbusy = ((mem_busy)&&(~mem_we));
 
1380,7 → 1410,14
// One or PC, one for CC, and one for GIE match
// Note that the alu_reg is the register to write on a divide or
// FPU operation.
`ifdef OPT_NO_USERMODE
assign wr_reg_id[3:0] = (alu_wr|div_valid|fpu_valid)
? alu_reg[3:0]:mem_wreg[3:0];
assign wr_reg_id[4] = 1'b0;
`else
assign wr_reg_id = (alu_wr|div_valid|fpu_valid)?alu_reg:mem_wreg;
`endif
 
// Are we writing to the CC register?
assign wr_write_cc = (wr_reg_id[3:0] == `CPU_CC_REG);
assign wr_write_scc = (wr_reg_id[4:0] == {1'b0, `CPU_CC_REG});
1397,7 → 1434,11
:((dbgv) ? dbg_val : alu_result));
always @(posedge i_clk)
if (wr_reg_ce)
regset[wr_reg_id] <= wr_gpreg_vl;
`ifdef OPT_NO_USERMODE
regset[wr_reg_id[3:0]] <= wr_gpreg_vl;
`else
regset[wr_reg_id] <= wr_gpreg_vl;
`endif
 
//
// Write back to the condition codes/flags register ...
1483,7 → 1524,29
// a panic/fault halt. The trick is that you cannot be allowed to
// set the sleep bit and switch to supervisor mode in the same
// instruction: users are not allowed to halt the CPU.
initial sleep = 1'b0;
`ifdef OPT_NO_USERMODE
reg r_sleep_is_halt;
initial r_sleep_is_halt = 1'b0;
always @(posedge i_clk)
if (i_rst)
r_sleep_is_halt <= 1'b0;
else if ((wr_reg_ce)&&(wr_write_cc)
&&(wr_spreg_vl[`CPU_SLEEP_BIT])
&&(~wr_spreg_vl[`CPU_GIE_BIT]))
r_sleep_is_halt <= 1'b1;
 
// Trying to switch to user mode, either via a WAIT or an RTU
// instruction will cause the CPU to sleep until an interrupt, in
// the NO-USERMODE build.
always @(posedge i_clk)
if ((i_rst)||((i_interrupt)&&(!r_sleep_is_halt)))
sleep <= 1'b0;
else if ((wr_reg_ce)&&(wr_write_cc)
&&(wr_spreg_vl[`CPU_GIE_BIT]))
sleep <= 1'b1;
`else
always @(posedge i_clk)
if ((i_rst)||(w_switch_to_interrupt))
sleep <= 1'b0;
else if ((wr_reg_ce)&&(wr_write_cc)&&(~alu_gie))
1503,6 → 1566,7
// to sleep mode *and* supervisor mode at the same
// time, lest you halt the CPU.
sleep <= wr_spreg_vl[`CPU_SLEEP_BIT];
`endif
 
always @(posedge i_clk)
if (i_rst)
1511,6 → 1575,10
step <= wr_spreg_vl[`CPU_STEP_BIT];
 
// The GIE register. Only interrupts can disable the interrupt register
`ifdef OPT_NO_USERMODE
assign w_switch_to_interrupt = 1'b0;
assign w_release_from_interrupt = 1'b0;
`else
assign w_switch_to_interrupt = (gie)&&(
// On interrupt (obviously)
((i_interrupt)&&(~alu_phase)&&(~bus_lock))
1542,34 → 1610,56
&&(((wr_reg_ce)&&(wr_spreg_vl[`CPU_GIE_BIT])
&&(wr_write_scc))
);
`endif
 
`ifdef OPT_NO_USERMODE
assign gie = 1'b0;
`else
reg r_gie;
 
initial r_gie = 1'b0;
always @(posedge i_clk)
if (i_rst)
gie <= 1'b0;
r_gie <= 1'b0;
else if (w_switch_to_interrupt)
gie <= 1'b0;
r_gie <= 1'b0;
else if (w_release_from_interrupt)
gie <= 1'b1;
r_gie <= 1'b1;
assign gie = r_gie;
`endif
 
initial trap = 1'b0;
`ifdef OPT_NO_USERMODE
assign trap = 1'b0;
assign ubreak = 1'b0;
`else
reg r_trap;
 
initial r_trap = 1'b0;
always @(posedge i_clk)
if ((i_rst)||(w_release_from_interrupt))
trap <= 1'b0;
r_trap <= 1'b0;
else if ((alu_gie)&&(wr_reg_ce)&&(~wr_spreg_vl[`CPU_GIE_BIT])
&&(wr_write_ucc)) // &&(wr_reg_id[4]) implied
trap <= 1'b1;
r_trap <= 1'b1;
else if ((wr_reg_ce)&&(wr_write_ucc)&&(~alu_gie))
trap <= (trap)&&(wr_spreg_vl[`CPU_TRAP_BIT]);
r_trap <= (r_trap)&&(wr_spreg_vl[`CPU_TRAP_BIT]);
 
initial ubreak = 1'b0;
reg r_ubreak;
 
initial r_ubreak = 1'b0;
always @(posedge i_clk)
if ((i_rst)||(w_release_from_interrupt))
ubreak <= 1'b0;
r_ubreak <= 1'b0;
else if ((op_gie)&&(break_pending)&&(w_switch_to_interrupt))
ubreak <= 1'b1;
r_ubreak <= 1'b1;
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)&&(wr_write_ucc))
ubreak <= (ubreak)&&(wr_spreg_vl[`CPU_BREAK_BIT]);
r_ubreak <= (ubreak)&&(wr_spreg_vl[`CPU_BREAK_BIT]);
 
assign trap = r_trap;
assign ubreak = r_ubreak;
`endif
 
 
`ifdef OPT_ILLEGAL_INSTRUCTION
initial ill_err_i = 1'b0;
always @(posedge i_clk)
1580,18 → 1670,25
ill_err_i <= (ill_err_i)&&(wr_spreg_vl[`CPU_ILL_BIT]);
else if ((alu_illegal)&&(~alu_gie)&&(!clear_pipeline))
ill_err_i <= 1'b1;
initial ill_err_u = 1'b0;
 
`ifdef OPT_NO_USERMODE
assign ill_err_u = 1'b0;
`else
reg r_ill_err_u;
 
initial r_ill_err_u = 1'b0;
always @(posedge i_clk)
// The bit is automatically cleared on release from interrupt
// or reset
if ((i_rst)||(w_release_from_interrupt))
ill_err_u <= 1'b0;
r_ill_err_u <= 1'b0;
// If the supervisor (or debugger) writes to this register,
// clearing the bit, then clear it
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)&&(wr_write_ucc))
ill_err_u <=((ill_err_u)&&(wr_spreg_vl[`CPU_ILL_BIT]));
r_ill_err_u <=((ill_err_u)&&(wr_spreg_vl[`CPU_ILL_BIT]));
else if ((alu_illegal)&&(alu_gie)&&(!clear_pipeline))
ill_err_u <= 1'b1;
r_ill_err_u <= 1'b1;
`endif
`else
assign ill_err_u = 1'b0;
assign ill_err_i = 1'b0;
1607,16 → 1704,24
else if ((bus_err)&&(~alu_gie))
ibus_err_flag <= 1'b1;
// User bus error flag -- if ever set, it will cause an interrupt to
// supervisor mode.
initial ubus_err_flag = 1'b0;
// supervisor mode.
`ifdef OPT_NO_USERMODE
assign ubus_err_flag = 1'b0;
`else
reg r_ubus_err_flag;
 
initial r_ubus_err_flag = 1'b0;
always @(posedge i_clk)
if ((i_rst)||(w_release_from_interrupt))
ubus_err_flag <= 1'b0;
r_ubus_err_flag <= 1'b0;
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)&&(wr_write_ucc))
ubus_err_flag <= (ubus_err_flag)&&(wr_spreg_vl[`CPU_BUSERR_BIT]);
r_ubus_err_flag <= (ubus_err_flag)&&(wr_spreg_vl[`CPU_BUSERR_BIT]);
else if ((bus_err)&&(alu_gie))
ubus_err_flag <= 1'b1;
r_ubus_err_flag <= 1'b1;
 
assign ubus_err_flag = r_ubus_err_flag;
`endif
 
generate
if (IMPLEMENT_DIVIDE != 0)
begin
1633,6 → 1738,11
r_idiv_err_flag <= (r_idiv_err_flag)&&(wr_spreg_vl[`CPU_DIVERR_BIT]);
else if ((div_error)&&(~alu_gie))
r_idiv_err_flag <= 1'b1;
 
assign idiv_err_flag = r_idiv_err_flag;
`ifdef OPT_NO_USERMODE
assign udiv_err_flag = 1'b0;
`else
// User divide (by zero) error flag -- if ever set, it will
// cause a sudden switch interrupt to supervisor mode.
initial r_udiv_err_flag = 1'b0;
1645,8 → 1755,8
else if ((div_error)&&(alu_gie))
r_udiv_err_flag <= 1'b1;
 
assign idiv_err_flag = r_idiv_err_flag;
assign udiv_err_flag = r_udiv_err_flag;
`endif
end else begin
assign idiv_err_flag = 1'b0;
assign udiv_err_flag = 1'b0;
1686,15 → 1796,23
end endgenerate
 
`ifdef OPT_VLIW
reg r_ihalt_phase, r_uhalt_phase;
reg r_ihalt_phase;
 
initial r_ihalt_phase = 0;
initial r_uhalt_phase = 0;
always @(posedge i_clk)
if (i_rst)
r_ihalt_phase <= 1'b0;
else if ((~alu_gie)&&(alu_pc_valid)&&(~clear_pipeline))
r_ihalt_phase <= alu_phase;
 
assign ihalt_phase = r_ihalt_phase;
 
`ifdef OPT_NO_USERMODE
assign uhalt_phase = 1'b0;
`else
reg r_uhalt_phase;
 
initial r_uhalt_phase = 0;
always @(posedge i_clk)
if ((i_rst)||(w_release_from_interrupt))
r_uhalt_phase <= 1'b0;
1703,8 → 1821,8
else if ((~alu_gie)&&(wr_reg_ce)&&(wr_write_ucc))
r_uhalt_phase <= wr_spreg_vl[`CPU_PHASE_BIT];
 
assign ihalt_phase = r_ihalt_phase;
assign uhalt_phase = r_uhalt_phase;
`endif
`else
assign ihalt_phase = 1'b0;
assign uhalt_phase = 1'b0;
1720,13 → 1838,20
// What happens when the pipeline has gie and ~gie instructions within
// it? Do we clear both? What if a gie instruction tries to clear
// a non-gie instruction?
`ifdef OPT_NO_USERMODE
assign upc = {(AW){1'b0}};
`else
reg [(AW-1):0] r_upc;
 
always @(posedge i_clk)
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc))
upc <= wr_spreg_vl[(AW-1):0];
r_upc <= wr_spreg_vl[(AW-1):0];
else if ((alu_gie)&&
(((alu_pc_valid)&&(~clear_pipeline)&&(!alu_illegal))
||(mem_pc_valid)))
upc <= alu_pc;
r_upc <= alu_pc;
assign upc = r_upc;
`endif
 
always @(posedge i_clk)
if (i_rst)
1734,7 → 1859,7
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_pc))
ipc <= wr_spreg_vl[(AW-1):0];
else if ((~alu_gie)&&
(((alu_pc_valid)&&(~clear_pipeline))
(((alu_pc_valid)&&(~clear_pipeline)&&(!alu_illegal))
||(mem_pc_valid)))
ipc <= alu_pc;
 
1759,19 → 1884,6
pf_pc <= alu_pc;
`endif
 
initial new_pc = 1'b1;
always @(posedge i_clk)
if ((i_rst)||(i_clear_pf_cache))
new_pc <= 1'b1;
else if (w_switch_to_interrupt)
new_pc <= 1'b1;
else if (w_release_from_interrupt)
new_pc <= 1'b1;
else if ((wr_reg_ce)&&(wr_reg_id[4] == gie)&&(wr_write_pc))
new_pc <= 1'b1;
else
new_pc <= 1'b0;
 
`ifdef OPT_PIPELINED
reg r_clear_icache;
initial r_clear_icache = 1'b1;
1784,42 → 1896,65
r_clear_icache <= 1'b0;
assign w_clear_icache = r_clear_icache;
`else
assign w_clear_icache = 1'b0;
assign w_clear_icache = i_clear_pf_cache;
`endif
 
initial new_pc = 1'b1;
always @(posedge i_clk)
if ((i_rst)||(w_clear_icache))
new_pc <= 1'b1;
else if (w_switch_to_interrupt)
new_pc <= 1'b1;
else if (w_release_from_interrupt)
new_pc <= 1'b1;
else if ((wr_reg_ce)&&(wr_reg_id[4] == gie)&&(wr_write_pc))
new_pc <= 1'b1;
else
new_pc <= 1'b0;
 
//
// The debug interface
wire [31:0] w_debug_pc;
generate
`ifdef OPT_NO_USERMODE
if (AW<32)
assign w_debug_pc = {{(32-AW){1'b0}},ipc};
else
assign w_debug_pc = ipc;
`else
if (AW<32)
assign w_debug_pc = {{(32-AW){1'b0}},(i_dbg_reg[4])?upc:ipc};
else
assign w_debug_pc = (i_dbg_reg[4])?upc:ipc;
`endif
endgenerate
always @(posedge i_clk)
begin
always @(posedge i_clk)
`ifdef OPT_NO_USERMODE
o_dbg_reg <= regset[i_dbg_reg[3:0]];
if (i_dbg_reg[3:0] == `CPU_PC_REG)
o_dbg_reg <= w_debug_pc;
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
begin
o_dbg_reg <= regset[i_dbg_reg];
if (i_dbg_reg[3:0] == `CPU_PC_REG)
o_dbg_reg <= {{(32-AW){1'b0}},(i_dbg_reg[4])?upc:ipc};
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
o_dbg_reg[14:0] <= w_iflags;
o_dbg_reg[15] <= 1'b0;
o_dbg_reg[31:23] <= w_cpu_info;
o_dbg_reg[`CPU_GIE_BIT] <= gie;
end
end else begin
always @(posedge i_clk)
`else
o_dbg_reg <= regset[i_dbg_reg];
if (i_dbg_reg[3:0] == `CPU_PC_REG)
o_dbg_reg <= w_debug_pc;
else if (i_dbg_reg[3:0] == `CPU_CC_REG)
begin
o_dbg_reg <= regset[i_dbg_reg];
if (i_dbg_reg[3:0] == `CPU_PC_REG)
o_dbg_reg <= (i_dbg_reg[4])?upc:ipc;
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
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
end endgenerate
`endif
end
 
always @(posedge i_clk)
o_dbg_cc <= { o_break, bus_err, gie, sleep };
1908,7 → 2043,7
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,
w_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,
/trunk/rtl/enetpackets.v
200,8 → 200,10
reg [(MAW+1):0] tx_len;
 
`ifdef RX_SYNCHRONOUS_WITH_WB_CLK
wire rx_broadcast;
wire [(MAW+1):0] rx_len;
`else
(* ASYNC_REG = "TRUE" *) reg rx_broadcast;
(* ASYNC_REG = "TRUE" *) reg [(MAW+1):0] rx_len;
`endif
 
303,7 → 305,9
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,
assign w_rx_ctrl = { 4'h0, w_maw, {(24-20){1'b0}},
(rx_valid)&&(rx_broadcast)&&(!rx_clear),
rx_crcerr, rx_err,
rx_miss, rx_busy, (rx_valid)&&(!rx_clear),
{(14-MAW-2){1'b0}}, rx_len };
 
683,6 → 687,7
assign rx_busy = n_rx_busy;
assign rx_valid = n_rx_valid;
assign rx_len = n_rx_len;
assign rx_broadcast = n_rx_broadcast;
`else
reg r_rx_busy, r_rx_valid;
always @(posedge i_wb_clk)
694,6 → 699,7
rx_busy <= r_rx_busy;
 
rx_len <= n_rx_len;
rx_broadcast <= n_rx_broadcast;
end
 
`endif
/trunk/rtl/fastio.v
4,7 → 4,12
//
// Project: OpenArty, an entirely open SoC based upon the Arty platform
//
// Purpose:
// Purpose: This file is used to group all of the simple I/O registers
// together. These are the I/O registers whose values can be
// read without requesting it of any submodules, and that are guaranteed
// not to stall the bus. In general, these are items that can be read
// or written in one clock (two, if an extra delay is needed to match
// timing requirements).
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
159,11 → 164,28
initial pwr_counter = 32'h00;
always @(posedge i_clk)
if (pwr_counter[31])
pwr_counter[30:0] <= pwr_counter[30:0] + 31'h001;
pwr_counter[30:0] <= pwr_counter[30:0] + 1'b1;
else
pwr_counter[31:0] <= pwr_counter[31:0] + 31'h001;
pwr_counter[31:0] <= pwr_counter[31:0] + 1'b1;
 
//
// These pwr_counter bits are used for generating a PWM modulated
// color LED output--allowing us to create multiple different, varied,
// color LED "colors". Here, we reverse the bits, to make their
// transitions and PWM that much *less* noticable. (a 50%
// value, thus, is now an on-off-on-off-etc sequence, vice a
// sequence of 256 ons followed by a sequence of 256 offs --- it
// places the transitions into a higher frequency bracket, and costs
// us no logic to do--only a touch more pain to understand on behalf
// of the programmer.)
wire [8:0] rev_pwr_counter;
assign rev_pwr_counter[8:0] = { pwr_counter[0],
pwr_counter[1], pwr_counter[2],
pwr_counter[3], pwr_counter[4],
pwr_counter[5], pwr_counter[6],
pwr_counter[7], pwr_counter[8] };
 
//
// BTNSW
//
// The button and switch control register
269,9 → 291,9
r_clr_led0_r[7:0], r_clr_led0_g[7:0], r_clr_led0_b[7:0]
};
always @(posedge i_clk)
o_clr_led0 <= { (pwr_counter[8:0] < r_clr_led0_r),
(pwr_counter[8:0] < r_clr_led0_g),
(pwr_counter[8:0] < r_clr_led0_b) };
o_clr_led0 <= { (rev_pwr_counter[8:0] < r_clr_led0_r),
(rev_pwr_counter[8:0] < r_clr_led0_g),
(rev_pwr_counter[8:0] < r_clr_led0_b) };
 
// CLR LED 1
wire [31:0] w_clr_led1;
291,9 → 313,9
r_clr_led1_r[7:0], r_clr_led1_g[7:0], r_clr_led1_b[7:0]
};
always @(posedge i_clk)
o_clr_led1 <= { (pwr_counter[8:0] < r_clr_led1_r),
(pwr_counter[8:0] < r_clr_led1_g),
(pwr_counter[8:0] < r_clr_led1_b) };
o_clr_led1 <= { (rev_pwr_counter[8:0] < r_clr_led1_r),
(rev_pwr_counter[8:0] < r_clr_led1_g),
(rev_pwr_counter[8:0] < r_clr_led1_b) };
// CLR LED 0
wire [31:0] w_clr_led2;
reg [8:0] r_clr_led2_r, r_clr_led2_g, r_clr_led2_b;
312,9 → 334,9
r_clr_led2_r[7:0], r_clr_led2_g[7:0], r_clr_led2_b[7:0]
};
always @(posedge i_clk)
o_clr_led2 <= { (pwr_counter[8:0] < r_clr_led2_r),
(pwr_counter[8:0] < r_clr_led2_g),
(pwr_counter[8:0] < r_clr_led2_b) };
o_clr_led2 <= { (rev_pwr_counter[8:0] < r_clr_led2_r),
(rev_pwr_counter[8:0] < r_clr_led2_g),
(rev_pwr_counter[8:0] < r_clr_led2_b) };
// CLR LED 3
wire [31:0] w_clr_led3;
reg [8:0] r_clr_led3_r, r_clr_led3_g, r_clr_led3_b;
333,9 → 355,9
r_clr_led3_r[7:0], r_clr_led3_g[7:0], r_clr_led3_b[7:0]
};
always @(posedge i_clk)
o_clr_led3 <= { (pwr_counter[8:0] < r_clr_led3_r),
(pwr_counter[8:0] < r_clr_led3_g),
(pwr_counter[8:0] < r_clr_led3_b) };
o_clr_led3 <= { (rev_pwr_counter[8:0] < r_clr_led3_r),
(rev_pwr_counter[8:0] < r_clr_led3_g),
(rev_pwr_counter[8:0] < r_clr_led3_b) };
 
//
// The Calendar DATE
463,7 → 485,23
r_gpstx_data };
assign gpstx_int = !gpstx_busy;
 
reg [32:0] sec_step;
initial sec_step = 33'h1;
always @(posedge i_clk)
if ((w_wb_stb)&&(w_wb_addr == 5'h12))
sec_step <= { 1'b1, w_wb_data };
else if (!pps_int)
sec_step <= 33'h1;
 
reg [31:0] time_now_secs;
initial time_now_secs = 32'h00;
always @(posedge i_clk)
if (pps_int)
time_now_secs <= time_now_secs + sec_step[31:0];
else if (sec_step[32])
time_now_secs <= time_now_secs + sec_step[31:0];
 
always @(posedge i_clk)
case(i_wb_addr)
5'h00: o_wb_data <= `DATESTAMP;
5'h01: o_wb_data <= pic_data;
483,13 → 521,9
5'h0f: o_wb_data <= auxtx_data;
5'h10: o_wb_data <= gpsrx_data;
5'h11: o_wb_data <= gpstx_data;
// 5'h12: o_wb_data <= i_gps_secs;
5'h12: o_wb_data <= time_now_secs;
5'h13: o_wb_data <= i_gps_sub;
5'h14: o_wb_data <= i_gps_step;
// 5'hf: UART_SETUP
// 4'h6: GPIO
// ?? : GPS-UARTRX
// ?? : GPS-UARTTX
default: o_wb_data <= 32'h00;
endcase
 
/trunk/sw/board/Makefile
31,12 → 31,14
##
##
.PHONY: all
PROGRAMS := exstartup oledtest gpsdump exmulti cputest
PROGRAMS := exstartup oledtest gpsdump exmulti cputest # hello
all: $(PROGRAMS)
OBJDIR := obj-zip
NM := zip-nm
RDELF := zip-readelf
CC := zip-gcc
OBJDUMP := zip-objdump
SOURCES := exstartup.c bootloader.c gpsdump.c oledtest.c exmulti.c
SOURCES := exstartup.c bootloader.c gpsdump.c oledtest.c exmulti.c # hello.c
HEADERS := artyboard.h zipsys.h
DUMPRTL := -fdump-rtl-all
DUMPTREE:= -fdump-tree-all
50,19 → 52,28
$(CC) -O3 -c -fno-builtin $< -o $@
$(OBJDIR)/%.s: %.c
$(CC) -O3 -S -fno-builtin $< -o $@
$(OBJDIR)/%.txt: $(OBJDIR)/%.o
bash -c "$(RDELF) -a $^ ; $(OBJDUMP) -S -D $^ " | tee $@
%.txt: %
$(OBJDUMP) -S -D $^ > $@
 
exstartup: exstartup.c artyboard.h zipsys.h arty.ld
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=exstartup.map exstartup.c -o exstartup
 
 
exstartup: $(OBJDIR)/exstartup.o $(OBJDIR)/bootloader.o arty.ld
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=exstartup.map $(OBJDIR)/exstartup.o $(OBJDIR)/bootloader.o -o exstartup
 
exmulti: $(OBJDIR)/exmulti.o $(OBJDIR)/bootloader.o arty.ld
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=exmulti.map $(OBJDIR)/exmulti.o $(OBJDIR)/bootloader.o -o $@
 
gpsdump: $(OBJDIR)/gpsdump.o $(OBJDIR)/bootloader.o arty.ld
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=gpsdump.map $(OBJDIR)/gpsdump.o $(OBJDIR)/bootloader.o -o $@
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=gpsdump.map $(OBJDIR)/bootloader.o $(OBJDIR)/gpsdump.o -o $@
 
hello: $(OBJDIR)/hello.o $(OBJDIR)/bootloader.o arty.ld
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=hello.map $(OBJDIR)/bootloader.o $(OBJDIR)/hello.o -o $@
 
oledtest: $(OBJDIR)/oledtest.o $(OBJDIR)/bootloader.o $(OBJDIR)/splash.o $(OBJDIR)/mug.o arty.ld
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=oledtest.map $(OBJDIR)/oledtest.o $(OBJDIR)/bootloader.o $(OBJDIR)/splash.o $(OBJDIR)/mug.o -o $@
 
exmulti: $(OBJDIR)/exmulti.o $(OBJDIR)/bootloader.o arty.ld
$(CC) -O3 -T arty.ld -fno-builtin -Wl,-Map=exmulti.map $(OBJDIR)/exmulti.o $(OBJDIR)/bootloader.o -o $@
 
cputest: $(OBJDIR)/cputest.o artyram.ld
$(CC) -O3 -T artyram.ld -fno-builtin -Wl,-Map=cputest.map $(OBJDIR)/cputest.o -o $@
 
87,6 → 98,10
$(OBJDIR)/depends.txt: $(OBJDIR)/
$(build-depends)
 
.PHONY: depends
depends:
$(build-depends)
 
$(OBJDIR)/:
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR)/; fi"
 
/trunk/sw/board/arty.ld
50,6 → 50,7
.rocode 0x4e0000 : {
_boot_address = .;
*(.start) *(.boot)
*(.text.startup)
} > flash
_kernel_image_start = . ;
.fastcode : {
58,9 → 59,10
}> blkram AT> flash
_sdram_image_start = . ;
.ramcode : {
*(.text.startup)
*(.text)
*(.rodata*) *(.strings)
*(.data) *(COMMON) *(.bss)
*(.data) *(COMMON)
}> sdram AT> flash
_sdram_image_end = . ;
.bss : {
/trunk/sw/board/artyboard.h
59,20 → 59,15
#define BUS_ZIP 0x4000
 
// DMA Interrupt parameters
#define DMA_JIFFIES (DMA_TRIGGER|0x0400)
#define DMA_TMC (DMA_TRIGGER|0x0800)
#define DMA_TMB (DMA_TRIGGER|0x0c00)
#define DMA_TMA (DMA_TRIGGER|0x1000)
#define DMA_AUX (DMA_TRIGGER|0x1400)
#define DMA_PPS (DMA_TRIGGER|0x1800)
#define DMA_NETRX (DMA_TRIGGER|0x1c00)
#define DMA_NETTX (DMA_TRIGGER|0x2000)
#define DMA_UARTRX (DMA_TRIGGER|0x2400)
#define DMA_UARTTX (DMA_TRIGGER|0x2800)
#define DMA_GPSRX (DMA_TRIGGER|0x2c00)
#define DMA_GPSTX (DMA_TRIGGER|0x3000)
#define DMA_SDCARD (DMA_TRIGGER|0x3400)
#define DMA_OLED (DMA_TRIGGER|0x3800)
#define DMA_ONPPS DMA_ONINT(6)
#define DMA_ONNETRX DMA_ONINT(7)
#define DMA_ONNETTX DMA_ONINT(8)
#define DMA_ONUARTRX DMA_ONINT(9)
#define DMA_ONUARTTX DMA_ONINT(10)
#define DMA_ONGPSRX DMA_ONINT(11)
#define DMA_ONGPSTX DMA_ONINT(12)
#define DMA_ONSDCARD DMA_ONINT(13)
#define DMA_ONOLED DMA_ONINT(14)
 
// That's our maximum number of interrupts. Any more, and we'll need to
// remove one. Don't forget, the primary interrupt source will be the SYS_
90,6 → 85,17
typedef struct {
unsigned sd_ctrl, sd_data, sd_fifo[2];
} SDCARD;
#define SD_SETAUX 0x0ff
#define SD_READAUX 0x0bf
#define SD_CMD 0x040
#define SD_FIFO_OP 0x0800 // Read only
#define SD_WRITEOP 0x0c00 // Write to the FIFO
#define SD_ALTFIFO 0x1000
#define SD_BUSY 0x4000
#define SD_ERROR 0x8000
#define SD_CLEARERR 0x8000
#define SD_READ_SECTOR ((SD_CMD|SD_CLEARERR|SD_FIFO_OP)+17)
#define SD_WRITE_SECTOR ((SD_CMD|SD_CLEARERR|SD_WRITEOP)+24)
 
typedef struct {
unsigned r_clock, r_stopwach, r_timer, r_alarm;
99,10 → 105,6
unsigned g_alpha, g_beta, g_gamma, g_step;
} GPSTRACKER;
 
typedef struct {
unsigned rxcmd, txcmd;
unsigned mac[2];
unsigned rxmiss, rxerr, rxcrc, txcol;
#define ENET_TXGO 0x004000
#define ENET_TXBUSY 0x004000
#define ENET_NOHWCRC 0x008000
122,8 → 124,24
#define ENET_RXCLRERR 0x078000
#define ENET_TXBUFLN(NET) (1<<(NET.txcmd>>24))
#define ENET_RXBUFLN(NET) (1<<(NET.rxcmd>>24))
typedef struct {
unsigned rxcmd, txcmd;
unsigned long mac;
unsigned rxmiss, rxerr, rxcrc, txcol;
} ENETPACKET;
 
 
#define OLED_PMODEN 0x0010001
#define OLED_PMODEN_OFF 0x0010000
#define OLED_IOPWR OLED_PMODEN
#define OLED_VCCEN 0x0020002
#define OLED_VCC_DISABLE 0x0020000
#define OLED_RESET 0x0040000
#define OLED_RESET_CLR 0x0040004
#define OLED_FULLPOWER (OLED_PMODEN|OLED_VCCEN|OLED_RESET_CLR)
#define OLED_POWER_DOWN (OLED_PMODEN_OFF|OLED_VCCEN|OLED_RESET_CLR)
#define OLED_BUSY(dev) (dev.o_ctrl & 1)
#define OLED_DISPLAYON 0x0af // To be sent over the control channel
typedef struct {
unsigned o_ctrl, o_a, o_b, o_data;
} OLEDRGB;
137,6 → 155,26
unsigned e_v[32];
} ENETMDIO;
 
#define MDIO_BMCR 0x00
#define MDIO_BMSR 0x01
#define MDIO_PHYIDR1 0x02
#define MDIO_PHYIDR2 0x03
#define MDIO_ANAR 0x04
#define MDIO_ANLPAR 0x05
#define MDIO_ANLPARNP 0x05 // Duplicate register address
#define MDIO_ANER 0x06
#define MDIO_ANNPTR 0x07
#define MDIO_PHYSTS 0x10
#define MDIO_FCSCR 0x14
#define MDIO_RECR 0x15
#define MDIO_PCSR 0x16
#define MDIO_RBR 0x17
#define MDIO_LEDCR 0x18
#define MDIO_PHYCR 0x19
#define MDIO_BTSCR 0x1a
#define MDIO_CDCTRL 0x1b
#define MDIO_EDCR 0x1d
 
typedef struct {
unsigned f_ereg, f_status, f_nvconfig, f_vconfig,
f_evconfig, f_flags, f_lock, f_;
144,6 → 182,18
unsigned f_otpc, f_otp[16];
} EFLASHCTRL;
 
#define EQSPI_SZPAGE 64
#define EQSPI_NPAGES 256
#define EQSPI_NSECTORS 256
#define EQSPI_SECTORSZ (EQSPI_SZPAGE * EQSPI_NPAGES)
#define EQSPI_SECTOROF(A) ((A)& (-EQSPI_SECTORSZ))
#define EQSPI_SUBSECTOROF(A) ((A)& (-1<<10))
#define EQSPI_PAGEOF(A) ((A)& (-SZPAGE))
#define EQSPI_ERASEFLAG 0xc00001be
#define EQSPI_ERASECMD(A) (EQSPI_ERASEFLAG | EQSPI_SECTOROF(A))
#define EQSPI_ENABLEWP 0x00000000
#define EQSPI_DISABLEWP 0x40000000
 
typedef struct {
int io_version, io_pic;
unsigned *io_buserr;
151,13 → 201,37
unsigned io_btnsw;
unsigned io_ledctrl;
unsigned io_auxsetup, io_gpssetup;
#define UART_PARITY_NONE 0
#define UART_PARITY_ODD 0x04000000
#define UART_PARITY_EVEN 0x05000000
#define UART_PARITY_SPACE 0x06000000
#define UART_PARITY_MARK 0x07000000
#define UART_STOP_ONEBIT 0
#define UART_STOP_TWOBITS 0x08000000
#define UART_DATA_8BITS 0
#define UART_DATA_7BITS 0x10000000
#define UART_DATA_6BITS 0x20000000
#define UART_DATA_5BITS 0x30000000
unsigned io_clrled[4];
unsigned io_rtcdate;
unsigned io_gpio;
#define GPIO_SET(X) (X |(X<<16))
#define GPIO_CLEAR(X) (X<<16)
unsigned io_uart_rx, io_uart_tx;
unsigned io_gps_rx, io_gps_tx;
#define UART_RX_BREAK 0x0800
#define UART_RX_FRAMEERR 0x0400
#define UART_RX_PARITYERR 0x0200
#define UART_RX_NOTREADY 0x0100
#define UART_RX_ERR (-256)
#define UART_TX_BUSY 0x0100
#define UART_TX_BREAK 0x0200
union {
unsigned long now;
struct { unsigned sec; unsigned sub; };
} io_tim;
unsigned io_gps_sec, io_gps_sub, io_gps_step;
unsigned io_reserved[32-21];
unsigned io_reserved[32-23];
SCOPE io_scope[4];
RTC io_rtc;
SDCARD io_sd;
182,6 → 256,9
#define SDRAM (void *)0x4000000
#define CLOCKFREQHZ 81250000
#define CLOCKFREQ_HZ CLOCKFREQHZ
#define RAMWORDS 0x800000
//
#define MEMWORDS 0x0008000
#define FLASHWORDS 0x0400000
#define SDRAMWORDS 0x4000000
 
#endif
/trunk/sw/board/artyram.ld
52,6 → 52,7
*(.start) *(.boot)
_kernel_image_start = . ;
*(.kernel)
*(.text.startup)
*(.text)
*(.rodata*) *(.strings)
*(.data) *(COMMON) *(.bss)
/trunk/sw/board/bootloader.c
13,9 → 13,10
// This particular implementation depends upon the following symbols
// being defined:
//
// void entry(void)
// int main(int argc, char **argv)
// The location where your program will start from, once fully
// loaded.
// loaded. argc will always be set to zero, and ARGV to a pointer
// to zero.
//
// _top_of_stack:
// A pointer to a location in memory which we can use for a stack.
56,6 → 57,15
// This is one past the last address in SDRAM that needs to be
// set with valid data.
//
// This pointer is made even more confusing by the fact that,
// if there is nothing allocated in SDRAM, this pointer will
// still point to block RAM. To make matters worse, the MAP
// file won't match the pointer in memory. (I spent three days
// trying to chase this down, and came up empty. Basically,
// the BFD structures may set this to point to block RAM, whereas
// the MAP--which uses different data and different methods of
// computation--may leave this pointing to SDRAM. Go figure.)
//
// _bss_image_end:
// This is the last address of memory that must be cleared upon
// startup, for which the program is assuming that it is zero.
64,6 → 74,8
// anyway--since we might be starting from a reset instead of power
// up.
//
//
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
93,8 → 105,10
////////////////////////////////////////////////////////////////////////////////
//
//
#include "zipcpu.h"
#include "zipsys.h"
#include "artyboard.h"
#include "zipsys.h"
#include "bootloader.h"
 
// A bootloader is about nothing more than copying memory from a couple
// particular locations (Flash/ROM) to other locations in memory (BLKRAM
133,32 → 147,35
//
asm("\t.section\t.start\n"
"\t.global\t_start\n"
"_start:\n"
"\tLDI\t_top_of_stack,SP\n"
"\tMOV\t_after_bootloader(PC),R0\n"
"\tBRA\tbootloader\n"
"_start:" "\t; Here's the global ZipCPU entry point upon reset/reboot\n"
"\tLDI\t_top_of_stack,SP" "\t; Set up our supervisor stack ptr\n"
"\tMOV\t_kernel_exit(PC),uPC" "\t; Set user PC pointer to somewhere valid\n"
#ifndef SKIP_BOOTLOADER
"\tMOV\t_after_bootloader(PC),R0" " ; JSR to the bootloader routine\n"
"\tBRA\t_bootloader\n"
"_after_bootloader:\n"
"\tLDI\t_top_of_stack,SP\n"
"\tOR\t0x4000,CC\n" // Clear the data cache
"\tMOV\t_kernel_exit(PC),R0\n"
"\tBRA\tentry\n"
"_kernel_exit:\n"
"\tLDI\t_top_of_stack,SP" "\t; Set up our supervisor stack ptr\n"
"\tOR\t0x4000,CC" "\t; Clear the data cache\n"
#endif
"\tCLR\tR1\n" "\t; argc = 0\n"
"\tMOV\t_argv(PC),R2\n" "\t; argv = &0\n"
"\tMOV\t_kernel_exit(PC),R0" "\t; Create somewhere the kernel can return to\n"
"\tBRA\tmain" "\t; Call the user main() function\n"
"_kernel_exit:" "\t; Main should never return. Halt here if it does\n"
"\tHALT\n"
"\tBRA\t_kernel_exit\n"
"\tBRA\t_kernel_exit" "\t; We should *never* continue following a halt, do something useful if so ??\n"
"_argv:\n"
"\t.WORD\t0,0\n"
"\t.section\t.text");
 
extern int _sdram_image_end, _sdram_image_start, _sdram,
_blkram, _flash, _bss_image_end,
_kernel_image_start, _kernel_image_end;
 
//
// We need to insist that the bootloader be kept in Flash, else it would depend
// upon running a routine from memory that ... wasn't in memory yet. For this
// purpose, we place the bootloader in a special .boot section. We'll also tell
// the linker, via the arty.ld file, that thsi .boot section needs to be placed
// the linker, via the linker script, that this .boot section needs to be placed
// into flash.
//
extern void bootloader(void) __attribute__ ((section (".boot")));
extern void _bootloader(void) __attribute__ ((section (".boot")));
 
//
// bootloader()
169,45 → 186,52
// 3. The third area isn't copied from flash, but rather it is just set to
// zero. This is sometimes called the BSS segment.
//
void bootloader(void) {
int zero = 0;
#ifndef SKIP_BOOTLOADER
void _bootloader(void) {
int *sdend = _sdram_image_end, *bsend = _bss_image_end;
if (sdend < _sdram)
sdend = _sdram;
if (bsend < sdend)
bsend = sdend;
 
#ifdef USE_DMA
zip->dma.ctrl= DMACLEAR;
zip->dma.rd = &_kernel_image_start;
if (&_kernel_image_end != &_sdram_image_start) {
zip->dma.len = &_kernel_image_end - &_blkram;
zip->dma.wr = &_blkram;
zip->dma.ctrl= DMACCOPY;
zip->z_dma.d_ctrl= DMACLEAR;
zip->z_dma.d_rd = _kernel_image_start;
if (_kernel_image_end != _blkram) {
zip->z_dma.d_len = _kernel_image_end - _blkram;
zip->z_dma.d_wr = _blkram;
zip->z_dma.d_ctrl= DMACCOPY;
 
zip->pic = SYSINT_DMAC;
while((zip->pic & SYSINT_DMAC)==0)
zip->z_pic = SYSINT_DMAC;
while((zip->z_pic & SYSINT_DMAC)==0)
;
}
 
// zip->dma.rd // Keeps the same value
zip->dma.wr = &_sdram;
if (&_sdram_image_end != &_sdram) {
zip->dma.len = &_sdram_image_end - &_sdram;
zip->dma.ctrl= DMACCOPY;
// zip->z_dma.d_rd // Keeps the same value
zip->z_dma.d_wr = _sdram;
if (sdend != _sdram) {
zip->z_dma.d_len = sdend - _sdram;
zip->z_dma.d_ctrl= DMACCOPY;
 
zip->z_pic = SYSINT_DMAC;
while((zip->z_pic & SYSINT_DMAC)==0)
;
}
 
zip->pic = SYSINT_DMAC;
while((zip->pic & SYSINT_DMAC)==0)
;
if (bsend != sdend) {
int zero = 0;
 
if (&_bss_image_end != &_sdram_image_end) {
zip->dma.len = &_bss_image_end - &_sdram_image_end;
zip->dma.rd = &zero;
// zip->dma.wr // Keeps the same value
zip->dma.ctrl = DMACCOPY;
zip->z_dma.d_len = bsend - sdend;
zip->z_dma.d_rd = &zero;
// zip->z_dma.wr // Keeps the same value
zip->z_dma.d_ctrl = DMACCOPY;
 
zip->pic = SYSINT_DMAC;
while((zip->pic & SYSINT_DMAC)==0)
zip->z_pic = SYSINT_DMAC;
while((zip->z_pic & SYSINT_DMAC)==0)
;
}
#else
int *rdp = &_kernel_image_start, *wrp = &_blkram;
int *rdp = _kernel_image_start, *wrp = _blkram;
 
//
// Load any part of the image into block RAM, but *only* if there's a
216,8 → 240,8
// It starts at _kernel_image_start --- our last valid address within
// the flash address region.
//
if (&_kernel_image_end != &_sdram_image_start) {
for(int i=0; i< &_kernel_image_end - &_blkram; i++)
if (_kernel_image_end != _blkram) {
for(int i=0; i< _kernel_image_end - _blkram; i++)
*wrp++ = *rdp++;
}
 
227,8 → 251,8
// As with the last pointer, this one is also created for us by the
// linker.
//
wrp = &_sdram;
for(int i=0; i< &_sdram_image_end - &_sdram; i++)
wrp = _sdram;
for(int i=0; i< sdend - _sdram; i++)
*wrp++ = *rdp++;
 
//
237,8 → 261,10
// initialization is expected within it. We start writing where
// the valid SDRAM context, i.e. the non-zero contents, end.
//
for(int i=0; i<&_bss_image_end - &_sdram_image_end; i++)
for(int i=0; i<bsend - sdend; i++)
*wrp++ = 0;
 
#endif
}
#endif
 
/trunk/sw/board/cputest.c
33,6 → 33,7
///////////////////////////////////////////////////////////////////////////////
//
//
#include "zipcpu.h"
#include "zipsys.h"
#include "artyboard.h"
 
42,9 → 43,9
 
static volatile int *const UARTTX = &((IOSPACE *)0x0100)->io_uart_tx,
*const UART_CTRL = &((IOSPACE *)0x0100)->io_auxsetup;
static volatile int * const PIC = (volatile int *)0xc0000000;
static volatile int * const PIC = (volatile int *)0xff000000;
static const int INT_UARTTX = SYSINT_UARTTX; // 0x2000;
static volatile int *const COUNTER = &((ZIPSYS *)ZIPSYS_ADDR)->m.ck;
static volatile int *const COUNTER = &((ZIPSYS *)ZIPSYS_ADDR)->z_m.ac_ck;
 
#define HAVE_COUNTER
#define HAVE_SCOPE
54,6 → 55,7
#define PREPARE_SCOPE SCOPE_DELAY
 
unsigned zip_ucc(void);
unsigned zip_cc(void);
void zip_save_context(int *);
void zip_halt(void);
 
119,8 → 121,8
"\tMOV\tR3,uR8\n"
"\tMOV\tR3,uR9\n"
"\tMOV\tR3,uR10\n"
"\tMOV\tR3,uR11\n" // uR11 = pc
"\tMOV\tR3,uR12\n" // uR12 = pc
"\tMOV\tR3,uR11\n"
"\tMOV\tR3,uR12\n"
"\tMOV\tR2,uSP\n" // uSP = stack
"\tMOV\t0x20+R3,uCC\n" // Clear uCC of all but the GIE bit
"\tMOV\tR1,uPC\n" // uPC = pc
180,6 → 182,15
"\tJMP\tR0\n"
"\tBREAK\n");
 
void break_three(void);
// Can we jump to a break, and still have the uPC match
asm("\t.text\n\t.global\tbreak_three\n"
"\t.type\tbreak_three,@function\n"
// R1 = 0 by default from calling. This will return as though
// we had succeeded.
"break_three:\n"
"\tBREAK\n");
 
void early_branch_test(void);
asm("\t.text\n\t.global\tearly_branch_test\n"
"\t.type\tearly_branch_test,@function\n"
1137,6 → 1148,10
txreg("uPC : ", context[15]);
txstr("\r\n\r\n");
 
// While previous versions of cputest.c called zip_busy(), here we
// reject that notion for the simple reason that zip_busy may not
// necessarily halt any Verilator simulation. Instead, we try to
// halt the CPU.
while(1)
zip_halt();
}
1203,6 → 1218,17
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0; // #1
 
// Test break instruction in user mode
// Make sure that a decision on the clock prior won't still cause a
// break condition
testid("Break test #3"); MARKSTART;
run_test(break_three, user_stack_ptr);
if ((context[15] != (int)break_three) // Insist we stop at the break
||(0==(zip_ucc()&0x80)) // insn, that the break flag is
||(zip_ucc()&0x01d10)) // set, and no other excpt flags
test_fails(start_time, &testlist[tnum]);
txstr("Pass\r\n"); testlist[tnum++] = 0; // 0
 
// LJMP test ... not (yet) written
 
// Test the early branching capability
/trunk/sw/board/exmulti.c
37,8 → 37,9
////////////////////////////////////////////////////////////////////////////////
//
//
#include "zipcpu.h"
#include "zipsys.h"
#include "artyboard.h"
#include "zipsys.h"
 
void idle_task(void) {
while(1)
46,8 → 47,8
}
 
void wait_on_interrupt(int mask) {
zip->pic = DALLPIC|mask;
zip->pic = EINT(mask);
zip->z_pic = DALLPIC|mask;
zip->z_pic = EINT(mask);
zip_rtu();
}
 
111,10 → 112,10
 
int errstring[128];
 
void entry(void) {
void main(int argc, char **argv) {
const unsigned red = 0x0ff0000, green = 0x0ff00, blue = 0x0ff,
white = 0x070707, black = 0, dimgreen = 0x1f00,
second = 81250000;
second = CLOCKFREQHZ;
int i, sw;
 
// Start the GPS converging ...
136,12 → 137,12
//
// Acknowledge all interrupts, turn off all interrupts
//
zip->pic = 0x7fff7fff;
zip->z_pic = CLEARPIC;
while(sys->io_pwrcount < (second >> 4))
;
 
// Repeating timer, every 250ms
zip->tma = (second/4) | 0x80000000;
zip->z_tma = TMR_INTERVAL | (second/4);
wait_on_interrupt(SYSINT_TMA);
 
sys->io_clrled[0] = green;
151,7 → 152,7
 
sys->io_clrled[0] = dimgreen;
sys->io_clrled[1] = green;
sys->io_scope[0].s_ctrl = 32 | 0x80000000; // SCOPE_TRIGGER;
sys->io_scope[0].s_ctrl = SCOPE_NO_RESET | 32;
sys->io_ledctrl = 0x020;
 
wait_on_interrupt(SYSINT_TMA);
199,12 → 200,12
 
do {
wait_on_interrupt(SYSINT_PPS|SYSINT_TMA);
} while((zip->pic & SYSINT_PPS)==0);
} while((zip->z_pic & SYSINT_PPS)==0);
while(1) {
int *s = errstring;
 
zip->wdt = CLOCKFREQ_HZ*4;
zip->z_wdt = CLOCKFREQ_HZ*4;
sys->io_ledctrl = 0x088;
 
// 1. Read and report the GPS tracking err
321,11 → 322,11
*s++ = '\0';
 
/*
zip->dma.ctrl = DMACLEAR;
zip->dma.rd = errstring;
zip->dma.wr = &sys->io_uart_tx;
zip->dma.len = s - errstring-1;
zip->dma.ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_GPSRX);
zip->z_dma.d_ctrl = DMACLEAR;
zip->z_dma.d_rd = errstring;
zip->z_dma.d_wr = &sys->io_uart_tx;
zip->z_dma.d_len = s - errstring-1;
zip->z_dma.d_ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_GPSRX);
wait_on_interrupt(SYSINT_DMAC);
*/
 
332,16 → 333,16
for(int i=0; errstring[i]; i++) {
wait_on_interrupt(SYSINT_UARTTX);
sys->io_uart_tx = errstring[i];
zip->pic = SYSINT_UARTTX;
zip->z_pic = SYSINT_UARTTX;
}
 
sys->io_ledctrl = 0x080;
 
/*
zip->dma.rd = &sys->io_gps_rx;
zip->dma.wr = &sys->io_uart_tx;
zip->dma.len = 0x01000000;
zip->dma.ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_CONSTSRC|DMA_GPSRX);
zip->z_dma.d_rd = &sys->io_gps_rx;
zip->z_dma.d_wr = &sys->io_uart_tx;
zip->z_dma.d_len = 0x01000000;
zip->z_dma.d_ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_CONSTSRC|DMA_ONGPSRX);
wait_on_interrupt(SYSINT_PPS);
*/
 
354,17 → 355,17
}
*/
 
zip->pic = SYSINT_GPSRX | SYSINT_PPS;
zip->z_pic = SYSINT_GPSRX | SYSINT_PPS;
do {
wait_on_interrupt(SYSINT_PPS|SYSINT_GPSRX);
if (zip->pic & SYSINT_GPSRX) {
if (zip->z_pic & SYSINT_GPSRX) {
sys->io_uart_tx = sys->io_gps_rx;
zip->pic = SYSINT_GPSRX;
zip->z_pic = SYSINT_GPSRX;
}
} while((zip->pic & SYSINT_PPS)==0);
} while((zip->z_pic & SYSINT_PPS)==0);
 
// wait_on_interrupt(SYSINT_PPS);
// zip->dma.ctrl= DMACLEAR;
// zip->z_dma.d_ctrl= DMACLEAR;
}
 
zip_halt();
/trunk/sw/board/exstartup.c
37,111 → 37,26
////////////////////////////////////////////////////////////////////////////////
//
//
#include "zipcpu.h"
#include "zipsys.h"
#include "artyboard.h"
#include "zipsys.h"
 
asm("\t.section\t.start\n"
"\t.global\t_start\n"
"_start:\n"
"\tLDI\t_top_of_stack,SP\n"
"\tMOV\t_after_bootloader(PC),R0\n"
"\tBRA\tbootloader\n"
"_after_bootloader:\n"
"\tLDI\t_top_of_stack,SP\n"
"\tOR\t0x4000,CC\n" // Clear the data cache
"\tMOV\t_kernel_exit(PC),R0\n"
"\tBRA\tentry\n"
"_kernel_exit:\n"
"\tHALT\n"
"\tBRA\t_kernel_exit\n"
"\t.section\t.text");
 
extern int _sdram_image_end, _sdram_image_start, _sdram,
_blkram, _flash, _bss_image_end,
_kernel_image_start, _kernel_image_end;
 
extern void bootloader(void) __attribute__ ((section (".boot")));
 
// #define USE_DMA
void bootloader(void) {
int zero = 0;
 
#ifdef USE_DMA
zip->dma.ctrl= DMACLEAR;
zip->dma.rd = _kernel_image_start;
if (_kernel_image_end != _sdram_image_start) {
zip->dma.len = _kernel_image_end - _blkram;
zip->dma.wr = _blkram;
zip->dma.ctrl= DMACCOPY;
 
zip->pic = SYSINT_DMAC;
while((zip->pic & SYSINT_DMAC)==0)
;
}
 
zip->dma.len = &_sdram_image_end - _sdram;
zip->dma.wr = _sdram;
zip->dma.ctrl= DMACCOPY;
 
zip->pic = SYSINT_DMAC;
while((zip->pic & SYSINT_DMAC)==0)
;
 
if (_bss_image_end != _sdram_image_end) {
zip->dma.len = _bss_image_end - _sdram_image_end;
zip->dma.rd = &zero;
// zip->dma.wr // Keeps the same value
zip->dma.ctrl = DMACCOPY;
 
zip->pic = SYSINT_DMAC;
while((zip->pic & SYSINT_DMAC)==0)
;
}
#else
int *rdp = &_kernel_image_start, *wrp = &_blkram;
 
//
// Load any part of the image into block RAM, but *only* if there's a
// block RAM section in the image. Based upon our LD script, the
// block RAM should be filled from _blkram to _kernel_image_end.
// It starts at _kernel_image_start --- our last valid address within
// the flash address region.
//
if (&_kernel_image_end != &_sdram_image_start) {
for(int i=0; i< &_kernel_image_end - &_blkram; i++)
*wrp++ = *rdp++;
}
 
//
// Now, we move on to the SDRAM image. We'll here load into SDRAM
// memory up to the end of the SDRAM image, _sdram_image_end.
// As with the last pointer, this one is also created for us by the
// linker.
//
wrp = &_sdram;
for(int i=0; i< &_sdram_image_end - &_sdram; i++)
*wrp++ = *rdp++;
 
//
// Finally, we load BSS. This is the segment that only needs to be
// cleared to zero. It is available for global variables, but some
// initialization is expected within it. We start writing where
// the valid SDRAM context, i.e. the non-zero contents, end.
//
for(int i=0; i<&_bss_image_end - &_sdram_image_end; i++)
*wrp++ = 0;
#endif
}
 
void idle_task(void) {
while(1)
zip_idle();
}
 
void entry(void) {
void wait_on_interrupt(int mask) {
zip->z_pic = DALLPIC|mask;
zip->z_pic = EINT(mask);
zip_rtu();
}
 
 
void main(int argc, char **argv) {
const unsigned red = 0x0ff0000, green = 0x0ff00, blue = 0x0ff,
white = 0x070707, black = 0, dimgreen = 0x1f00,
second = 81250000;
second = CLOCKFREQHZ;
int i, sw;
 
int user_context[16];
158,59 → 73,48
//
// Acknowledge all interrupts, turn off all interrupts
//
zip->pic = 0x7fff7fff;
zip->z_pic = CLEARPIC;
while(sys->io_pwrcount < (second >> 4))
;
 
// Repeating timer, every 250ms
zip->tma = (second/4) | 0x80000000;
// zip->tma = 1024 | 0x80000000;
// Restart the PIC -- listening for SYSINT_TMA only
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
zip->z_tma = TMR_INTERVAL | (second/4);
wait_on_interrupt(SYSINT_TMA);
 
sys->io_clrled[0] = green;
sys->io_ledctrl = 0x010;
 
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
wait_on_interrupt(SYSINT_TMA);
 
sys->io_clrled[0] = dimgreen;
sys->io_clrled[1] = green;
sys->io_scope[0].s_ctrl = 32 | 0x80000000; // SCOPE_TRIGGER;
sys->io_scope[0].s_ctrl = SCOPE_NO_RESET | 32;
sys->io_ledctrl = 0x020;
 
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
wait_on_interrupt(SYSINT_TMA);
 
sys->io_clrled[1] = dimgreen;
sys->io_clrled[2] = green;
sys->io_ledctrl = 0x040;
 
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
wait_on_interrupt(SYSINT_TMA);
 
sys->io_clrled[2] = dimgreen;
sys->io_clrled[3] = green;
sys->io_ledctrl = 0x080;
 
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
wait_on_interrupt(SYSINT_TMA);
 
sys->io_clrled[3] = dimgreen;
 
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
wait_on_interrupt(SYSINT_TMA);
 
for(i=0; i<4; i++)
sys->io_clrled[i] = black;
 
// Wait one second ...
for(i=0; i<4; i++) {
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
}
for(i=0; i<4; i++)
wait_on_interrupt(SYSINT_TMA);
 
sw = sys->io_btnsw & 0x0f;
for(int i=0; i<4; i++)
217,33 → 121,28
sys->io_clrled[i] = (sw & (1<<i)) ? white : black;
 
 
// Wait another two second ...
for(i=0; i<8; i++) {
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
}
// Wait another two seconds ...
for(i=0; i<8; i++)
wait_on_interrupt(SYSINT_TMA);
 
// Blink all the LEDs
// First turn them on
sys->io_ledctrl = 0x0ff;
// Then wait a quarter second
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
wait_on_interrupt(SYSINT_TMA);
// Then turn the back off
sys->io_ledctrl = 0x0f0;
// and wait another quarter second
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
wait_on_interrupt(SYSINT_TMA);
 
// Now, read buttons, and flash an LED on any button being held
// down ... ? neat?
 
// zip->tma = 20000000; // 1/4 second -- already set
while(1) {
unsigned btn, ledc;
 
zip_rtu();
zip->pic = EINT(SYSINT_TMA)|SYSINT_TMA;
zip->z_pic = EINT(SYSINT_TMA)|SYSINT_TMA;
// If the button is pressed, toggle the LED
// Otherwise, turn the LED off.
//
/trunk/sw/board/gpsdump.c
35,41 → 35,44
////////////////////////////////////////////////////////////////////////////////
//
//
#include "zipcpu.h"
#include "zipsys.h"
#include "artyboard.h"
 
void entry(void) {
/*
void main(int argc, char **argv) {
/*
// Method one: direct polling
while(1) {
int ch;
ch = sys->io_gps_rx;
if ((ch&-256)==0)
if ((ch&UART_RX_ERR)==0)
sys->io_uart_tx = ch;
}
*/
*/
 
// Method two: Waiting on interrupts
zip->pic = SYSINT_GPSRX;
zip->z_pic = SYSINT_GPSRX;
while(1) {
while((zip->pic & SYSINT_GPSRX)==0)
while((zip->z_pic & SYSINT_GPSRX)==0)
;
sys->io_uart_tx = sys->io_gps_rx;
zip->pic = SYSINT_GPSRX;
zip->z_pic = SYSINT_GPSRX;
}
 
/*
// Method three: Use the DMA
zip->dma.ctrl = DMACLEAR;
zip->z_dma.d_ctrl = DMACLEAR;
while(1) {
zip->dma.rd = &sys->io_gps_rx;
zip->dma.wr = &sys->io_uart_tx;
zip->dma.len = 0x01000000; // More than we'll ever do ...
zip->dma.ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_CONSTSRC|DMA_GPSRX);
// zip->dma.ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_CONSTSRC);
zip->z_dma.d_rd = (int *)&sys->io_gps_rx;
zip->z_dma.d_wr = (int *)&sys->io_uart_tx;
zip->z_dma.d_len = 0x01000000; // More than we'll ever do ...
zip->z_dma.d_ctrl = (DMAONEATATIME|DMA_CONSTDST|DMA_CONSTSRC|DMA_ONGPSRX);
 
while(zip->dma.ctrl & 0x80000000)
if (zip->dma.ctrl & 0x40000000)
zip_halt();;
while(zip->z_dma.d_ctrl & DMA_BUSY) {
zip_idle();
if (zip->z_dma.d_ctrl & DMA_ERR)
zip_halt();
}
}
*/
}
/trunk/sw/board/oledtest.c
39,7 → 39,7
////////////////////////////////////////////////////////////////////////////////
//
//
 
#include "zipcpu.h"
#include "zipsys.h"
#include "artyboard.h"
 
50,21 → 50,8
 
extern int splash[], mug[];
 
#define OLED_PMODEN 0x0010001
#define OLED_PMODEN_OFF 0x0010000
#define OLED_IOPWR OLED_PMODEN
#define OLED_VCCEN 0x0020002
#define OLED_VCC_DISABLE 0x0020000
#define OLED_RESET 0x0040000
#define OLED_RESET_CLR 0x0040004
#define OLED_FULLPOWER (OLED_PMODEN|OLED_VCCEN|OLED_RESET_CLR)
#define OLED_POWER_DOWN (OLED_PMODEN_OFF|OLED_VCC_DISABLE)
#define OLED_BUSY 1
#define OLED_DISPLAYON 0x0af
 
 
#define MICROSECOND (CLOCKFREQ_HZ/1000000)
 
#define OLED_DISPLAY_OFF
 
 
78,23 → 65,23
*/
void timer_delay(int counts) {
// Clear the PIC. We want to exit from here on timer counts alone
zip->pic = CLEARPIC;
zip->z_pic = CLEARPIC;
 
if (counts > 10) {
// Set our timer to count down the given number of counts
zip->tma = counts;
zip->pic = EINT(SYSINT_TMA);
zip->z_tma = counts;
zip->z_pic = EINT(SYSINT_TMA);
zip_rtu();
zip->pic = CLEARPIC;
zip->z_pic = CLEARPIC;
} // else anything less has likely already passed
}
 
void wait_on_interrupt(int mask) {
// Clear our interrupt only, but disable all others
zip->pic = DALLPIC|mask;
zip->pic = EINT(mask);
zip->z_pic = DALLPIC|mask;
zip->z_pic = EINT(mask);
zip_rtu();
zip->pic = DINT(mask)|mask;
zip->z_pic = DINT(mask)|mask;
}
 
void oled_clear(void);
170,7 → 157,7
int i;
 
for(i=0; i<sizeof(init_sequence); i++) {
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
sys->io_oled.o_ctrl = init_sequence[i];
}
204,11 → 191,11
* (4+5), so the OLEDrgb should see: 0x25,0x00,0x00,0x5f,0x3f.
*/
void oled_clear(void) {
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
sys->io_oled.o_a = 0x5f3f0000;
sys->io_oled.o_ctrl = 0x40250000;
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
}
 
230,7 → 217,7
if (r+h > 63) h = 63-r;
 
// Enable the fill rectangle function, rather than just the outline
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
sys->io_oled.o_ctrl = 0x12601;
 
253,7 → 240,7
sys->io_oled.o_b|= ((pix ) & 0x01f)<< 1;
 
// Make certain we had finished with the port
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
 
// and send our new command. Note that o_a and o_b were already set
263,7 → 250,7
 
// To be nice to whatever routine follows, we'll wait 'til the port
// is clear again.
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
}
 
284,13 → 271,13
void oled_show_image(int *img) {
#define USE_DMA
#ifdef USE_DMA
zip->dma.len= 6144;
zip->dma.rd = img;
zip->dma.wr = (int *)&sys->io_oled.o_data;
zip->dma.ctrl = DMAONEATATIME|DMA_CONSTDST|DMA_OLED;
zip->z_dma.d_len= 6144;
zip->z_dma.d_rd = img;
zip->z_dma.d_wr = (int *)&sys->io_oled.o_data;
zip->z_dma.d_ctrl = DMAONEATATIME|DMA_CONSTDST|DMA_ONOLED;
#else
for(int i=0; i<6144; i++) {
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
sys->io_oled.o_data = img[i];
}
305,7 → 292,7
* in the bootstrap.c file, but that calls us here.
*
*/
void entry(void) {
void main(int argc, char **argv) {
 
// Since we'll be returning to userspace via zip_rtu() in order to
// wait for an interrupt, let's at least place a valid program into
318,7 → 305,7
 
// Clear the PIC. We'll come back and use it later. We clear it here
// partly in order to avoid a race condition later.
zip->pic = CLEARPIC;
zip->z_pic = CLEARPIC;
 
// Wait till we've had power for at least a quarter second
if (0) {
402,14 → 389,14
 
// Let's start our writes at the top left of the GDDRAM
// (screen memory)
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
sys->io_oled.o_ctrl = 0x2015005f; // Sets column min/max address
 
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
sys->io_oled.o_ctrl = 0x2075003f; // Sets row min/max address
while(sys->io_oled.o_ctrl & OLED_BUSY)
while(OLED_BUSY(sys->io_oled))
;
 
// Now ... finally ... we can send our image.
/trunk/sw/board/zipsys.h
40,16 → 40,17
#define ZIPSYS_H
 
typedef struct {
unsigned ck, mem, pf, icnt;
unsigned ac_ck, ac_mem, ac_pf, ac_icnt;
} ZIPTASKCTRS;
 
typedef struct {
int ctrl, len;
int *rd, *wr;
int d_ctrl, d_len;
int *d_rd, *d_wr;
} ZIPDMA;
 
#define DMA_TRIGGER 0x00008000
#define DMACLEAR 0xffed0000
#define DMACABORT 0xffed0000
#define DMACLEAR 0xafed0000
#define DMACCOPY 0x0fed0000
#define DMACERR 0x40000000
#define DMA_CONSTSRC 0x20000000
57,15 → 58,22
#define DMAONEATATIME 0x0fed0001
#define DMA_BUSY 0x80000000
#define DMA_ERR 0x40000000
#define DMA_ONINT(INT) (DMA_TRIGGER|((INT&15)<<10))
#define DMA_ONJIFFIES DMA_ONINT(1)
#define DMA_ONTMC DMA_ONINT(2)
#define DMA_ONTMB DMA_ONINT(3)
#define DMA_ONTMA DMA_ONINT(4)
#define DMA_ONAUX DMA_ONINT(5)
 
#define TMR_INTERVAL 0x80000000
typedef struct {
int pic, wdt, err, apic, tma, tmb, tmc,
jiffies;
ZIPTASKCTRS m, u;
ZIPDMA dma;
int z_pic, z_wdt, z_wbus, z_apic, z_tma, z_tmb, z_tmc,
z_jiffies;
ZIPTASKCTRS z_m, z_u;
ZIPDMA z_dma;
} ZIPSYS;
 
#define ZIPSYS_ADDR 0xc0000000
#define ZIPSYS_ADDR 0xff000000
 
#define SYSINT_DMAC 0x0001
#define SYSINT_JIFFIES 0x0002
96,59 → 104,28
#define ALTINT_SCOPE 0x1000
#define ALTINT_GPIO 0x2000
 
 
#define CC_Z 0x0001
#define CC_C 0x0002
#define CC_N 0x0004
#define CC_V 0x0008
#define CC_SLEEP 0x0010
#define CC_GIE 0x0020
#define CC_STEP 0x0040
#define CC_BREAK 0x0080
#define CC_ILL 0x0100
#define CC_TRAPBIT 0x0200
#define CC_BUSERR 0x0400
#define CC_DIVERR 0x0800
#define CC_FPUERR 0x1000
#define CC_IPHASE 0x2000
#define CC_MMUERR 0x8000
#define CC_EXCEPTION (CC_ILL|CC_BUSERR|CC_DIVERR|CC_FPUERR|CC_MMUERR)
#define CC_FAULT (CC_ILL|CC_BUSERR|CC_DIVERR|CC_FPUERR)
 
extern void zip_break(void);
extern void zip_rtu(void);
extern void zip_halt(void);
extern void zip_idle(void);
extern void zip_syscall(void);
extern void zip_restore_context(int *);
extern void zip_save_context(int *);
extern int zip_bitrev(int v);
extern unsigned zip_cc(void);
extern unsigned zip_ucc(void);
 
extern int _top_of_heap[1];
 
extern void save_context(int *);
extern void restore_context(int *);
extern int syscall(int,int,int,int);
 
#ifndef NULL
#define NULL ((void *)0)
#endif
 
#define EINT(A) (0x80000000|(A<<16))
#define DINT(A) (0x00000000|(A<<16))
#define CLEARPIC 0x7fff7fff
#define DALLPIC 0x7fff0000 // Disable all PIC interrupt sources
#define INTNOW 0x08000
 
static volatile ZIPSYS *const zip = (ZIPSYS *)(ZIPSYS_ADDR);
 
static inline void DISABLE_INTS(void) {
zip->pic = 0;
zip->z_pic = 0;
}
 
static inline void ENABLE_INTS(void) {
zip->pic = 0x80000000;
zip->z_pic = 0x80000000;
}
 
typedef struct {
int c_r[16];
unsigned long c_ck, c_mem, c_pf, c_icnt;
} ZSYSCONTEXT;
 
void save_contextncntrs(ZSYSCONTEXT *c);
void restore_contextncntrs(ZSYSCONTEXT *c);
 
#endif
/trunk/sw/host/flashdrvr.cpp
164,11 → 164,13
}
 
#define VCONF_VALUE 0x8b
#define VCONF_VALUE_ALT 0x83
 
bool FLASHDRVR::verify_config(void) {
unsigned cfg = m_fpga->readio(R_QSPI_VCONF);
// printf("CFG = %02x\n", cfg);
return (cfg == VCONF_VALUE);
if (cfg != VCONF_VALUE)
printf("Unexpected volatile configuration = %02x\n", cfg);
return ((cfg == VCONF_VALUE)||(cfg == VCONF_VALUE_ALT));
}
 
void FLASHDRVR::set_config(void) {
/trunk/sw/host/zipload.cpp
525,7 → 525,6
m_fpga->writeio(R_ZIPCTRL, CPU_HALT|CPU_sPC);
m_fpga->writeio(R_ZIPDATA, entry);
 
m_fpga->writeio(R_CPUSCOPE, 25);
printf("Starting the CPU\n");
m_fpga->writeio(R_ZIPCTRL, CPU_GO|CPU_sPC);
} else {

powered by: WebSVN 2.1.0

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