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

Subversion Repositories zipcpu

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 159 to Rev 160
    Reverse comparison

Rev 159 → Rev 160

/zipcpu/trunk/rtl/core/idecode.v
19,7 → 19,7
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
88,8 → 88,11
wire [(AW-1):0] o_dcd_branch_pc;
reg o_dcdI, o_dcdIz;
`ifdef OPT_PIPELINED
reg r_lock, r_pipe;
reg r_lock;
`endif
`ifdef OPT_PIPELINED_BUS_ACCESS
reg r_pipe;
`endif
 
 
wire [4:0] w_op;
443,7 → 446,7
// taking place, and it's only valid if the new word is not compressed.
//
reg r_valid;
`ifdef OPT_PIPELINED
`ifdef OPT_PIPELINED_BUS_ACCESS
initial r_pipe = 1'b0;
always @(posedge i_clk)
if (i_ce)
/zipcpu/trunk/rtl/core/pipemem.v
160,8 → 160,9
always @(posedge i_clk)
o_wreg <= fifo_oreg[rdaddr];
always @(posedge i_clk)
if (i_wb_ack)
o_result <= i_wb_data;
// if (i_wb_ack) isn't necessary, since o_valid won't be true
// then either.
o_result <= i_wb_data;
 
assign o_pipe_stalled = (cyc)
&&((i_wb_stall)||((~o_wb_stb_lcl)&&(~o_wb_stb_gbl)));
/zipcpu/trunk/rtl/core/div.v
12,7 → 12,7
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
44,6 → 44,10
output reg [(BW-1):0] o_quotient;
output wire [3:0] o_flags;
 
// r_busy is an internal busy register. It will clear one clock
// before we are valid, so it can't be o_busy ...
//
reg r_busy;
reg [(2*BW-2):0] r_divisor;
reg [(BW-1):0] r_dividend;
wire [(BW):0] diff; // , xdiff[(BW-1):0];
50,26 → 54,35
assign diff = r_dividend - r_divisor[(BW-1):0];
// assign xdiff= r_dividend - { 1'b0, r_divisor[(BW-1):1] };
 
reg r_sign, pre_sign, r_z, r_c;
reg [(LGBW):0] r_bit;
reg r_sign, pre_sign, r_z, r_c, last_bit;
reg [(LGBW-1):0] r_bit;
 
initial r_busy = 1'b0;
always @(posedge i_clk)
if (i_rst)
begin
r_busy <= 1'b0;
else if (i_wr)
r_busy <= 1'b1;
else if ((last_bit)||(o_err))
r_busy <= 1'b0;
 
initial o_busy = 1'b0;
always @(posedge i_clk)
if (i_rst)
o_busy <= 1'b0;
end else if (i_wr)
begin
else if (i_wr)
o_busy <= 1'b1;
end else if ((o_busy)&&((r_bit == 6'h0)||(o_err)))
else if (((last_bit)||(o_err))&&(~r_sign))
o_busy <= 1'b0;
// else busy is zero and stays at zero
else if (~r_busy)
o_busy <= 1'b0;
 
always @(posedge i_clk)
if ((i_rst)||(i_wr))
o_valid <= 1'b0;
else if (o_busy)
else if (r_busy)
begin
if ((r_bit == 6'h0)||(o_err))
if ((last_bit)||(o_err))
o_valid <= (o_err)||(~r_sign);
end else if (r_sign)
begin
85,12 → 98,26
else if (o_busy)
o_err <= (r_divisor == 0);
 
initial last_bit = 1'b0;
always @(posedge i_clk)
if ((i_wr)||(pre_sign)||(i_rst))
last_bit <= 1'b0;
else if (r_busy)
last_bit <= (r_bit == {{(LGBW-1){1'b0}},1'b1});
 
always @(posedge i_clk)
// if (i_rst) r_busy <= 1'b0;
// else
if (i_wr)
begin
//
// Set our values upon an initial command. Here's
// where we come in and start.
//
// r_busy <= 1'b1;
//
o_quotient <= 0;
// r_bit <= { 1'b1, {(LGBW){1'b0}} };
r_bit <= { 1'b0, {(LGBW){1'b1}} };
r_bit <= {(LGBW){1'b1}};
r_divisor <= { i_denominator, {(BW-1){1'b0}} };
r_dividend <= i_numerator;
r_sign <= 1'b0;
98,22 → 125,49
r_z <= 1'b1;
end else if (pre_sign)
begin
// r_bit <= r_bit - 1;
r_sign <= ((r_divisor[(2*BW-2)])^(r_dividend[(BW-1)]));;
//
// Note that we only come in here, for one clock, if
// our initial value may have been signed. If we are
// doing an unsigned divide, we then skip this step.
//
r_sign <= ((r_divisor[(2*BW-2)])^(r_dividend[(BW-1)]));
// Negate our dividend if necessary so that it becomes
// a magnitude only value
if (r_dividend[BW-1])
r_dividend <= -r_dividend;
// Do the same with the divisor--rendering it into
// a magnitude only.
if (r_divisor[(2*BW-2)])
r_divisor[(2*BW-2):(BW-1)] <= -r_divisor[(2*BW-2):(BW-1)];
//
// We only do this stage for a single clock, so go on
// with the rest of the divide otherwise.
pre_sign <= 1'b0;
end else if (o_busy)
end else if (r_busy)
begin
r_bit <= r_bit + {(LGBW+1){1'b1}}; // r_bit = r_bit - 1;
// While the divide is taking place, we examine each bit
// in turn here.
//
r_bit <= r_bit + {(LGBW){1'b1}}; // r_bit = r_bit - 1;
r_divisor <= { 1'b0, r_divisor[(2*BW-2):1] };
if (|r_divisor[(2*BW-2):(BW)])
begin
end else if (diff[BW])
begin
//
// diff = r_dividend - r_divisor[(BW-1):0];
//
// If this value was negative, there wasn't
// enough value in the dividend to support
// pulling off a bit. We'll move down a bit
// therefore and try again.
//
end else begin
//
// Put a '1' into our output accumulator.
// Subtract the divisor from the dividend,
// and then move on to the next bit
//
r_dividend <= diff[(BW-1):0];
o_quotient[r_bit[(LGBW-1):0]] <= 1'b1;
r_z <= 1'b0;
127,7 → 181,7
// Set Carry on an exact divide
wire w_n;
always @(posedge i_clk)
r_c <= (o_busy)&&((diff == 0)||(r_dividend == 0));
r_c <= (r_busy)&&((diff == 0)||(r_dividend == 0));
assign w_n = o_quotient[(BW-1)];
 
assign o_flags = { 1'b0, w_n, r_c, r_z };
/zipcpu/trunk/rtl/core/zipcpu.v
71,7 → 71,7
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
165,7 → 165,7
input i_dbg_we;
input [31:0] i_dbg_data;
// Debug interface -- outputs
output reg o_dbg_stall;
output wire o_dbg_stall;
output reg [31:0] o_dbg_reg;
output reg [3:0] o_dbg_cc;
output wire o_break;
204,7 → 204,7
// (BUS, TRAP,ILL,BREAKEN,STEP,GIE,SLEEP ), V, N, C, Z
reg [3:0] flags, iflags;
wire [13:0] w_uflags, w_iflags;
reg trap, break_en, step, gie, sleep;
reg trap, break_en, step, gie, sleep, r_halted;
`ifdef OPT_ILLEGAL_INSTRUCTION
reg ill_err_u, ill_err_i;
`else
284,7 → 284,7
wire [13:0] opFl;
reg [5:0] r_opF;
wire [7:0] opF;
wire op_ce, op_phase, op_pipe;
wire op_ce, op_phase, op_pipe, op_change_data_ce;
// Some pipeline control wires
`ifdef OPT_PIPELINED
reg opA_alu, opA_mem;
292,6 → 292,9
`endif
`ifdef OPT_ILLEGAL_INSTRUCTION
reg op_illegal;
`else
wire op_illegal;
assign op_illegal = 1'b0;
`endif
reg op_break;
wire op_lock;
346,6 → 349,12
&&(~mem_rdbusy)&&(~div_busy)&&(~fpu_busy)
&&(set_cond);
 
// ALU, DIV, or FPU CE ... equivalent to the OR of all three of these
wire adf_ce, adf_ce_unconditional;
assign adf_ce_unconditional = (master_ce)&&(~clear_pipeline)&&(opvalid)
&&(~opvalid_mem)&&(~mem_rdbusy)&&(~div_busy)
&&(~fpu_busy);
assign adf_ce = (adf_ce_unconditional)&&(set_cond);
 
//
//
354,7 → 363,7
//
wire wr_reg_ce, wr_flags_ce, wr_write_pc, wr_write_cc;
wire [4:0] wr_reg_id;
wire [31:0] wr_reg_vl;
wire [31:0] wr_gpreg_vl, wr_spreg_vl;
wire w_switch_to_interrupt, w_release_from_interrupt;
reg [(AW-1):0] upc, ipc;
 
424,9 → 433,16
||(dcdF_stall)
);
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~op_stall)&&(~clear_pipeline);
// BUT ... op_ce is too complex for many of the data operations. So
// let's make their circuit enable code simpler. In particular, if
// op_ doesn't need to be preserved, we can change it all we want
// ... right? The clear_pipeline code, for example, really only needs
// to determine whether opvalid is true.
assign op_change_data_ce = (~op_stall);
`else
assign op_stall = (opvalid)&&(~master_ce);
assign op_ce = ((dcdvalid)||(dcd_illegal))&&(~clear_pipeline);
assign op_change_data_ce = 1'b1;
`endif
 
//
450,8 → 466,7
||((opvalid)&&(op_lock)&&(op_lock_stall))
||((opvalid)&&(op_break))
||(div_busy)||(fpu_busy);
assign alu_ce = (master_ce)&&((opvalid_alu)||(op_illegal))
&&(~alu_stall)
assign alu_ce = (master_ce)&&(opvalid_alu)&&(~alu_stall)
&&(~clear_pipeline);
`else
assign alu_stall = ((~master_ce)&&(opvalid_alu))
713,10 → 728,10
`endif
 
always @(posedge i_clk)
if (op_ce) // &&(dcdvalid))
if (op_change_data_ce)
begin
if ((wr_reg_ce)&&(wr_reg_id == dcdA))
r_opA <= wr_reg_vl;
r_opA <= wr_gpreg_vl;
else if (dcdA_pc)
r_opA <= w_pcA_v;
else if (dcdA_cc)
729,9 → 744,9
// but for some reason we're stuck here as they became
// valid. Pick them up now anyway
// if (((opA_alu)&&(alu_wr))||((opA_mem)&&(mem_valid)))
// r_opA <= wr_reg_vl;
// r_opA <= wr_gpreg_vl;
if ((wr_reg_ce)&&(wr_reg_id == opA_id)&&(opA_rd))
r_opA <= wr_reg_vl;
r_opA <= wr_gpreg_vl;
`endif
end
 
744,7 → 759,7
endgenerate
 
assign w_opBnI = (~dcdB_rd) ? 32'h00
: (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_reg_vl
: (((wr_reg_ce)&&(wr_reg_id == dcdB)) ? wr_gpreg_vl
: ((dcdB_pc) ? w_pcB_v
: ((dcdB_cc) ? { w_cpu_info, w_opB[22:14], // w_opB[31:14],
(dcdB[4])?w_uflags:w_iflags}
751,11 → 766,11
: w_opB)));
 
always @(posedge i_clk)
if (op_ce) // &&(dcdvalid))
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_reg_vl;
r_opB <= wr_gpreg_vl;
`endif
 
// The logic here has become more complex than it should be, no thanks
768,7 → 783,9
// below, arriving at what we finally want in the (now wire net)
// opF.
always @(posedge i_clk)
if (op_ce)
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
begin // Set the flag condition codes, bit order is [3:0]=VNCZ
case(dcdF[2:0])
3'h0: r_opF <= 6'h00; // Always
830,7 → 847,7
opvalid_div <= (dcdDV)&&(w_opvalid);
opvalid_fpu <= (dcdFP)&&(w_opvalid);
`endif
end else if ((clear_pipeline)||(alu_ce)||(mem_ce)||(div_ce)||(fpu_ce))
end else if ((clear_pipeline)||(adf_ce_unconditional)||(mem_ce))
begin
opvalid <= 1'b0;
opvalid_alu <= 1'b0;
873,7 → 890,7
 
initial r_op_lock = 1'b0;
always @(posedge i_clk)
if (i_rst)
if ((i_rst)||(clear_pipeline))
r_op_lock <= 1'b0;
else if (op_ce)
r_op_lock <= (dcd_lock)&&(~clear_pipeline);
914,7 → 931,7
end
 
always @(posedge i_clk)
if (op_ce)
if (op_change_data_ce)
begin
opn <= dcdOp; // Which ALU operation?
// opM <= dcdM; // Is this a memory operation?
936,7 → 953,7
always @(posedge i_clk)
if ((i_rst)||(clear_pipeline))
r_op_phase <= 1'b0;
else if (op_ce)
else if (op_change_data_ce)
r_op_phase <= dcd_phase;
assign op_phase = r_op_phase;
`else
957,7 → 974,7
// the stalls will already be in place.
`ifdef OPT_PIPELINED
assign opA = ((wr_reg_ce)&&(wr_reg_id == opA_id)) // &&(opA_rd))
? wr_reg_vl : r_opA;
? wr_gpreg_vl : r_opA;
`else
assign opA = r_opA;
`endif
980,7 → 997,7
 
`ifdef OPT_PIPELINED
assign opB = ((wr_reg_ce)&&(wr_reg_id == opB_id)&&(opB_rd))
? wr_reg_vl: r_opB;
? wr_gpreg_vl: r_opB;
`else
assign opB = r_opB;
`endif
1120,7 → 1137,7
always @(posedge i_clk)
if (i_rst)
r_alu_phase <= 1'b0;
else if ((alu_ce)||(mem_ce)||(div_ce)||(fpu_ce))
else if ((adf_ce_unconditional)||(mem_ce))
r_alu_phase <= op_phase;
assign alu_phase = r_alu_phase;
`else
1128,7 → 1145,7
`endif
 
always @(posedge i_clk)
if ((alu_ce)||(div_ce)||(fpu_ce))
if (adf_ce_unconditional)
alu_reg <= opR;
else if ((i_halt)&&(i_dbg_we))
alu_reg <= i_dbg_reg;
1139,15 → 1156,16
reg dbgv;
initial dbgv = 1'b0;
always @(posedge i_clk)
dbgv <= (~i_rst)&&(~alu_ce)&&((i_halt)&&(i_dbg_we));
dbgv <= (~i_rst)&&(i_halt)&&(i_dbg_we)&&(r_halted);
reg [31:0] dbg_val;
always @(posedge i_clk)
dbg_val <= i_dbg_data;
always @(posedge i_clk)
if ((alu_ce)||(mem_ce))
if ((adf_ce_unconditional)||(mem_ce))
alu_gie <= op_gie;
always @(posedge i_clk)
if ((alu_ce)||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)
if ((adf_ce_unconditional)
||((master_ce)&&(opvalid_mem)&&(~clear_pipeline)
&&(~mem_stalled)))
alu_pc <= op_pc;
 
1167,11 → 1185,11
always @(posedge i_clk)
if (i_rst)
r_alu_pc_valid <= 1'b0;
else if (alu_ce) // Includes && (~alu_clear_pipeline)
else if (adf_ce_unconditional)//Includes&&(~alu_clear_pipeline)
r_alu_pc_valid <= 1'b1;
else if ((~alu_busy)||(clear_pipeline))
else if (((~alu_busy)&&(~div_busy)&&(~fpu_busy))||(clear_pipeline))
r_alu_pc_valid <= 1'b0;
assign alu_pc_valid = (r_alu_pc_valid)&&(~alu_busy);
assign alu_pc_valid = (r_alu_pc_valid)&&((~alu_busy)&&(~div_busy)&&(~fpu_busy));
always @(posedge i_clk)
if (i_rst)
mem_pc_valid <= 1'b0;
1263,12 → 1281,15
// Further, alu_wr includes (set_cond), so we don't need to
// check for that here either.
`ifdef OPT_ILLEGAL_INSTRUCTION
assign wr_reg_ce = (dbgv)||(~alu_illegal)&&
(((alu_wr)&&(~clear_pipeline)
&&((alu_valid)||(div_valid)||(fpu_valid)))
||(mem_valid));
assign wr_reg_ce = (dbgv)||(mem_valid)
||((~clear_pipeline)&&(~alu_illegal)
&&(((alu_wr)&&(alu_valid))
||(div_valid)||(fpu_valid)));
`else
assign wr_reg_ce = (dbgv)||((alu_wr)&&(~clear_pipeline))||(mem_valid)||(div_valid)||(fpu_valid);
assign wr_reg_ce = (dbgv)||(mem_valid)
||((~clear_pipeline)
&&(((alu_wr)&&(alu_valid))
||(div_valid)||(fpu_valid)));
`endif
// Which register shall be written?
// COULD SIMPLIFY THIS: by adding three bits to these registers,
1275,19 → 1296,21
// 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.
assign wr_reg_id = (alu_wr)?alu_reg:mem_wreg;
assign wr_reg_id = (alu_wr|div_valid|fpu_valid)?alu_reg:mem_wreg;
// Are we writing to the CC register?
assign wr_write_cc = (wr_reg_id[3:0] == `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_reg_vl = ((mem_valid) ? mem_result
assign wr_gpreg_vl = ((mem_valid) ? mem_result
:((div_valid|fpu_valid))
? ((div_valid) ? div_result:fpu_result)
:((dbgv) ? dbg_val : alu_result));
assign wr_spreg_vl = ((mem_valid) ? mem_result
:((dbgv) ? dbg_val : alu_result));
always @(posedge i_clk)
if (wr_reg_ce)
regset[wr_reg_id] <= wr_reg_vl;
regset[wr_reg_id] <= wr_gpreg_vl;
 
//
// Write back to the condition codes/flags register ...
1308,7 → 1331,7
always @(posedge i_clk)
// If explicitly writing the register itself
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_cc))
flags <= wr_reg_vl[3:0];
flags <= wr_gpreg_vl[3:0];
// Otherwise if we're setting the flags from an ALU operation
else if ((wr_flags_ce)&&(alu_gie))
flags <= (div_valid)?div_flags:((fpu_valid)?fpu_flags
1316,7 → 1339,7
 
always @(posedge i_clk)
if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_cc))
iflags <= wr_reg_vl[3:0];
iflags <= wr_gpreg_vl[3:0];
else if ((wr_flags_ce)&&(~alu_gie))
iflags <= (div_valid)?div_flags:((fpu_valid)?fpu_flags
: alu_flags);
1341,10 → 1364,11
if ((i_rst)||(i_halt))
break_en <= 1'b0;
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_cc))
break_en <= wr_reg_vl[`CPU_BREAK_BIT];
break_en <= wr_spreg_vl[`CPU_BREAK_BIT];
`ifdef OPT_ILLEGAL_INSTRUCTION
assign o_break = ((break_en)||(~op_gie))&&(op_break)
&&(~alu_valid)&&(~mem_valid)&&(~mem_busy)
&&(~alu_busy)
&&(~div_busy)&&(~fpu_busy)
&&(~clear_pipeline)
||((~alu_gie)&&(bus_err))
1354,6 → 1378,7
`else
assign o_break = (((break_en)||(~op_gie))&&(op_break)
&&(~alu_valid)&&(~mem_valid)&&(~mem_busy)
&&(~alu_busy)&&(~div_busy)&&(~fpu_busy)
&&(~clear_pipeline))
||((~alu_gie)&&(bus_err))
||((~alu_gie)&&(div_valid)&&(div_error))
1376,23 → 1401,23
// Well ... not quite. Switching to user mode and
// sleep mode shouold only be possible if the interrupt
// flag isn't set.
// Thus: if (i_interrupt)&&(wr_reg_vl[GIE])
// Thus: if (i_interrupt)&&(wr_spreg_vl[GIE])
// don't set the sleep bit
// otherwise however it would o.w. be set
sleep <= (wr_reg_vl[`CPU_SLEEP_BIT])
&&((~i_interrupt)||(~wr_reg_vl[`CPU_GIE_BIT]));
else if ((wr_reg_ce)&&(wr_write_cc)&&(wr_reg_vl[`CPU_GIE_BIT]))
sleep <= (wr_spreg_vl[`CPU_SLEEP_BIT])
&&((~i_interrupt)||(~wr_spreg_vl[`CPU_GIE_BIT]));
else if ((wr_reg_ce)&&(wr_write_cc)&&(wr_spreg_vl[`CPU_GIE_BIT]))
// In user mode, however, you can only set the sleep
// mode while remaining in user mode. You can't switch
// to sleep mode *and* supervisor mode at the same
// time, lest you halt the CPU.
sleep <= wr_reg_vl[`CPU_SLEEP_BIT];
sleep <= wr_spreg_vl[`CPU_SLEEP_BIT];
 
always @(posedge i_clk)
if ((i_rst)||(w_switch_to_interrupt))
step <= 1'b0;
else if ((wr_reg_ce)&&(~alu_gie)&&(wr_reg_id[4])&&(wr_write_cc))
step <= wr_reg_vl[`CPU_STEP_BIT];
step <= wr_spreg_vl[`CPU_STEP_BIT];
else if (((alu_pc_valid)||(mem_pc_valid))&&(step)&&(gie))
step <= 1'b0;
 
1419,12 → 1444,12
//
||(bus_err)
// If we write to the CC register
||((wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT])
||((wr_reg_ce)&&(~wr_spreg_vl[`CPU_GIE_BIT])
&&(wr_reg_id[4])&&(wr_write_cc))
);
assign w_release_from_interrupt = (~gie)&&(~i_interrupt)
// Then if we write the CC register
&&(((wr_reg_ce)&&(wr_reg_vl[`CPU_GIE_BIT])
&&(((wr_reg_ce)&&(wr_spreg_vl[`CPU_GIE_BIT])
&&(~wr_reg_id[4])&&(wr_write_cc))
);
always @(posedge i_clk)
1441,11 → 1466,11
trap <= 1'b0;
else if (w_release_from_interrupt)
trap <= 1'b0;
else if ((alu_gie)&&(wr_reg_ce)&&(~wr_reg_vl[`CPU_GIE_BIT])
else if ((alu_gie)&&(wr_reg_ce)&&(~wr_spreg_vl[`CPU_GIE_BIT])
&&(wr_write_cc)) // &&(wr_reg_id[4]) implied
trap <= 1'b1;
else if ((wr_reg_ce)&&(wr_write_cc)&&(wr_reg_id[4]))
trap <= wr_reg_vl[`CPU_TRAP_BIT];
trap <= wr_spreg_vl[`CPU_TRAP_BIT];
 
`ifdef OPT_ILLEGAL_INSTRUCTION
initial ill_err_i = 1'b0;
1454,7 → 1479,7
ill_err_i <= 1'b0;
// Only the debug interface can clear this bit
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG})
&&(~wr_reg_vl[`CPU_ILL_BIT]))
&&(~wr_spreg_vl[`CPU_ILL_BIT]))
ill_err_i <= 1'b0;
else if ((alu_pc_valid)&&(alu_illegal)&&(~alu_gie))
ill_err_i <= 1'b1;
1468,7 → 1493,7
// If the supervisor writes to this register, clearing the
// bit, then clear it
else if (((~alu_gie)||(dbgv))
&&(wr_reg_ce)&&(~wr_reg_vl[`CPU_ILL_BIT])
&&(wr_reg_ce)&&(~wr_spreg_vl[`CPU_ILL_BIT])
&&(wr_reg_id[4])&&(wr_write_cc))
ill_err_u <= 1'b0;
else if ((alu_pc_valid)&&(alu_illegal)&&(alu_gie))
1484,7 → 1509,7
if (i_rst)
ibus_err_flag <= 1'b0;
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG})
&&(~wr_reg_vl[`CPU_BUSERR_BIT]))
&&(~wr_spreg_vl[`CPU_BUSERR_BIT]))
ibus_err_flag <= 1'b0;
else if ((bus_err)&&(~alu_gie))
ibus_err_flag <= 1'b1;
1497,7 → 1522,7
else if (w_release_from_interrupt)
ubus_err_flag <= 1'b0;
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)
&&(~wr_reg_vl[`CPU_BUSERR_BIT])
&&(~wr_spreg_vl[`CPU_BUSERR_BIT])
&&(wr_reg_id[4])&&(wr_write_cc))
ubus_err_flag <= 1'b0;
else if ((bus_err)&&(alu_gie))
1516,7 → 1541,7
if (i_rst)
r_idiv_err_flag <= 1'b0;
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG})
&&(~wr_reg_vl[`CPU_DIVERR_BIT]))
&&(~wr_spreg_vl[`CPU_DIVERR_BIT]))
r_idiv_err_flag <= 1'b0;
else if ((div_error)&&(div_valid)&&(~alu_gie))
r_idiv_err_flag <= 1'b1;
1529,7 → 1554,7
else if (w_release_from_interrupt)
r_udiv_err_flag <= 1'b0;
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)
&&(~wr_reg_vl[`CPU_DIVERR_BIT])
&&(~wr_spreg_vl[`CPU_DIVERR_BIT])
&&(wr_reg_id[4])&&(wr_write_cc))
r_udiv_err_flag <= 1'b0;
else if ((div_error)&&(alu_gie)&&(div_valid))
1553,7 → 1578,7
if (i_rst)
r_ifpu_err_flag <= 1'b0;
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG})
&&(~wr_reg_vl[`CPU_FPUERR_BIT]))
&&(~wr_spreg_vl[`CPU_FPUERR_BIT]))
r_ifpu_err_flag <= 1'b0;
else if ((fpu_error)&&(fpu_valid)&&(~alu_gie))
r_ifpu_err_flag <= 1'b1;
1566,7 → 1591,7
else if (w_release_from_interrupt)
r_ufpu_err_flag <= 1'b0;
else if (((~alu_gie)||(dbgv))&&(wr_reg_ce)
&&(~wr_reg_vl[`CPU_FPUERR_BIT])
&&(~wr_spreg_vl[`CPU_FPUERR_BIT])
&&(wr_reg_id[4])&&(wr_write_cc))
r_ufpu_err_flag <= 1'b0;
else if ((fpu_error)&&(alu_gie)&&(fpu_valid))
1612,7 → 1637,7
// a non-gie instruction?
always @(posedge i_clk)
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc))
upc <= wr_reg_vl[(AW-1):0];
upc <= wr_spreg_vl[(AW-1):0];
else if ((alu_gie)&&
(((alu_pc_valid)&&(~clear_pipeline))
||(mem_pc_valid)))
1622,7 → 1647,7
if (i_rst)
ipc <= RESET_ADDRESS;
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_pc))
ipc <= wr_reg_vl[(AW-1):0];
ipc <= wr_spreg_vl[(AW-1):0];
else if ((~alu_gie)&&
(((alu_pc_valid)&&(~clear_pipeline))
||(mem_pc_valid)))
1636,7 → 1661,7
else if (w_release_from_interrupt)
pf_pc <= upc;
else if ((wr_reg_ce)&&(wr_reg_id[4] == gie)&&(wr_write_pc))
pf_pc <= wr_reg_vl[(AW-1):0];
pf_pc <= wr_spreg_vl[(AW-1):0];
`ifdef OPT_PIPELINED
else if ((dcd_early_branch)&&(~clear_pipeline))
pf_pc <= dcd_branch_pc + 1;
1696,10 → 1721,12
o_dbg_cc <= { o_break, bus_err, gie, sleep };
 
always @(posedge i_clk)
o_dbg_stall <= (i_halt)&&(
r_halted <= (i_halt)&&(
(pf_cyc)||(mem_cyc_gbl)||(mem_cyc_lcl)||(mem_busy)
||(alu_busy)||(div_busy)||(fpu_busy)
||((~opvalid)&&(~i_rst)&&(~dcd_illegal))
||((~dcdvalid)&&(~i_rst)&&(~pf_illegal)));
assign o_dbg_stall = r_halted;
 
//
//
1727,7 → 1754,7
// ||((opvalid_mem)&&(~op_pipe)&&(mem_busy))
// ||((opvalid_mem)&&( op_pipe)&&(mem_pipe_stalled)));
// opA[23:20], opA[3:0],
gie, sleep, wr_reg_ce, wr_reg_vl[4:0]
gie, sleep, wr_reg_ce, wr_gpreg_vl[4:0]
/*
i_rst, master_ce, (new_pc),
((dcd_early_branch)&&(dcdvalid)),
/zipcpu/trunk/rtl/zipsystem.v
64,7 → 64,7
//
///////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
173,7 → 173,7
parameter RESET_ADDRESS=24'h0100000, ADDRESS_WIDTH=24,
LGICACHE=10, START_HALTED=1, EXTERNAL_INTERRUPTS=1,
`ifdef OPT_MULTIPLY
IMPLEMENT_MPY = 1,
IMPLEMENT_MPY = `OPT_MULTIPLY,
`else
IMPLEMENT_MPY = 0,
`endif
369,7 → 369,8
//
wire wdt_ack, wdt_stall, wdt_reset;
wire [31:0] wdt_data;
ziptimer watchdog(i_clk, cpu_reset, ~cmd_halt,
ziptimer #(32,31,0)
watchdog(i_clk, cpu_reset, ~cmd_halt,
sys_cyc, ((sys_stb)&&(sys_addr == `WATCHDOG)), sys_we,
sys_data,
wdt_ack, wdt_stall, wdt_data, wdt_reset);
523,7 → 524,7
wire cpu_gbl_cyc;
assign dmac_stb = (sys_stb)&&(sys_addr[4]);
`ifdef INCLUDE_DMA_CONTROLLER
wbdmac #(AW) dma_controller(i_clk,
wbdmac #(AW) dma_controller(i_clk, cpu_reset,
sys_cyc, dmac_stb, sys_we,
sys_addr[1:0], sys_data,
dmac_ack, dmac_stall, dmac_data,
535,12 → 536,6
main_int_vector[14:1], 1'b0 },
// DMAC interrupt, for upon completion
dmac_int);
// Whether or not the CPU wants the bus, and
// thus we must kick the DMAC off.
// However, the logic required for this
// override never worked well, so here
// we just don't use it.
// cpu_gbl_cyc);
`else
reg r_dmac_ack;
always @(posedge i_clk)
677,8 → 672,15
wire [31:0] cpu_dbg_data;
assign cpu_dbg_we = ((dbg_cyc)&&(dbg_stb)&&(~cmd_addr[5])
&&(dbg_we)&&(dbg_addr));
zipcpu #(RESET_ADDRESS,ADDRESS_WIDTH,LGICACHE, IMPLEMENT_MPY,
IMPLEMENT_DIVIDE, IMPLEMENT_FPU, IMPLEMENT_LOCK)
zipcpu #(
.RESET_ADDRESS(RESET_ADDRESS),
.ADDRESS_WIDTH(ADDRESS_WIDTH),
.LGICACHE(LGICACHE),
.IMPLEMENT_MPY(IMPLEMENT_MPY),
.IMPLEMENT_DIVIDE(IMPLEMENT_DIVIDE),
.IMPLEMENT_FPU(IMPLEMENT_FPU),
.IMPLEMENT_LOCK(IMPLEMENT_LOCK)
)
thecpu(i_clk, cpu_reset, pic_interrupt,
cpu_halt, cmd_clear_pf_cache, cmd_addr[4:0], cpu_dbg_we,
dbg_idata, cpu_dbg_stall, cpu_dbg_data,
726,7 → 728,7
:((~cmd_addr[5])?cpu_dbg_data : wb_data);
initial dbg_ack = 1'b0;
always @(posedge i_clk)
dbg_ack <= (dbg_cyc)&&(~dbg_stall);
dbg_ack <= (dbg_cyc)&&(dbg_stb)&&(~dbg_stall);
assign dbg_stall=(dbg_cyc)&&((~sys_dbg_cyc)||(sys_stall))&&(dbg_addr);
 
// Now for the external wishbone bus
/zipcpu/trunk/rtl/peripherals/wbdmac.v
81,12 → 81,9
// Creator: Dan Gisselquist
// Gisselquist Technology, LLC
//
// Copyright: 2015
//
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
105,7 → 102,15
///////////////////////////////////////////////////////////////////////////
//
//
module wbdmac(i_clk,
`define DMA_IDLE 3'b000
`define DMA_WAIT 3'b001
`define DMA_READ_REQ 3'b010
`define DMA_READ_ACK 3'b011
`define DMA_PRE_WRITE 3'b100
`define DMA_WRITE_REQ 3'b101
`define DMA_WRITE_ACK 3'b110
 
module wbdmac(i_clk, i_rst,
i_swb_cyc, i_swb_stb, i_swb_we, i_swb_addr, i_swb_data,
o_swb_ack, o_swb_stall, o_swb_data,
o_mwb_cyc, o_mwb_stb, o_mwb_we, o_mwb_addr, o_mwb_data,
114,7 → 119,7
o_interrupt);
parameter ADDRESS_WIDTH=32, LGMEMLEN = 10,
DW=32, LGDV=5,AW=ADDRESS_WIDTH;
input i_clk;
input i_clk, i_rst;
// Slave/control wishbone inputs
input i_swb_cyc, i_swb_stb, i_swb_we;
input [1:0] i_swb_addr;
124,7 → 129,7
output wire o_swb_stall;
output reg [(DW-1):0] o_swb_data;
// Master/DMA wishbone control
output reg o_mwb_cyc, o_mwb_stb, o_mwb_we;
output wire o_mwb_cyc, o_mwb_stb, o_mwb_we;
output reg [(AW-1):0] o_mwb_addr;
output reg [(DW-1):0] o_mwb_data;
// Master/DMA wishbone responses from the bus
145,8 → 150,8
//
 
 
reg cfg_wp; // Write protect
reg cfg_err;
reg [2:0] dma_state;
reg cfg_err, cfg_len_nonzero;
reg [(AW-1):0] cfg_waddr, cfg_raddr, cfg_len;
reg [(LGMEMLEN-1):0] cfg_blocklen_sub_one;
reg cfg_incs, cfg_incd;
157,134 → 162,253
// memory block here.
 
reg [(DW-1):0] dma_mem [0:(((1<<LGMEMLEN))-1)];
reg [(LGMEMLEN):0] nread, nwritten, nacks;
wire [(AW-1):0] bus_nacks;
assign bus_nacks = { {(AW-LGMEMLEN-1){1'b0}}, nacks };
reg [(LGMEMLEN):0] nread, nwritten, nwacks, nracks;
wire [(AW-1):0] bus_nracks;
assign bus_nracks = { {(AW-LGMEMLEN-1){1'b0}}, nracks };
 
reg last_read_request, last_read_ack,
last_write_request, last_write_ack;
reg trigger, abort;
 
initial dma_state = `DMA_IDLE;
initial o_interrupt = 1'b0;
initial o_mwb_cyc = 1'b0;
initial cfg_err = 1'b0;
initial cfg_wp = 1'b0;
initial cfg_len = {(AW){1'b0}};
initial cfg_blocklen_sub_one = {(LGMEMLEN){1'b1}};
initial cfg_on_dev_trigger = 1'b0;
initial cfg_len_nonzero = 1'b0;
always @(posedge i_clk)
if ((o_mwb_cyc)&&(o_mwb_we)) // Write cycle
case(dma_state)
`DMA_IDLE: begin
o_mwb_addr <= cfg_raddr;
nwritten <= 0;
nread <= 0;
nracks <= 0;
nwacks <= 0;
cfg_len_nonzero <= (|cfg_len);
 
// 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))
begin
if ((o_mwb_stb)&&(~i_mwb_stall))
begin
nwritten <= nwritten+1;
if (nwritten == nread-1)
// Wishbone interruptus
o_mwb_stb <= 1'b0;
else if (cfg_incd) begin
o_mwb_addr <= o_mwb_addr + 1;
cfg_waddr <= cfg_waddr + 1;
case(i_swb_addr)
2'b00: begin
if ((i_swb_data[27:16] == 12'hfed)
&&(cfg_len_nonzero))
dma_state <= `DMA_WAIT;
cfg_blocklen_sub_one
<= i_swb_data[(LGMEMLEN-1):0]
+ {(LGMEMLEN){1'b1}};
// i.e. -1;
cfg_dev_trigger <= i_swb_data[14:10];
cfg_on_dev_trigger <= i_swb_data[15];
cfg_incs <= ~i_swb_data[29];
cfg_incd <= ~i_swb_data[28];
end
// o_mwb_data <= dma_mem[nwritten + 1];
end
2'b01: begin
cfg_len <= i_swb_data[(AW-1):0];
cfg_len_nonzero <= (|i_swb_data[(AW-1):0]);
end
2'b10: cfg_raddr <= i_swb_data[(AW-1):0];
2'b11: cfg_waddr <= i_swb_data[(AW-1):0];
endcase
end end
`DMA_WAIT: begin
o_mwb_addr <= cfg_raddr;
nracks <= 0;
nwacks <= 0;
nwritten <= 0;
nread <= 0;
if (abort)
dma_state <= `DMA_IDLE;
else if (trigger)
dma_state <= `DMA_READ_REQ;
end
`DMA_READ_REQ: begin
nwritten <= 0;
 
if (i_mwb_err)
begin
o_mwb_cyc <= 1'b0;
cfg_err <= 1'b1;
cfg_len <= 0;
nread <= 0;
end else if (i_mwb_ack)
begin
nacks <= nacks+1;
cfg_len <= cfg_len - 1;
if ((nacks+1 == nwritten)&&(~o_mwb_stb))
begin
o_mwb_cyc <= 1'b0;
nread <= 0;
o_interrupt <= (cfg_len == 1);
// Turn write protect back on
cfg_wp <= 1'b1;
end
end
end else if ((o_mwb_cyc)&&(~o_mwb_we)) // Read cycle
if (~i_mwb_stall)
begin
if ((o_mwb_stb)&&(~i_mwb_stall))
// Number of read acknowledgements needed
nracks <= nracks+1;
if (last_read_request)
//((nracks == {1'b0, cfg_blocklen_sub_one})||(bus_nracks == cfg_len-1))
// Wishbone interruptus
dma_state <= `DMA_READ_ACK;
if (cfg_incs)
o_mwb_addr <= o_mwb_addr
+ {{(AW-1){1'b0}},1'b1};
end
 
if (i_mwb_err)
begin
cfg_len <= 0;
dma_state <= `DMA_IDLE;
end
if (abort)
dma_state <= `DMA_IDLE;
if (i_mwb_ack)
begin
nread <= nread+1;
if (cfg_incs)
cfg_raddr <= cfg_raddr
+ {{(AW-1){1'b0}},1'b1};
end end
`DMA_READ_ACK: begin
nwritten <= 0;
 
if (i_mwb_err)
begin
cfg_len <= 0;
dma_state <= `DMA_IDLE;
end else if (i_mwb_ack)
begin
nread <= nread+1;
if (last_read_ack) // (nread+1 == nracks)
dma_state <= `DMA_PRE_WRITE;
if (cfg_incs)
cfg_raddr <= cfg_raddr
+ {{(AW-1){1'b0}},1'b1};
end
if (abort)
dma_state <= `DMA_IDLE;
end
`DMA_PRE_WRITE: begin
o_mwb_addr <= cfg_waddr;
dma_state <= (abort)?`DMA_IDLE:`DMA_WRITE_REQ;
end
`DMA_WRITE_REQ: begin
if (~i_mwb_stall)
begin
nwritten <= nwritten+1;
if (last_write_request) // (nwritten == nread-1)
// Wishbone interruptus
dma_state <= `DMA_WRITE_ACK;
if (cfg_incd)
begin
nacks <= nacks+1;
if ((nacks == {1'b0, cfg_blocklen_sub_one})
||(bus_nacks <= cfg_len-1))
// Wishbone interruptus
o_mwb_stb <= 1'b0;
else if (cfg_incs) begin
o_mwb_addr <= o_mwb_addr + 1;
end
o_mwb_addr <= o_mwb_addr
+ {{(AW-1){1'b0}},1'b1};
cfg_waddr <= cfg_waddr
+ {{(AW-1){1'b0}},1'b1};
end
end
 
if (i_mwb_err)
if (i_mwb_err)
begin
cfg_len <= 0;
dma_state <= `DMA_IDLE;
end
if (i_mwb_ack)
begin
nwacks <= nwacks+1;
cfg_len <= cfg_len +{(AW){1'b1}}; // -1
end
if (abort)
dma_state <= `DMA_IDLE;
end
`DMA_WRITE_ACK: begin
if (i_mwb_err)
begin
cfg_len <= 0;
nread <= 0;
dma_state <= `DMA_IDLE;
end else if (i_mwb_ack)
begin
nwacks <= nwacks+1;
cfg_len <= cfg_len +{(AW){1'b1}};//cfg_len -= 1;
if (last_write_ack) // (nwacks+1 == nwritten)
begin
o_mwb_cyc <= 1'b0;
cfg_err <= 1'b1;
cfg_len <= 0;
nread <= 0;
end else if (i_mwb_ack)
begin
nread <= nread+1;
if ((~o_mwb_stb)&&(nread+1 == nacks))
begin
o_mwb_cyc <= 1'b0;
nacks <= 0;
end
if (cfg_incs)
cfg_raddr <= cfg_raddr + 1;
// dma_mem[nread[(LGMEMLEN-1):0]] <= i_mwb_data;
dma_state <= (cfg_len == 1)?`DMA_IDLE:`DMA_WAIT;
end
end else if ((~o_mwb_cyc)&&(nread > 0)&&(~cfg_err))
begin // Initiate/continue a write cycle
o_mwb_cyc <= 1'b1;
o_mwb_stb <= 1'b1;
o_mwb_we <= 1'b1;
// o_mwb_data <= dma_mem[0];
o_mwb_addr <= cfg_waddr;
// nwritten <= 0; // Can't set to zero, in case we're
// nacks <= 0; // continuing a cycle
end else if ((~o_mwb_cyc)&&(nread == 0)&&(cfg_len>0)&&(~cfg_wp)
&&((~cfg_on_dev_trigger)
||(i_dev_ints[cfg_dev_trigger])))
begin // Initiate a read cycle
o_mwb_cyc <= 1'b1;
o_mwb_stb <= 1'b1;
o_mwb_we <= 1'b0;
o_mwb_addr<= cfg_raddr;
nwritten <= 0;
nread <= 0;
nacks <= 0;
end else begin
o_mwb_cyc <= 1'b0;
o_mwb_stb <= 1'b0;
o_mwb_we <= 1'b0;
o_mwb_addr <= cfg_raddr;
o_interrupt<= 1'b0;
nwritten <= 0;
if ((i_swb_cyc)&&(i_swb_stb)&&(i_swb_we))
begin
cfg_wp <= 1'b1;
case(i_swb_addr)
2'b00: begin
cfg_wp <= (i_swb_data[27:16]!=12'hfed);
cfg_blocklen_sub_one
<= i_swb_data[(LGMEMLEN-1):0]
+ {(LGMEMLEN){1'b1}};
// i.e. -1;
cfg_dev_trigger <= i_swb_data[14:10];
cfg_on_dev_trigger <= i_swb_data[15];
cfg_incs <= ~i_swb_data[29];
cfg_incd <= ~i_swb_data[28];
cfg_err <= 1'b0;
end
2'b01: cfg_len <= i_swb_data[(AW-1):0];
2'b10: cfg_raddr <= i_swb_data[(AW-1):0];
2'b11: cfg_waddr <= i_swb_data[(AW-1):0];
endcase
end
end
 
if (abort)
dma_state <= `DMA_IDLE;
end
default:
dma_state <= `DMA_IDLE;
endcase
 
initial o_interrupt = 1'b0;
always @(posedge i_clk)
o_interrupt <= (dma_state == `DMA_WRITE_ACK)&&(i_mwb_ack)
&&(last_write_ack)
&&(cfg_len == {{(AW-1){1'b0}},1'b1});
 
initial cfg_err = 1'b0;
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))
cfg_err <= 1'b0;
end else if (((i_mwb_err)&&(o_mwb_cyc))||(abort))
cfg_err <= 1'b1;
 
initial last_read_request = 1'b0;
always @(posedge i_clk)
if ((dma_state == `DMA_WAIT)||(dma_state == `DMA_READ_REQ))
begin
if ((~i_mwb_stall)&&(dma_state == `DMA_READ_REQ))
begin
last_read_request <=
(nracks + 1 == { 1'b0, cfg_blocklen_sub_one})
||(bus_nracks == cfg_len-2);
end else
last_read_request <=
(nracks== { 1'b0, cfg_blocklen_sub_one})
||(bus_nracks == cfg_len-1);
end else
last_read_request <= 1'b0;
 
initial last_read_ack = 1'b0;
always @(posedge i_clk)
if ((dma_state == `DMA_READ_REQ)||(dma_state == `DMA_READ_ACK))
begin
if (i_mwb_ack)
last_read_ack <= (nread+2 == nracks);
else
last_read_ack <= (nread+1 == nracks);
end else
last_read_ack <= 1'b0;
 
initial last_write_request = 1'b0;
always @(posedge i_clk)
if (dma_state == `DMA_PRE_WRITE)
last_write_request <= (nread <= 1);
else if (dma_state == `DMA_WRITE_REQ)
begin
if (i_mwb_stall)
last_write_request <= (nwritten >= nread-1);
else
last_write_request <= (nwritten >= nread-2);
end else
last_write_request <= 1'b0;
 
initial last_write_ack = 1'b0;
always @(posedge i_clk)
if((dma_state == `DMA_WRITE_REQ)||(dma_state == `DMA_WRITE_ACK))
begin
if (i_mwb_ack)
last_write_ack <= (nwacks+2 == nwritten);
else
last_write_ack <= (nwacks+1 == nwritten);
end else
last_write_ack <= 1'b0;
 
assign o_mwb_cyc = (dma_state == `DMA_READ_REQ)
||(dma_state == `DMA_READ_ACK)
||(dma_state == `DMA_WRITE_REQ)
||(dma_state == `DMA_WRITE_ACK);
 
assign o_mwb_stb = (dma_state == `DMA_READ_REQ)
||(dma_state == `DMA_WRITE_REQ);
 
assign o_mwb_we = (dma_state == `DMA_PRE_WRITE)
||(dma_state == `DMA_WRITE_REQ)
||(dma_state == `DMA_WRITE_ACK);
 
//
// This is tricky. In order for Vivado to consider dma_mem to be a
// proper memory, it must have a simple address fed into it. Hence
294,25 → 418,22
//
reg [(LGMEMLEN-1):0] rdaddr;
always @(posedge i_clk)
if ((o_mwb_cyc)&&(o_mwb_we)&&(o_mwb_stb)&&(~i_mwb_stall))
// This would be the normal advance, save that we are
// already one ahead of nwritten
rdaddr <= rdaddr + 1; // {{(LGMEMLEN-1){1'b0}},1};
else if ((~o_mwb_cyc)&&(nread > 0)&&(~cfg_err))
// Here's where we do our extra advance
rdaddr <= nwritten[(LGMEMLEN-1):0]+1;
else if ((~o_mwb_cyc)||(~o_mwb_we))
rdaddr <= nwritten[(LGMEMLEN-1):0];
if((dma_state == `DMA_IDLE)||(dma_state == `DMA_WAIT)
||(dma_state == `DMA_WRITE_ACK))
rdaddr <= 0;
else if ((dma_state == `DMA_PRE_WRITE)
||((dma_state==`DMA_WRITE_REQ)&&(~i_mwb_stall)))
rdaddr <= rdaddr + {{(LGMEMLEN-1){1'b0}},1'b1};
always @(posedge i_clk)
if ((~o_mwb_cyc)||((o_mwb_we)&&(o_mwb_stb)&&(~i_mwb_stall)))
if ((dma_state != `DMA_WRITE_REQ)||(~i_mwb_stall))
o_mwb_data <= dma_mem[rdaddr];
always @(posedge i_clk)
if ((o_mwb_cyc)&&(~o_mwb_we)&&(i_mwb_ack))
if((dma_state == `DMA_READ_REQ)||(dma_state == `DMA_READ_ACK))
dma_mem[nread[(LGMEMLEN-1):0]] <= i_mwb_data;
 
always @(posedge i_clk)
casez(i_swb_addr)
2'b00: o_swb_data <= { ~cfg_wp, cfg_err,
2'b00: o_swb_data <= { (dma_state != `DMA_IDLE), cfg_err,
~cfg_incs, ~cfg_incd,
1'b0, nread,
cfg_on_dev_trigger, cfg_dev_trigger,
323,14 → 444,28
2'b11: o_swb_data <= { {(DW-AW){1'b0}}, cfg_waddr};
endcase
 
// This causes us to wait a minimum of two clocks before starting: One
// to go into the wait state, and then one while in the wait state to
// develop the trigger.
initial trigger = 1'b0;
always @(posedge i_clk)
if ((i_swb_cyc)&&(i_swb_stb)) // &&(~i_swb_we))
o_swb_ack <= 1'b1;
// else if ((i_swb_cyc)&&(i_swb_stb)&&(i_swb_we)&&(~o_mwb_cyc)&&(nread == 0))
else
o_swb_ack <= 1'b0;
trigger <= (dma_state == `DMA_WAIT)
&&((~cfg_on_dev_trigger)
||(i_dev_ints[cfg_dev_trigger]));
 
// Ack any access. We'll quietly ignore any access where we are busy,
// 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);
 
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)
&&(i_swb_addr == 2'b00)
&&(i_swb_data == 32'hffed0000));
 
endmodule
 
/zipcpu/trunk/rtl/peripherals/zipcounter.v
27,7 → 27,7
//
///////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
61,17 → 61,13
// Interrupt line
output reg o_int;
 
initial o_int = 0;
initial o_wb_data = 32'h00;
always @(posedge i_clk)
if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we))
o_wb_data <= i_wb_data;
{ o_int, o_wb_data } <= { 1'b0, i_wb_data };
else if (i_ce)
o_wb_data <= o_wb_data + 1;
 
initial o_int = 0;
always @(posedge i_clk)
if (i_ce)
o_int <= &o_wb_data;
{ o_int, o_wb_data } <= o_wb_data+{{(BW-1){1'b0}},1'b1};
else
o_int <= 1'b0;
 
/zipcpu/trunk/rtl/peripherals/zipjiffies.v
45,7 → 45,7
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
67,7 → 67,7
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_data,
o_wb_ack, o_wb_stall, o_wb_data,
o_int);
parameter BW = 32, VW = (BW-2);
parameter BW = 32;
input i_clk, i_ce;
// Wishbone inputs
input i_wb_cyc, i_wb_stb, i_wb_we;
104,13 → 104,13
 
initial new_set = 1'b0;
always @(posedge i_clk)
begin
// Delay things by a clock to simplify our logic
if ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we))
begin
new_set <= 1'b1;
new_when<= i_wb_data;
end else
new_set <= 1'b0;
new_set <= ((i_wb_cyc)&&(i_wb_stb)&&(i_wb_we));
// new_when is a don't care when new_set = 0, so don't worry
// about setting it at all times.
new_when<= i_wb_data;
end
 
initial o_int = 1'b0;
initial int_set = 1'b0;
118,16 → 118,18
begin
o_int <= 1'b0;
if ((i_ce)&&(int_set)&&(r_counter == int_when))
begin // Interrupts are self-clearing
o_int <= 1'b1; // Set the interrupt flag
int_set <= 1'b0;// Clear the interrupt
end
// Interrupts are self-clearing
o_int <= 1'b1; // Set the interrupt flag for one clock
else if ((new_set)&&(till_wb <= 0))
o_int <= 1'b1;
 
if ((new_set)&&(till_wb > 0))
int_set <= 1'b1;
else if ((i_ce)&&(r_counter == int_when))
int_set <= 1'b0;
 
if ((new_set)&&(till_wb > 0)&&((till_wb<till_when)||(~int_set)))
begin
int_when <= new_when;
int_set <= ((int_set)||(till_wb>0));
end
end
 
//

powered by: WebSVN 2.1.0

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