URL
https://opencores.org/ocsvn/openarty/openarty/trunk
Subversion Repositories openarty
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 24 to Rev 25
- ↔ Reverse comparison
Rev 24 → Rev 25
/openarty/trunk/rtl/icontrol.v
File deleted
/openarty/trunk/rtl/memdev.v
39,7 → 39,7
// |
module memdev(i_clk, i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, |
o_wb_ack, o_wb_stall, o_wb_data); |
parameter AW=15, DW=32; |
parameter AW=15, DW=32, EXTRACLOCK= 0; |
input i_clk, i_wb_cyc, i_wb_stb, i_wb_we; |
input [(AW-1):0] i_wb_addr; |
input [(DW-1):0] i_wb_data; |
47,27 → 47,48
output wire o_wb_stall; |
output reg [(DW-1):0] o_wb_data; |
|
reg last_wstb, last_stb; |
always @(posedge i_clk) |
last_wstb <= (i_wb_stb)&&(i_wb_we); |
always @(posedge i_clk) |
last_stb <= (i_wb_stb); |
wire w_wstb, w_stb; |
wire [(DW-1):0] w_data; |
wire [(AW-1):0] w_addr; |
|
reg [(DW-1):0] last_data; |
reg [(AW-1):0] last_addr; |
always @(posedge i_clk) |
last_data <= i_wb_data; |
always @(posedge i_clk) |
last_addr <= i_wb_addr; |
generate |
if (EXTRACLOCK == 0) |
begin |
|
assign w_wstb = (i_wb_stb)&&(i_wb_we); |
assign w_stb = i_wb_stb; |
assign w_addr = i_wb_addr; |
assign w_data = i_wb_data; |
|
end else begin |
|
reg last_wstb, last_stb; |
always @(posedge i_clk) |
last_wstb <= (i_wb_stb)&&(i_wb_we); |
always @(posedge i_clk) |
last_stb <= (i_wb_stb); |
|
reg [(DW-1):0] last_data; |
reg [(AW-1):0] last_addr; |
always @(posedge i_clk) |
last_data <= i_wb_data; |
always @(posedge i_clk) |
last_addr <= i_wb_addr; |
|
assign w_wstb = last_wstb; |
assign w_stb = last_stb; |
assign w_addr = last_addr; |
assign w_data = last_data; |
end endgenerate |
|
reg [(DW-1):0] mem [0:((1<<AW)-1)]; |
always @(posedge i_clk) |
o_wb_data <= mem[last_addr]; |
o_wb_data <= mem[w_addr]; |
always @(posedge i_clk) |
if (last_wstb) |
mem[last_addr] <= last_data; |
if (w_wstb) |
mem[w_addr] <= w_data; |
always @(posedge i_clk) |
o_wb_ack <= (last_stb); |
o_wb_ack <= (w_stb); |
assign o_wb_stall = 1'b0; |
|
endmodule |
/openarty/trunk/rtl/cpu/div.v
34,8 → 34,8
// |
module div(i_clk, i_rst, i_wr, i_signed, i_numerator, i_denominator, |
o_busy, o_valid, o_err, o_quotient, o_flags); |
parameter BW=32, LGBW = 5; |
input i_clk, i_rst; |
parameter BW=32, LGBW = 5; |
input i_clk, i_rst; |
// Input parameters |
input i_wr, i_signed; |
input [(BW-1):0] i_numerator, i_denominator; |
/openarty/trunk/rtl/cpu/zipbones.v
186,7 → 186,7
`endif |
); |
end else begin |
zipcpuhs #(RESET_ADDRESS,ADDRESS_WIDTH,LGICACHE) |
zipcpu #(RESET_ADDRESS,ADDRESS_WIDTH,LGICACHE) |
thecpu(i_clk, cpu_reset, i_ext_int, |
cpu_halt, cmd_clear_pf_cache, cmd_addr[4:0], cpu_dbg_we, |
i_dbg_data, cpu_dbg_stall, cpu_dbg_data, |
/openarty/trunk/rtl/cpu/zipcpuhs.v
1,6 → 1,6
/////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: zipcpu.v |
// Filename: zipcpuhs.v |
// |
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
// |
7,63 → 7,85
// Purpose: This is the top level module holding the core of the Zip CPU |
// together. The Zip CPU is designed to be as simple as possible. |
// (actual implementation aside ...) The instruction set is about as |
// RISC as you can get, there are only 16 instruction types supported. |
// Please see the accompanying spec.pdf file for a description of these |
// instructions. |
// RISC as you can get, there are only 26 instruction types supported, not |
// including the floating point instruction set. Please see the |
// accompanying spec.pdf file for a description of these instructions. |
// |
// All instructions are 32-bits wide. All bus accesses, both address and |
// data, are 32-bits over a wishbone bus. |
// |
// The Zip CPU is fully pipelined with the following pipeline stages: |
// |
// This version of the ZipCPU has been modified for "high speed" operation. |
// By that I mean, it has been modified so that it can handle a high speed |
// system clock. The nominal five stage pipeline has therefore been |
// broken into nine pieces, as outlined below: |
// |
// 1. Prefetch, returns the instruction from memory. |
// |
// 2. Instruction Decode |
// 2. Instruction Decode: triplet instructions, VLIW upper half, |
// VLIW lower half, and normal instructions |
// |
// 3. Read Operands |
// 3. Instruction Decode: Select among the four types of |
// instructions |
// |
// 4. Apply Instruction |
// 4. Read Operand B |
// |
// 4. Write-back Results |
// 5. Read Operand A, add the immediate offset to Operand B |
// |
// Further information about the inner workings of this CPU may be |
// found in the spec.pdf file. (The documentation within this file |
// had become out of date and out of sync with the spec.pdf, so look |
// to the spec.pdf for accurate and up to date information.) |
// 6. 16 ALU operations |
// |
// 7. Select among ALU results |
// |
// In general, the pipelining is controlled by three pieces of logic |
// per stage: _ce, _stall, and _valid. _valid means that the stage |
// holds a valid instruction. _ce means that the instruction from the |
// previous stage is to move into this one, and _stall means that the |
// instruction from the previous stage may not move into this one. |
// The difference between these control signals allows individual stages |
// to propagate instructions independently. In general, the logic works |
// as: |
// 8. Select from ALU, Memory, Divide, FPU results |
// |
// 9. Write-back Results |
// |
// assign (n)_ce = (n-1)_valid && (~(n)_stall) |
// Further information about the ZipCPU may be found in the spec.pdf file. |
// (The documentation within this file is likely to become out of date |
// and out of sync with the spec.pdf, so look to the spec.pdf for |
// accurate and up to date information.) |
// |
// |
// always @(posedge i_clk) |
// if ((i_rst)||(clear_pipeline)) |
// (n)_valid = 0 |
// else if (n)_ce |
// (n)_valid = 1 |
// else if (n+1)_ce |
// (n)_valid = 0 |
// A note about pipelining. The approach used to accommodate pipelining |
// in this implementation assumes that if will be impossible to tell if |
// a particular stage will stall until the logic for that stage completes. |
// There is no time, therefore, for the stall logic to ripple from the |
// end of the pipeline to the beginning. At best, it can ripple from |
// one stage to the next. Stall logic, therefore, is latched in a |
// FLIP-FLOP, rather than done in a combinatorial fashion. Hopefully, |
// you'll have a copy of the stall logic slides. If not, here's the |
// outline of how stalls will be done: |
// |
// assign (n)_stall = ( (n-1)_valid && ( pipeline hazard detection ) ) |
// || ( (n)_valid && (n+1)_stall ); |
// assign (n)_slp = // stall logic for location n, based upon the prior |
// // stages info |
// assign (n)_slc = // stall logic for location n, based upon a copy of |
// // what was in the prior stage |
// |
// and ... |
// |
// // We'll shorten _valid to _v, _stall to _s, _copy to _c |
// always @(posedge i_clk) |
// if (n)_ce |
// (n)_variable = ... whatever logic for this stage |
// if ((i_rst)||(clear_pipeline) |
// (n)_v = 0; |
// else if (!(n)_stall) |
// (n)_v = ( (n-1)_v && (!(n)_slp) ); |
// else |
// (n)_v = ( !(n)_slc ); |
// |
// Note that a stage can stall even if no instruction is loaded into |
// it. |
// always @(posedge i_clk) |
// if ((i_rst)||(clear_pipeline) |
// (n)_s = 1'b0; |
// else if (!(n)_s) |
// (n)_s = ((n-1)_v) && ( (n)_slp || (n+1)_s ); |
// else |
// (n)_s = ( (n)_slc || (n+1)_s ); |
// |
// always @(posedge i_clk) |
// if ((n)_s) |
// (n)_data = PROCESS[(n)_c]; |
// // Can't chnge copy if not stalled |
// else |
// (n)_data = PROCESS[(n-1)_data]; |
// (n)_c <= (n-1)_data; |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
239,7 → 261,7
wire [31:0] pf_data; |
wire [31:0] instruction; |
wire [(AW-1):0] instruction_pc; |
wire pf_valid, instruction_gie, pf_illegal; |
wire pf_v, instruction_gie, pf_illegal; |
|
// |
// |
257,7 → 279,7
dcdF_wr, dcd_gie, dcd_break, dcd_lock, |
dcd_pipe, dcd_ljmp; |
reg [1:0] r_dcdvalid; |
wire dcd_valid; |
wire dcd_v; |
wire [(AW-1):0] dcd_pc; |
wire [31:0] dcd_I; |
wire dcd_zI; // true if dcdI == 0 |
276,7 → 298,7
// |
// |
// Now, let's read our operands |
reg opa_valid, opa_DV, opa_FP, opa_ALU, opa_M, |
reg opa_v, opa_DV, opa_FP, opa_ALU, opa_M, |
opa_rA, opa_rB; |
reg [4:0] alu_reg; |
reg [3:0] opa_opn; |
292,12 → 314,7
// Some pipeline control wires |
reg opa_A_alu, opa_A_mem; |
reg opa_B_alu, opa_B_mem; |
`ifdef OPT_ILLEGAL_INSTRUCTION |
reg opa_illegal; |
`else |
wire opa_illegal; |
assign opa_illegal = 1'b0; |
`endif |
reg opa_break; |
reg opa_lock; |
|
310,8 → 327,8
// |
// Now, let's read our operands |
reg [3:0] opb_opn; |
reg opb_valid, opb_valid_mem, opb_valid_alu; |
reg opb_valid_div, opb_valid_fpu; |
reg opb_v, opb_v_mem, opb_v_alu; |
reg opb_v_div, opb_v_fpu; |
reg [4:0] opb_R; |
reg [31:0] r_opb_A, r_opb_B; |
reg [(AW-1):0] opb_pc; |
324,12 → 341,7
// Some pipeline control wires |
reg opb_A_alu, opb_A_mem; |
reg opb_B_alu, opb_B_mem; |
`ifdef OPT_ILLEGAL_INSTRUCTION |
reg opb_illegal; |
`else |
wire opb_illegal; |
assign opb_illegal = 1'b0; |
`endif |
reg opb_break; |
reg opb_lock; |
|
340,14 → 352,15
// Variable declarations |
// |
// |
reg stage_busy; |
reg [(AW-1):0] alu_pc; |
reg r_alu_pc_valid, mem_pc_valid; |
wire alu_pc_valid; |
reg r_alu_pc_v, mem_pc_v; |
wire alu_pc_v; |
wire alu_phase; |
wire alu_ce, alu_stall; |
wire [31:0] alu_result; |
wire [3:0] alu_flags; |
wire alu_valid, alu_busy; |
wire alu_v, alu_busy; |
wire set_cond; |
reg alu_wr, alF_wr, alu_gie; |
wire alu_illegal_op; |
357,7 → 370,7
|
wire mem_ce, mem_stalled; |
wire mem_pipe_stalled; |
wire mem_valid, mem_ack, mem_stall, mem_err, bus_err, |
wire mem_v, 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; |
|
365,18 → 378,18
wire [(AW-1):0] mem_addr; |
wire [31:0] mem_data, mem_result; |
|
wire div_ce, div_error, div_busy, div_valid; |
wire div_ce, div_error, div_busy, div_v; |
wire [31:0] div_result; |
wire [3:0] div_flags; |
|
assign div_ce = (master_ce)&&(~clear_pipeline)&&(opb_valid_div) |
assign div_ce = (master_ce)&&(~clear_pipeline)&&(opb_v_div) |
&&(~stage_busy)&&(set_cond); |
|
wire fpu_ce, fpu_error, fpu_busy, fpu_valid; |
wire fpu_ce, fpu_error, fpu_busy, fpu_v; |
wire [31:0] fpu_result; |
wire [3:0] fpu_flags; |
|
assign fpu_ce = (master_ce)&&(~clear_pipeline)&&(opb_valid_fpu) |
assign fpu_ce = (master_ce)&&(~clear_pipeline)&&(opb_v_fpu) |
&&(~stage_busy)&&(set_cond); |
|
// |
408,46 → 421,42
// |
// PIPELINE STAGE #2 :: Instruction Decode |
// Calculate stall conditions |
assign dcd_ce = ((~dcd_valid)||(~dcd_stalled))&&(~clear_pipeline); |
assign dcd_ce = ((~dcd_v)||(~dcd_stalled))&&(~clear_pipeline); |
|
assign dcd_stalled = (dcd_valid)&&(op_stall); |
assign dcd_stalled = (dcd_v)&&(opa_stall); |
// |
// PIPELINE STAGE #3 :: Read Operands |
// Calculate stall conditions |
wire op_lock_stall; |
assign op_stall = (opvalid)&&( // Only stall if we're loaded w/validins |
// Stall if we're stopped, and not allowed to execute |
// an instruction |
// (~master_ce) // Already captured in alu_stall |
// |
// Stall if going into the ALU and the ALU is stalled |
// i.e. if the memory is busy, or we are single |
// stepping. This also includes our stalls for |
// op_break and op_lock, so we don't need to |
// include those as well here. |
// This also includes whether or not the divide or |
// floating point units are busy. |
(alu_stall) |
// |
// Stall if we are going into memory with an operation |
// that cannot be pipelined, and the memory is |
// already busy |
||(mem_stalled) // &&(opvalid_mem) part of mem_stalled |
) |
||(dcd_valid)&&( |
// Stall if we need to wait for an operand A |
// to be ready to read |
(dcdA_stall) |
assign opa_stall_slp = ( |
// Likewise for B, also includes logic |
// regarding immediate offset (register must |
// be in register file if we need to add to |
// an immediate) |
||(dcdB_stall) |
(((dcdB_rd)&&(~dcd_zI)) |
&&((opa_v)&&(opb_R == dcdB) |
||(mem_rdbusy) |
||((div_busy)&&(div_R == dcdB)) |
||((fpu_busy)&&(fpu_R == dcdB)) |
||((alua_v)&&(alua_R==dcdB)) |
||((alub_v)&&(alub_R==dcdB)) |
||((alu_busy)) |
&&( |
// 1. |
((~dcd_zI)&&( |
((opb_R == dcdB)&&(opb_wR)) |
||((mem_rdbusy)&&(~dcd_pipe)) |
)) |
// 2. |
||((opF_wr)&&(dcdB_cc)) |
))) |
// Or if we need to wait on flags to work on the |
// CC register |
||(dcdF_stall) |
||(((~dcdF[3]) |
||((dcd_rA)&&(dcdA_cc)) |
||((dcd_rB)&&(dcdB_cc))) |
&&(opb_v)&&(opb_ccR)) |
); |
assign opa_ce = ((dcd_valid)||(dcd_illegal))&&(~opa_stall); |
|
// |
// PIPELINE STAGE #4 :: ALU / Memory |
462,34 → 471,30
// 4. Last case: Stall if we would otherwise move a break instruction |
// through the ALU. Break instructions are not allowed through |
// the ALU. |
assign alu_stall = (((~master_ce)||(mem_rdbusy)||(alu_busy))&&(opvalid_alu)) //Case 1&2 |
// Old case #3--this isn't an ALU stall though ... |
||((opvalid_alu)&&(wr_reg_ce)&&(wr_reg_id[4] == op_gie) |
&&(wr_write_cc)) // Case 3 |
||((opvalid)&&(op_lock)&&(op_lock_stall)) |
||((opvalid)&&(op_break)) |
||(div_busy)||(fpu_busy); |
assign alu_ce = (master_ce)&&(stage_ce)&&(opvalid_alu)&&(~clear_pipeline); |
assign alu_stall_clp = (~master_ce); |
assign alu_stall_cls = (~master_ce); |
always @(posedge i_clk) |
stage_busy <= (alu_ce)||(mem_ce)||(fpu_ce)||(div_ce) |
||(alu_busy)||(mem_rdbusy)||(fpu_busy)||(div_busy); |
assign stage_ce = (~div_busy)&&(~alu_busy)&&(~mem_rdbusy)&&(~fpu_busy); |
// |
|
// |
// Note: if you change the conditions for mem_ce, you must also change |
// alu_pc_valid. |
// alu_pc_v. |
// |
assign mem_ce = (master_ce)&&(opvalid_mem)&&(~mem_stalled) |
assign mem_ce = (master_ce)&&(opb_v_mem)&&(~mem_stalled) |
&&(~clear_pipeline); |
assign mem_stalled = (~master_ce)||(alu_busy)||((opvalid_mem)&&( |
(mem_pipe_stalled) |
||((~op_pipe)&&(mem_busy)) |
||(div_busy) |
||(fpu_busy) |
// Stall waiting for flags to be valid |
// Or waiting for a write to the PC register |
// Or CC register, since that can change the |
// PC as well |
||((wr_reg_ce)&&(wr_reg_id[4] == op_gie) |
&&((wr_write_pc)||(wr_write_cc))))); |
assign mem_stall_clp = (~master_ce)||(alu_busy)||(div_busy)||(fpu_busy) |
||(wr_write_pc)||(wr_write_cc) |
||((opb_v_mem)&&( |
(mem_pipe_stalled) |
||((~opb_pipe)&&(mem_busy)))); |
assign mem_stall_cls = (~master_ce)||(alu_busy)||(div_busy)||(fpu_busy) |
||(wr_write_pc)||(wr_write_cc) |
||((cp_opb_v_mem)&&( |
(mem_pipe_stalled) |
||((~cp_opb_pipe)&&(mem_busy)))); |
|
|
// |
504,7 → 509,7
~dcd_stalled, |
((dcd_early_branch)&&(~clear_pipeline)) |
? dcd_branch_pc:pf_pc, |
instruction, instruction_pc, pf_valid, |
instruction, instruction_pc, pf_v, |
pf_cyc, pf_stb, pf_we, pf_addr, pf_data, |
pf_ack, pf_stall, pf_err, i_wb_data, |
pf_illegal); |
513,7 → 518,7
// |
// The ifastdec decoder takes two clocks to decode an instruction. |
// Therefore, to determine if a decoded instruction is valid, we |
// need to wait two clocks from pf_valid. Hence, we dump this into |
// need to wait two clocks from pf_v. Hence, we dump this into |
// a pipeline below. |
// |
initial r_dcdvalid = 2'b00; |
521,21 → 526,21
if ((i_rst)||(clear_pipeline)||(w_clear_icache)) |
r_dcdvalid <= 2'b00; |
else if (dcd_ce) |
r_dcdvalid <= { r_dcdvalid[0], pf_valid }; |
r_dcdvalid <= { r_dcdvalid[0], pf_v }; |
else if (opa_ce) |
r_dcdvalid <= 1'b0; |
assign dcd_valid = r_dcdvalid[1]; |
assign dcd_v = r_dcdvalid[1]; |
|
ifastdec #(AW, IMPLEMENT_MPY, EARLY_BRANCHING, IMPLEMENT_DIVIDE, |
IMPLEMENT_FPU) |
instruction_decoder(i_clk, (i_rst)||(clear_pipeline), |
dcd_ce, dcd_stalled, instruction, instruction_gie, |
instruction_pc, pf_valid, pf_illegal, dcd_phase, |
instruction_pc, pf_v, pf_illegal, dcd_phase, |
dcd_illegal, dcd_pc, dcd_gie, |
{ dcdR_cc, dcdR_pc, dcd_iR }, |
{ dcdA_cc, dcdA_pc, dcd_iA }, |
{ dcdB_cc, dcdB_pc, dcd_iB }, |
dcd_I, dcd_zI, dcdF, dcdF_wr, dcdOp, |
{ dcd_Rcc, dcd_Rpc, dcd_iR }, |
{ dcd_Acc, dcd_Apc, dcd_iA }, |
{ dcd_Bcc, dcd_Bpc, dcd_iB }, |
dcd_I, dcd_zI, dcd_F, dcd_wF, dcdOp, |
dcdALU, dcdM, dcdDV, dcdFP, dcd_break, dcd_lock, |
dcd_wR,dcd_rA, dcd_rB, |
dcd_early_branch, |
542,9 → 547,14
dcd_branch_pc, dcd_ljmp, |
dcd_pipe); |
|
reg r_op_pipe; |
// |
// |
// PIPELINE STAGE #3 :: Read Operands (Registers) |
// |
// |
|
initial r_op_pipe = 1'b0; |
reg opa_pipe; |
initial opa_pipe = 1'b0; |
// To be a pipeable operation, there must be |
// two valid adjacent instructions |
// Both must be memory instructions |
555,20 → 565,78
// However ... we need to know this before this clock, hence this is |
// calculated in the instruction decoder. |
always @(posedge i_clk) |
if (op_ce) |
r_op_pipe <= dcd_pipe; |
else if (mem_ce) // Clear us any time an op_ is clocked in |
r_op_pipe <= 1'b0; |
assign op_pipe = r_op_pipe; |
if (!opa_stall) |
begin |
opa_v <= dcdvalid&&(~opa_stall_slp); |
opa_stall <= (dcdvalid)&&(opa_stall_slp); |
opa_pipe <= dcd_pipe; |
|
// |
// |
// PIPELINE STAGE #3 :: Read Operands (Registers) |
// |
// |
assign w_opA = regset[dcd_iA]; |
assign w_opB = regset[dcd_iB]; |
opa_wR <= dcd_wR; |
{ opa_Acc, opa_Apc, opa_iA, opa_rA } |
<= { dcd_Acc, dcd_Apc, dcd_iA, dcd_rA }; |
{ opa_Bcc, opa_Bpc, opa_iB, opa_rB } |
<= { dcd_Bcc, dcd_Bpc, dcd_iB, dcd_rB }; |
|
// Register A |
if (dcd_Apc) |
opa_vA <= (dcd_iA[4]==dcd_gie) ? dcd_pc |
: (dcd_iA)?upc : ipc; |
else if (dcd_Acc) |
opa_vA <= (dcd_iA[4])?user_flags_reg |
: supervisor_flags_reg; |
else |
opa_vA <= regset[dcd_iA]; |
|
// Register B |
if (!dcd_rB) |
opa_vB <= 32'h00; |
else if (dcd_Bpc) |
opa_vB <= (dcd_iB[4]==dcd_gie) ? dcd_pc |
: (dcd_iB)?upc : ipc; |
else if (dcd_Bcc) |
opa_vB <= (dcd_iB[4])?user_flags_reg |
: supervisor_flags_reg; |
else |
opa_vB <= regset[dcd_iB]; |
|
// Copy |
cp_opa_pc <= dcd_pc; |
cp_opa_gie <= dcd_gie; |
cp_opa_pipe <= dcd_pipe; |
{ cp_opa_Rcc, cp_opa_Rpc, cp_opa_iR } |
<= { dcd_Rcc, dcd_Rpc, dcd_iR }; |
{ cp_opa_Acc, cp_opa_Apc, cp_opa_iA } |
<= { dcd_Acc, dcd_Apc, dcd_iA }; |
{ cp_opa_Bcc, cp_opa_Bpc, cp_opa_iB } |
<= { dcd_Bcc, dcd_Bpc, dcd_iB }; |
end else begin |
opa_v <= (~opa_stall_slc); |
opa_stall <= (opa_stall_slc); |
opa_pipe <= cp_opa_pipe; |
|
// Register A |
if (cp_opa_Apc) |
opa_vA <= (cp_opa_iA[4]==cp_opa_gie) ? cp_opa_pc |
: (cp_opa_iA)?upc : ipc; |
else if (dcd_Acc) |
opa_vA <= (cp_opa_iA[4])?user_flags_reg |
: supervisor_flags_reg; |
else |
opa_vA <= regset[cp_opa_iA]; |
|
// Register B |
if (!cp_opa_rB) |
opa_vB <= 32'h00; |
else if (cp_opa_Bpc) |
opa_vB <= (cp_opa_iB[4]==cp_opa_gie) ? cp_opa_pc |
: (cp_opa_iB)?upc : ipc; |
else if (cp_opa_Bcc) |
opa_vB <= (cp_opa_iB[4])?user_flags_reg |
: supervisor_flags_reg; |
else |
opa_vB <= regset[cp_opa_iB]; |
end |
|
wire [8:0] w_cpu_info; |
assign w_cpu_info = { |
`ifdef OPT_ILLEGAL_INSTRUCTION |
601,28 → 669,9
`endif |
}; |
|
wire [31:0] w_pcA_v; |
generate |
if (AW < 32) |
assign w_pcA_v = {{(32-AW){1'b0}}, (dcd_iA[4] == dcd_gie)?dcd_pc:upc }; |
else |
assign w_pcA_v = (dcd_iA[4] == dcd_gie)?dcd_pc:upc; |
endgenerate |
|
reg [4:0] opa_Aid, opa_Bid; |
reg opa_Ard, opa_Brd; |
always @(posedge i_clk) |
if (opa_ce) |
begin |
opa_iA <= dcd_iA; |
opa_iB <= dcd_iB; |
opa_rA <= dcd_rA; |
opa_rB <= dcd_rB; |
end |
|
always @(posedge i_clk) |
if (opa_ce) |
begin |
if ((wr_reg_ce)&&(wr_reg_id == dcd_iA)) |
r_opA <= wr_gpreg_vl; |
else if (dcdA_pc) |
707,39 → 756,39
end // Bit order is { (flags_not_used), VNCZ mask, VNCZ value } |
assign opb_F = { r_opb_F[3], r_opb_F[5], r_opb_F[1], r_opb_F[4:0] }; |
|
wire w_opa_valid; |
wire w_opa_v; |
always @(posedge i_clk) |
if (i_rst) |
opa_valid <= 1'b0; |
opa_v <= 1'b0; |
else if (opa_ce) |
opa_valid <= ((dcd_valid)||(dcd_illegal))&&(~clear_pipeline); |
opa_v <= ((dcd_v)||(dcd_illegal))&&(~clear_pipeline); |
|
always @(posedge i_clk) |
if ((i_rst)||(clear_pipeline)) |
begin |
opa_valid <= 1'b0; |
opa_v <= 1'b0; |
end else if (opa_ce) |
begin |
opa_valid <=(dcd_valid); |
opa_M <= (dcd_valid)&&(opa_M )&&(~opa_illegal); |
opa_DV <= (dcd_valid)&&(opa_DV )&&(~opa_illegal); |
opa_FP <= (dcd_valid)&&(opa_FP )&&(~opa_illegal); |
opa_v <=(dcd_v); |
opa_M <= (dcd_v)&&(opa_M )&&(~opa_illegal); |
opa_DV <= (dcd_v)&&(opa_DV )&&(~opa_illegal); |
opa_FP <= (dcd_v)&&(opa_FP )&&(~opa_illegal); |
end else if (opb_ce) |
opa_valid <= 1'b0; |
opa_v <= 1'b0; |
|
initial opb_valid = 1'b0; |
initial opb_valid_alu = 1'b0; |
initial opb_valid_mem = 1'b0; |
initial opb_valid_div = 1'b0; |
initial opb_valid_fpu = 1'b0; |
initial opb_v = 1'b0; |
initial opb_v_alu = 1'b0; |
initial opb_v_mem = 1'b0; |
initial opb_v_div = 1'b0; |
initial opb_v_fpu = 1'b0; |
always @(posedge i_clk) |
if ((i_rst)||(clear_pipeline)) |
begin |
opb_valid <= 1'b0; |
opb_valid_alu <= 1'b0; |
opb_valid_mem <= 1'b0; |
opb_valid_div <= 1'b0; |
opb_valid_fpu <= 1'b0; |
opb_v <= 1'b0; |
opb_v_alu <= 1'b0; |
opb_v_mem <= 1'b0; |
opb_v_div <= 1'b0; |
opb_v_fpu <= 1'b0; |
end else if (opb_ce) |
begin |
// Do we have a valid instruction? |
750,18 → 799,18
// Hence, the test on dcd_stalled here. If we must |
// wait until our operands are valid, then we aren't |
// valid yet until then. |
opb_valid <= (opa_valid); |
opb_valid_alu <=(opa_valid)&&((opa_ALU)||(opa_illegal)); |
opb_valid_mem <= (opa_valid)&&(opa_M )&&(~opa_illegal); |
opb_valid_div <= (opa_valid)&&(opa_DV )&&(~opa_illegal); |
opb_valid_fpu <= (opa_valid)&&(opa_FP )&&(~opa_illegal); |
opb_v <= (opa_v); |
opb_v_alu <=(opa_v)&&((opa_ALU)||(opa_illegal)); |
opb_v_mem <= (opa_v)&&(opa_M )&&(~opa_illegal); |
opb_v_div <= (opa_v)&&(opa_DV )&&(~opa_illegal); |
opb_v_fpu <= (opa_v)&&(opa_FP )&&(~opa_illegal); |
end else if ((clear_pipeline)||(stage_ce)) |
begin |
opb_valid <= 1'b0; |
opb_valid_alu <= 1'b0; |
opb_valid_mem <= 1'b0; |
opb_valid_div <= 1'b0; |
opb_valid_fpu <= 1'b0; |
opb_v <= 1'b0; |
opb_v_alu <= 1'b0; |
opb_v_mem <= 1'b0; |
opb_v_div <= 1'b0; |
opb_v_fpu <= 1'b0; |
end |
|
initial op_break = 1'b0; |
769,7 → 818,7
if (i_rst) opb_break <= 1'b0; |
else if (opb_ce) |
opb_break <= (opa_break)&&((break_en)||(~opa_gie)); |
else if ((clear_pipeline)||(~opb_valid)) |
else if ((clear_pipeline)||(~opb_v)) |
opb_break <= 1'b0; |
|
reg r_op_lock, r_op_lock_stall; |
779,8 → 828,8
if (i_rst) |
r_op_lock_stall <= 1'b0; |
else |
r_op_lock_stall <= (~opvalid)||(~op_lock) |
||(~dcd_valid)||(~pf_valid); |
r_op_lock_stall <= (~opb_v)||(~opb_lock) |
||(~opa_v)||(~dcd_v)||(~pf_v); |
|
assign op_lock_stall = r_op_lock_stall; |
|
832,7 → 881,7
opa_ccR <= (dcdR_cc)&&(dcd_wR)&&(dcd_iR[4]==dcd_gie); |
opa_gie <= dcd_gie; |
// |
opa_pc <= dcd_valid; |
opa_pc <= dcd_v; |
opa_rA <= dcd_; |
opa_rB <= dcd_; |
end |
863,12 → 912,12
assign opA = r_opA; |
|
assign dcdA_stall = (dcd_rA) // &&(dcdvalid) is checked for elsewhere |
&&((opa_valid)||(mem_rdbusy) |
&&((opa_v)||(mem_rdbusy) |
||(div_busy)||(fpu_busy)) |
&&((opF_wr)&&(dcdA_cc)); |
|
assign dcdB_stall = (dcdB_rd) |
&&((opa_valid)||(mem_rdbusy) |
&&((opa_v)||(mem_rdbusy) |
||(div_busy)||(fpu_busy)||(alu_busy)) |
&&( |
// 1. |
882,7 → 931,7
assign dcdF_stall = ((~dcdF[3]) |
||((dcd_rA)&&(dcdA_cc)) |
||((dcd_rB)&&(dcdB_cc))) |
&&(opvalid)&&(opb_ccR); |
&&(opb_v)&&(opb_ccR); |
// |
// |
// PIPELINE STAGE #4 :: Apply Instruction |
889,12 → 938,12
// |
// |
fastops fastalu(i_clk, i_rst, alu_ce, |
(opb_valid_alu), opb_opn, opb_A, opb_B, |
alu_result, alu_flags, alu_valid, alu_illegal_op, |
(opb_v_alu), opb_opn, opb_A, opb_B, |
alu_result, alu_flags, alu_v, alu_illegal_op, |
alu_busy); |
|
div thedivide(i_clk, (i_rst)||(clear_pipeline), div_ce, opb_opn[0], |
opb_A, opb_B, div_busy, div_valid, div_error, div_result, |
opb_A, opb_B, div_busy, div_v, div_error, div_result, |
div_flags); |
|
generate |
902,18 → 951,18
begin |
// |
// sfpu thefpu(i_clk, i_rst, fpu_ce, |
// opA, opB, fpu_busy, fpu_valid, fpu_err, fpu_result, |
// opA, opB, fpu_busy, fpu_v, fpu_err, fpu_result, |
// fpu_flags); |
// |
assign fpu_error = 1'b0; // Must only be true if fpu_valid |
assign fpu_error = 1'b0; // Must only be true if fpu_v |
assign fpu_busy = 1'b0; |
assign fpu_valid = 1'b0; |
assign fpu_v = 1'b0; |
assign fpu_result= 32'h00; |
assign fpu_flags = 4'h0; |
end else begin |
assign fpu_error = 1'b0; |
assign fpu_busy = 1'b0; |
assign fpu_valid = 1'b0; |
assign fpu_v = 1'b0; |
assign fpu_result= 32'h00; |
assign fpu_flags = 4'h0; |
end endgenerate |
976,21 → 1025,21
else if (stage_ce) |
alu_illegal <= opb_illegal; |
|
initial r_alu_pc_valid = 1'b0; |
initial mem_pc_valid = 1'b0; |
initial r_alu_pc_v = 1'b0; |
initial mem_pc_v = 1'b0; |
always @(posedge i_clk) |
if (i_rst) |
r_alu_pc_valid <= 1'b0; |
r_alu_pc_v <= 1'b0; |
else if (adf_ce_unconditional)//Includes&&(~alu_clear_pipeline) |
r_alu_pc_valid <= 1'b1; |
r_alu_pc_v <= 1'b1; |
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)&&(~div_busy)&&(~fpu_busy)); |
r_alu_pc_v <= 1'b0; |
assign alu_pc_v = (r_alu_pc_v)&&((~alu_busy)&&(~div_busy)&&(~fpu_busy)); |
always @(posedge i_clk) |
if (i_rst) |
mem_pc_valid <= 1'b0; |
mem_pc_v <= 1'b0; |
else |
mem_pc_valid <= (mem_ce); |
mem_pc_v <= (mem_ce); |
|
wire bus_lock; |
|
1001,7 → 1050,7
r_bus_lock <= 2'b00; |
else if ((opb_ce)&&(opb_lock)) |
r_bus_lock <= 2'b11; |
else if ((|r_bus_lock)&&((~opb_valid_mem)||(~opb_ce))) |
else if ((|r_bus_lock)&&((~opb_v_mem)||(~opb_ce))) |
r_bus_lock <= r_bus_lock + 2'b11; // r_bus_lock -= 1 |
assign bus_lock = |r_bus_lock; |
|
1008,7 → 1057,7
pipemem #(AW,IMPLEMENT_LOCK) domem(i_clk, i_rst,(mem_ce)&&(set_cond), bus_lock, |
(opb_opn[0]), opb_B, opb_A, opb_R, |
mem_busy, mem_pipe_stalled, |
mem_valid, bus_err, mem_wreg, mem_result, |
mem_v, bus_err, mem_wreg, mem_result, |
mem_cyc_gbl, mem_cyc_lcl, |
mem_stb_gbl, mem_stb_lcl, |
mem_we, mem_addr, mem_data, |
1053,10 → 1102,10
|
// 1. Will we need to write a register? |
always @(posedge i_clk) |
r_wr_ce <= (dbgv)||(mem_valid) |
r_wr_ce <= (dbgv)||(mem_v) |
||((~clear_pipeline)&&(~alu_illegal) |
&&(((alu_wr)&&(alu_valid)) |
||(div_valid)||(fpu_valid))); |
&&(((alu_wr)&&(alu_v)) |
||(div_v)||(fpu_v))); |
assign wr_reg_ce = r_wr_ce; |
|
// 2. Did the ALU/MEM/DIV/FPU stage produce an error of any type? |
1067,19 → 1116,19
// these will be causes for an interrupt on the next clock after this |
// one. |
always @(posedge i_clk) |
r_wr_err <= ((div_valid)&&(div_error)) |
||((fpu_valid)&&(fpu_error)) |
||((alu_pc_valid)&&(alu_illegal)) |
r_wr_err <= ((div_v)&&(div_error)) |
||((fpu_v)&&(fpu_error)) |
||((alu_pc_v)&&(alu_illegal)) |
||(bus_err); |
reg r_wr_illegal; |
always @(posedge i_clk) |
r_wr_illegal <= (alu_pc_valid)&&(alu_illegal); |
r_wr_illegal <= (alu_pc_v)&&(alu_illegal); |
|
// Which register shall be written? |
// Note that the alu_reg is the register to write on a divide or |
// FPU operation. |
always @(posedge i_clk) |
r_wr_reg <= (alu_wr|div_valid|fpu_valid)?alu_reg:mem_wreg; |
r_wr_reg <= (alu_wr|div_v|fpu_v)?alu_reg:mem_wreg; |
assign wr_reg_id = r_wr_reg; |
|
// Are we writing to the CC register? |
1091,9 → 1140,9
|
// What value to write? |
always @(posedge i_clk) |
r_wr_val <= ((mem_valid) ? mem_result |
:((div_valid|fpu_valid)) |
? ((div_valid) ? div_result:fpu_result) |
r_wr_val <= ((mem_v) ? mem_result |
:((div_v|fpu_v)) |
? ((div_v) ? div_result:fpu_result) |
:((dbgv) ? dbg_val : alu_result)); |
assign wr_gpreg_vl = r_wr_val; |
assign wr_spreg_vl = r_wr_val; |
1102,17 → 1151,17
reg r_wr_flags_ce; |
initial r_wr_flags_ce = 1'b0; |
always @(posedge i_clk) |
r_wr_flags_ce <= ((alF_wr)||(div_valid)||(fpu_valid)) |
r_wr_flags_ce <= ((alF_wr)||(div_v)||(fpu_v)) |
&&(~clear_pipeline)&&(~alu_illegal); |
assign wr_flags_ce = r_wr_flags_ce; |
|
reg [3:0] r_wr_newflags; |
always @(posedge i_clk) |
if (div_valid) |
if (div_v) |
r_wr_newflags <= div_flags; |
else if (fpu_valid) |
else if (fpu_v) |
r_wr_newflags <= fpu_flags; |
else // if (alu_valid) |
else // if (alu_v) |
r_wr_newflags <= alu_flags; |
|
reg r_wr_gie; |
1119,14 → 1168,14
always @(posedge i_clk) |
r_wr_gie <= (~dbgv)&&(alu_gie); |
|
reg r_wr_pc_valid; |
initial r_wr_pc_valid = 1'b0; |
reg r_wr_pc_v; |
initial r_wr_pc_v = 1'b0; |
always @(posedge i_clk) |
r_wr_pc_valid <= ((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid); |
r_wr_pc_v <= ((alu_pc_v)&&(~clear_pipeline)) |
||(mem_pc_v); |
reg [(AW-1):0] r_wr_pc; |
always @(posedge i_clk) |
r_wr_pc <= alu_pc; // (alu_pc_valid)?alu_pc : mem_pc; |
r_wr_pc <= alu_pc; // (alu_pc_v)?alu_pc : mem_pc; |
|
//// |
// |
1214,7 → 1263,7
initial fast_interrupt = 1'b0; |
always @(posedge i_clk) // 12 inputs |
fast_interrupt <= ((gie)||(alu_gie))&&( |
((r_wr_pc_valid)&&(step)&&(~alu_phase)&&(~bus_lock)) |
((r_wr_pc_v)&&(step)&&(~alu_phase)&&(~bus_lock)) |
// Or ... if we encountered some form of error in our |
// instruction ... |
||(r_wr_err) |
1282,7 → 1331,7
step <= 1'b0; |
else if ((wr_reg_ce)&&(~alu_gie)&&(wr_reg_id[4])&&(wr_write_cc)) |
step <= wr_spreg_vl[`CPU_STEP_BIT]; |
else if (((alu_pc_valid)||(mem_pc_valid))&&(step)&&(gie)) |
else if (((alu_pc_v)||(mem_pc_v))&&(step)&&(gie)) |
step <= 1'b0; |
|
|
1348,7 → 1397,7
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG}) |
&&(~wr_spreg_vl[`CPU_DIVERR_BIT])) |
r_idiv_err_flag <= 1'b0; |
else if ((div_error)&&(div_valid)&&(~r_wr_gie)) |
else if ((div_error)&&(div_v)&&(~r_wr_gie)) |
r_idiv_err_flag <= 1'b1; |
// User divide (by zero) error flag -- if ever set, it will |
// cause a sudden switch interrupt to supervisor mode. |
1362,7 → 1411,7
&&(~wr_spreg_vl[`CPU_DIVERR_BIT]) |
&&(wr_reg_id[4])&&(wr_write_cc)) |
r_udiv_err_flag <= 1'b0; |
else if ((div_error)&&(r_wr_gie)&&(div_valid)) |
else if ((div_error)&&(r_wr_gie)&&(div_v)) |
r_udiv_err_flag <= 1'b1; |
|
assign idiv_err_flag = r_idiv_err_flag; |
1381,7 → 1430,7
else if ((dbgv)&&(wr_reg_id == {1'b0, `CPU_CC_REG}) |
&&(~wr_spreg_vl[`CPU_FPUERR_BIT])) |
r_ifpu_err_flag <= 1'b0; |
else if ((fpu_error)&&(fpu_valid)&&(~r_wr_gie)) |
else if ((fpu_error)&&(fpu_v)&&(~r_wr_gie)) |
r_ifpu_err_flag <= 1'b1; |
// User floating point error flag -- if ever set, it will cause |
// a sudden switch interrupt to supervisor mode. |
1395,7 → 1444,7
&&(~wr_spreg_vl[`CPU_FPUERR_BIT]) |
&&(wr_reg_id[4])&&(wr_write_cc)) |
r_ufpu_err_flag <= 1'b0; |
else if ((fpu_error)&&(r_wr_gie)&&(fpu_valid)) |
else if ((fpu_error)&&(r_wr_gie)&&(fpu_v)) |
r_ufpu_err_flag <= 1'b1; |
|
assign ifpu_err_flag = r_ifpu_err_flag; |
1413,7 → 1462,7
always @(posedge i_clk) |
if (i_rst) |
r_ihalt_phase <= 1'b0; |
else if ((~alu_gie)&&(alu_pc_valid)&&(~clear_pipeline)) |
else if ((~alu_gie)&&(alu_pc_v)&&(~clear_pipeline)) |
r_ihalt_phase <= alu_phase; |
always @(posedge i_clk) |
if (r_wr_gie) |
1442,8 → 1491,8
if ((wr_reg_ce)&&(wr_reg_id[4])&&(wr_write_pc)) |
upc <= wr_spreg_vl[(AW-1):0]; |
else if ((r_wr_gie)&& |
(((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid))) |
(((alu_pc_v)&&(~clear_pipeline)) |
||(mem_pc_v))) |
upc <= alu_pc; |
|
always @(posedge i_clk) |
1452,8 → 1501,8
else if ((wr_reg_ce)&&(~wr_reg_id[4])&&(wr_write_pc)) |
ipc <= wr_spreg_vl[(AW-1):0]; |
else if ((~r_wr_gie)&& |
(((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid))) |
(((alu_pc_v)&&(~clear_pipeline)) |
||(mem_pc_v))) |
ipc <= alu_pc; |
|
always @(posedge i_clk) |
1468,12 → 1517,12
`ifdef OPT_PIPELINED |
else if ((dcd_early_branch)&&(~clear_pipeline)) |
pf_pc <= dcd_branch_pc + 1; |
else if ((new_pc)||((~dcd_stalled)&&(pf_valid))) |
else if ((new_pc)||((~dcd_stalled)&&(pf_v))) |
pf_pc <= pf_pc + {{(AW-1){1'b0}},1'b1}; |
`else |
else if ((alu_gie==gie)&&( |
((alu_pc_valid)&&(~clear_pipeline)) |
||(mem_pc_valid))) |
((alu_pc_v)&&(~clear_pipeline)) |
||(mem_pc_v))) |
pf_pc <= alu_pc; |
`endif |
|
1547,7 → 1596,7
(~pf_cyc)&&(~mem_busy)&&(~alu_busy) |
&&(~div_busy)&&(~fpu_busy) |
// Operations must either be valid, or illegal |
&&((opvalid)||(i_rst)||(dcd_illegal)) |
&&((opb_v)||(i_rst)||(dcd_illegal)) |
// Decode stage must be either valid, in reset, or ill |
&&((dcdvalid)||(i_rst)||(pf_illegal))); |
assign o_dbg_stall = ~r_halted; |
1559,8 → 1608,8
// |
// |
assign o_op_stall = (master_ce)&&(op_stall); |
assign o_pf_stall = (master_ce)&&(~pf_valid); |
assign o_i_count = (alu_pc_valid)&&(~clear_pipeline); |
assign o_pf_stall = (master_ce)&&(~pf_v); |
assign o_i_count = (alu_pc_v)&&(~clear_pipeline); |
|
`ifdef DEBUG_SCOPE |
always @(posedge i_clk) |
1568,7 → 1617,7
/* |
o_break, i_wb_err, pf_pc[1:0], |
flags, |
pf_valid, dcdvalid, opvalid, alu_valid, mem_valid, |
pf_v, dcdvalid, opvalid, alu_v, mem_v, |
op_ce, alu_ce, mem_ce, |
// |
master_ce, opvalid_alu, opvalid_mem, |
1584,7 → 1633,7
/* |
i_rst, master_ce, (new_pc), |
((dcd_early_branch)&&(dcdvalid)), |
pf_valid, pf_illegal, |
pf_v, pf_illegal, |
op_ce, dcd_ce, dcdvalid, dcd_stalled, |
pf_cyc, pf_stb, pf_we, pf_ack, pf_stall, pf_err, |
pf_pc[7:0], pf_addr[7:0] |
1596,12 → 1645,12
(mem_busy)?{ (o_wb_gbl_stb|o_wb_lcl_stb), o_wb_we, |
o_wb_addr[8:0] } |
: { instruction[31:21] }, |
pf_valid, (pf_valid) ? alu_pc[14:0] |
pf_v, (pf_v) ? alu_pc[14:0] |
:{ pf_cyc, pf_stb, pf_pc[12:0] } |
|
/* |
i_wb_err, gie, new_pc, dcd_early_branch, // 4 |
pf_valid, pf_cyc, pf_stb, instruction_pc[0], // 4 |
pf_v, pf_cyc, pf_stb, instruction_pc[0], // 4 |
instruction[30:27], // 4 |
dcd_gie, mem_busy, o_wb_gbl_cyc, o_wb_gbl_stb, // 4 |
dcdvalid, |
/openarty/trunk/rtl/toplevel.v
7,8 → 7,9
// Purpose: This is the top level Verilog file. It is to be contrasted |
// with the other top level Verilog file in this same project in |
// that *this* top level is designed to create a *safe*, low-speed |
// (100MHz), configuration that can be used to test peripherals and other |
// things on the way to building a full featured high speed configuration. |
// (80MHz), configuration that can be used to test peripherals and other |
// things on the way to building a full featured high speed (160MHz) |
// configuration. |
// |
// Differences between this file and fasttop.v should be limited to speed |
// related differences (such as the number of counts per UART baud), and |
44,7 → 45,7
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
module toplevel(i_clk_100mhz, i_reset_btn, |
module toplevel(sys_clk_i, i_reset_btn, |
i_sw, // Switches |
i_btn, // Buttons |
o_led, // Single color LEDs |
56,11 → 57,11
// Missing: Ethernet |
o_eth_mdclk, io_eth_mdio, |
// Memory |
o_ddr_reset_n, o_ddr_cke, o_ddr_ck_p, o_ddr_ck_n, |
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
io_ddr_dqs_p, io_ddr_dqs_n, |
o_ddr_addr, o_ddr_ba, |
io_ddr_data, o_ddr_dm, o_ddr_odt, |
ddr3_reset_n, ddr3_cke, ddr3_ck_p, ddr3_ck_n, |
ddr3_cs_n, ddr3_ras_n, ddr3_cas_n, ddr3_we_n, |
ddr3_dqs_p, ddr3_dqs_n, |
ddr3_addr, ddr3_ba, |
ddr3_dq, ddr3_dm, ddr3_odt, |
// SD Card |
o_sd_sck, io_sd_cmd, io_sd, i_sd_cs, i_sd_wp, |
// GPS Pmod |
71,7 → 72,8
// PMod I/O |
i_aux_rx, i_aux_rts, o_aux_tx, o_aux_cts |
); |
input i_clk_100mhz, i_reset_btn; |
input [0:0] sys_clk_i; |
input i_reset_btn; |
input [3:0] i_sw; // Switches |
input [3:0] i_btn; // Buttons |
output wire [3:0] o_led; // LED |
87,17 → 89,18
output wire o_eth_mdclk; |
inout wire io_eth_mdio; |
// DDR3 SDRAM |
output wire o_ddr_reset_n; |
output wire o_ddr_cke; |
output wire o_ddr_ck_p, o_ddr_ck_n; |
output wire o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n; |
inout [1:0] io_ddr_dqs_p, io_ddr_dqs_n; |
output wire [13:0] o_ddr_addr; |
output wire [2:0] o_ddr_ba; |
inout [15:0] io_ddr_data; |
output wire ddr3_reset_n; |
output wire [0:0] ddr3_cke; |
output wire [0:0] ddr3_ck_p, ddr3_ck_n; |
output wire [0:0] ddr3_cs_n; |
output wire ddr3_ras_n, ddr3_cas_n, ddr3_we_n; |
output wire [2:0] ddr3_ba; |
output wire [13:0] ddr3_addr; |
output wire [0:0] ddr3_odt; |
output wire [1:0] ddr3_dm; |
inout [1:0] ddr3_dqs_p, ddr3_dqs_n; |
inout [15:0] ddr3_dq; |
// |
output wire [1:0] o_ddr_dm; |
output wire o_ddr_odt; |
// SD Card |
output wire o_sd_sck; |
inout io_sd_cmd; |
116,20 → 119,21
output wire o_aux_tx, o_aux_cts; |
|
// Build our master clock |
wire i_clk, clk_for_ddr, clk2_unused, enet_clk, clk5_unused, |
clk_feedback, clk_locked; |
wire s_clk, sys_clk, mem_clk_200mhz, |
clk1_unused, clk2_unused, enet_clk, clk4_unnused, |
clk5_unused, clk_feedback, clk_locked, mem_clk_200mhz_nobuf; |
PLLE2_BASE #( |
.BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW |
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360-360) |
.CLKIN1_PERIOD(10.0), // Input clock period in ns to ps resolution |
.CLKIN1_PERIOD(10.0), // Input clock period in ns resolution |
// CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: divide amount for each CLKOUT(1-128) |
.CLKFBOUT_MULT(8), // Multiply value for all CLKOUT (2-64) |
.CLKOUT0_DIVIDE(8), // 100 MHz (Main clock) |
.CLKOUT1_DIVIDE(8), // 100 MHz (DDR3 SDRAM clock) |
.CLKOUT2_DIVIDE(16), // 50 MHz (Flash clock, should we need it) |
.CLKOUT3_DIVIDE(32), // 25 MHz (Ethernet clock ?) |
.CLKOUT4_DIVIDE(16), // 50 MHz (Unused clock?) |
.CLKOUT5_DIVIDE(24), |
.CLKOUT0_DIVIDE(8), // 100 MHz (Clock for MIG) |
.CLKOUT1_DIVIDE(4), // 200 MHz (MIG Reference clock) |
.CLKOUT2_DIVIDE(32), // 50 MHz (Unused) |
.CLKOUT3_DIVIDE(64), // 25 MHz (Unused/Ethernet clock) |
.CLKOUT4_DIVIDE(32), // 50 MHz (Unused clock?) |
.CLKOUT5_DIVIDE(24), // 66 MHz |
// CLKOUT0_DUTY_CYCLE -- Duty cycle for each CLKOUT |
.CLKOUT0_DUTY_CYCLE(0.5), |
.CLKOUT1_DUTY_CYCLE(0.5), |
139,58 → 143,101
.CLKOUT5_DUTY_CYCLE(0.5), |
// CLKOUT0_PHASE -- phase offset for each CLKOUT |
.CLKOUT0_PHASE(0.0), |
.CLKOUT1_PHASE(90.0), |
.CLKOUT1_PHASE(0.0), |
.CLKOUT2_PHASE(0.0), |
.CLKOUT3_PHASE(0.0), |
.CLKOUT4_PHASE(0.0), |
.CLKOUT5_PHASE(0.0), |
.DIVCLK_DIVIDE(1), // Master division value , (1-56) |
.REF_JITTER1(0.0), // Reference input jitter in UI (0.000-0.999) |
.STARTUP_WAIT("FALSE") // Delayu DONE until PLL Locks, ("TRUE"/"FALSE") |
.REF_JITTER1(0.0), // Ref. input jitter in UI (0.000-0.999) |
.STARTUP_WAIT("TRUE") // Delay DONE until PLL Locks, ("TRUE"/"FALSE") |
) genclock( |
// Clock outputs: 1-bit (each) output |
.CLKOUT0(i_clk), |
.CLKOUT1(clk_for_ddr), |
.CLKOUT2(clk2_unused), // Reserved for flash, should we need it |
.CLKOUT0(mem_clk_nobuf), |
.CLKOUT1(mem_clk_200mhz_nobuf), |
.CLKOUT2(clk2_unused), |
.CLKOUT3(enet_clk), |
.CLKOUT4(clk4_unused), |
.CLKOUT5(clk5_unused), |
.CLKFBOUT(clk_feedback), // 1-bit output, feedback clock |
.LOCKED(clk_locked), |
.CLKIN1(i_clk_100mhz), |
.CLKIN1(sys_clk), |
.PWRDWN(1'b0), |
.RST(1'b0), |
.CLKFBIN(clk_feedback) // 1-bit input, feedback clock |
.CLKFBIN(clk_feedback_bufd) // 1-bit input, feedback clock |
); |
|
|
BUFH feedback_buffer(.I(clk_feedback),.O(clk_feedback_bufd)); |
// BUFG memref_buffer(.I(mem_clk_200mhz_nobuf),.O(mem_clk_200mhz)); |
IBUF sysclk_buf(.I(sys_clk_i[0]), .O(sys_clk)); |
|
// |
// |
// UART interface |
// |
// |
wire [29:0] bus_uart_setup; |
assign bus_uart_setup = 30'h10000019; // 4MBaud, 7 bits |
// assign bus_uart_setup = 30'h10000014; // ~4MBaud, 7 bits |
assign bus_uart_setup = 30'h10000051; // ~1MBaud, 7 bits |
|
wire [7:0] rx_data, tx_data; |
wire rx_break, rx_parity_err, rx_frame_err, rx_stb; |
wire tx_stb, tx_busy; |
|
reg pwr_reset, pre_reset; |
initial pwr_reset = 1'b1; |
// |
// RESET LOGIC |
// |
// Okay, so this looks bad at a first read--but it's not really that |
// bad. If you look close, there are two parts to the reset logic. |
// The first is the "PRE"-reset. This is a wire, set from the external |
// reset button. In good old-fashioned asynch-logic to synchronous |
// logic fashion, we synchronize this wire by registering it first |
// to pre_reset, and then to pwr_reset (the actual reset wire). |
// |
reg [7:0] pre_reset; |
reg pwr_reset; |
// Since all our stuff is synchronous to the clock that comes out of |
// the memory controller, sys_reset must needs come out of the memory |
// controller. |
// |
// Logic description starts with the PRE-reset, so as to make certain |
// we include the reset button. The memory controller wants an active |
// low reset here, so we provide such. |
initial pre_reset = 1'b0; |
always @(posedge i_clk) |
pre_reset <= ~i_reset_btn; |
always @(posedge i_clk) |
pwr_reset <= pre_reset; |
always @(posedge sys_clk) |
pre_reset <= ((!i_reset_btn)||(!clk_locked)) |
? 8'h00 : {pre_reset[6:0], 1'b1}; |
// |
// and then continues with the actual reset, now that we've |
// synchronized our reset button wire. This is an active LOW reset. |
initial pwr_reset = 1'b0; |
always @(posedge sys_clk) |
pwr_reset <= pre_reset[7]; |
// |
// Of course, this only goes into the memory controller. The true |
// device reset comes out of that memory controller, synchronized to |
// our memory generator provided clock(s) |
|
wire w_ck_uart, w_uart_tx; |
rxuart rcv(i_clk, pwr_reset, bus_uart_setup, i_uart_rx, |
rxuart rcv(s_clk, s_reset, bus_uart_setup, i_uart_rx, |
rx_stb, rx_data, rx_break, |
rx_parity_err, rx_frame_err, w_ck_uart); |
txuart txv(i_clk, pwr_reset, bus_uart_setup, 1'b0, |
txuart txv(s_clk, s_reset, bus_uart_setup|30'h8000000, 1'b0, |
tx_stb, tx_data, o_uart_tx, tx_busy); |
|
|
wire [3:0] w_led; |
reg [24:0] dbg_counter; |
always @(posedge sys_clk) |
dbg_counter <= dbg_counter + 25'h01; |
assign o_led = { w_led[3:2], |
((!pwr_reset)&(dbg_counter[24])) |
||((pwr_reset)&&(w_led[1])), |
(s_reset & dbg_counter[23]) |
||((!s_reset)&&(w_led[0])) }; |
|
|
|
|
////// |
// |
// |
197,37 → 244,46
// The WB bus interconnect, herein called busmaster, which handles |
// just about ... everything. It is in contrast to the other WB bus |
// interconnect, fastmaster, in that the busmaster build permits |
// peripherals that can *only* operate at 100MHz, no faster. |
// peripherals that can *only* operate at 80MHz, no faster, no slower. |
// |
// |
////// |
wire w_qspi_sck; |
wire w_qspi_sck, w_qspi_cs_n; |
wire [1:0] qspi_bmod; |
wire [3:0] qspi_dat; |
wire [3:0] i_qspi_dat; |
|
// |
wire [2:0] w_ddr_dqs; |
wire [31:0] wo_ddr_data, wi_ddr_data; |
// The SDRAM interface wires |
// |
wire ram_cyc, ram_stb, ram_we; |
wire [25:0] ram_addr; |
wire [31:0] ram_rdata, ram_wdata; |
wire ram_ack, ram_stall, ram_err; |
wire [31:0] ram_dbg; |
// |
wire w_mdio, w_mdwe; |
// |
wire w_sd_cmd; |
wire [3:0] w_sd_data; |
busmaster wbbus(i_clk, pwr_reset, |
busmaster wbbus(s_clk, s_reset, |
// External USB-UART bus control |
rx_stb, rx_data, tx_stb, tx_data, tx_busy, |
// Board lights and switches |
i_sw, i_btn, o_led, |
i_sw, i_btn, w_led, |
o_clr_led0, o_clr_led1, o_clr_led2, o_clr_led3, |
// Board level PMod I/O |
i_aux_rx, o_aux_tx, o_aux_cts, i_gps_rx, o_gps_tx, |
// Quad SPI flash |
o_qspi_cs_n, w_qspi_sck, qspi_dat, io_qspi_dat, qspi_bmod, |
w_qspi_cs_n, w_qspi_sck, qspi_dat, i_qspi_dat, qspi_bmod, |
// DDR3 SDRAM |
o_ddr_reset_n, o_ddr_cke, |
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
w_ddr_dqs, o_ddr_addr, o_ddr_ba, wo_ddr_data, wi_ddr_data, |
// o_ddr_reset_n, o_ddr_cke, o_ddr_ck_p, o_ddr_ck_n, |
// o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
// o_ddr_ba, o_ddr_addr, o_ddr_odt, o_ddr_dm, |
// io_ddr_dqs_p, io_ddr_dqs_n, io_ddr_data, |
ram_cyc, ram_stb, ram_we, ram_addr, ram_wdata, |
ram_ack, ram_stall, ram_rdata, ram_err, |
ram_dbg, |
// SD Card |
o_sd_sck, w_sd_cmd, w_sd_data, io_sd_cmd, io_sd, i_sd_cs, |
// Ethernet control (MDIO) lines |
264,32 → 320,25
// ?? Dual mode out (not yet) |
// |
// |
// assign io_qspi_dat = (~qspi_bmod[1])?({2'b11,1'bz,qspi_dat[0]}) |
// :((qspi_bmod[0])?(4'bzzzz):(qspi_dat[3:0])); |
// assign i_qspi_dat = io_qspi_dat; |
// |
wire [3:0] i_qspi_dat_ign; |
ODDR #(.DDR_CLK_EDGE("OPPOSITE_EDGE"), .INIT(1'b1), .SRTYPE("SYNC")) |
qsck( |
.Q(o_qspi_sck), |
.C(i_clk), |
.CE(1'b1), |
.D1(w_qspi_sck), |
.D2(w_qspi_sck), |
.R(1'b0), .S(1'b0)); |
xioddr qd0(i_clk, (~qspi_bmod[1])|(~qspi_bmod[0]), |
wire [3:0] i_qspi_pedge, i_qspi_nedge; |
|
xoddr xqspi_sck( s_clk, { w_qspi_sck, w_qspi_sck }, o_qspi_sck); |
xoddr xqspi_csn( s_clk, { w_qspi_cs_n, w_qspi_cs_n },o_qspi_cs_n); |
// |
xioddr xqspi_d0( s_clk, (qspi_bmod != 2'b11), |
{ qspi_dat[0], qspi_dat[0] }, |
{ i_qspi_dat_ign[0], i_qspi_dat[0] }, io_qspi_dat[0]); |
xioddr qd1(i_clk, (qspi_bmod == 2'b10), |
{ i_qspi_pedge[0], i_qspi_nedge[0] }, io_qspi_dat[0]); |
xioddr xqspi_d1( s_clk, (qspi_bmod==2'b10), |
{ qspi_dat[1], qspi_dat[1] }, |
{ i_qspi_dat_ign[1], i_qspi_dat[1] }, io_qspi_dat[1]); |
xioddr qd2(i_clk, (~qspi_bmod[1])||(~qspi_bmod[0]), |
{ qspi_dat[2], qspi_dat[2] }, |
{ i_qspi_dat_ign[2], i_qspi_dat[2] }, io_qspi_dat[2]); |
xioddr qd3(i_clk, (~qspi_bmod[1])||(~qspi_bmod[0]), |
{ qspi_dat[3], qspi_dat[3] }, |
{ i_qspi_dat_ign[3], i_qspi_dat[3] }, io_qspi_dat[3]); |
{ i_qspi_pedge[1], i_qspi_nedge[1] }, io_qspi_dat[1]); |
xioddr xqspi_d2( s_clk, (qspi_bmod!=2'b11), |
(qspi_bmod[1])?{ qspi_dat[2], qspi_dat[2] }:2'b11, |
{ i_qspi_pedge[2], i_qspi_nedge[2] }, io_qspi_dat[2]); |
xioddr xqspi_d3( s_clk, (qspi_bmod!=2'b11), |
(qspi_bmod[1])?{ qspi_dat[3], qspi_dat[3] }:2'b11, |
{ i_qspi_pedge[3], i_qspi_nedge[3] }, io_qspi_dat[3]); |
|
assign i_qspi_dat = i_qspi_pedge; |
// |
// Proposed QSPI mode select, to allow dual I/O mode |
// 000 Normal SPI mode |
299,74 → 348,8
// 110 Quad I/O mode output |
// |
// |
// assign io_qspi_dat[3:2] = (~qspi_bmod[2]) ? 2'b11 |
// : (qspi_bmod[0])?2'bzz : qspi_dat[3:2]; |
// assign io_qspi_dat[1] = (~qspi_bmod[1])?qspi_dat[1]:1'bz; |
// assign io_qspi_dat[0] = (qspi_bmod[0])?1'bz : qspi_dat[0]; |
|
// |
// |
// The following primitive is necessary in order to gain access |
// to the o_qspi_sck pin. |
// |
// |
/* |
wire [3:0] su_nc; // Startup primitive, no connect |
STARTUPE2 #( |
// Leave PROG_USR false to avoid activating the program |
// event security feature. Notes state that such a feature |
// requires encrypted bitstreams. |
.PROG_USR("FALSE"), |
// Sets the configuration clock frequency (in ns) for |
// simulation. |
.SIM_CCLK_FREQ(0.0) |
) STARTUPE2_inst ( |
// CFGCLK, 1'b output: Configuration main clock output -- no connect |
.CFGCLK(su_nc[0]), |
// CFGMCLK, 1'b output: Configuration internal oscillator clock output |
.CFGMCLK(su_nc[1]), |
// EOS, 1'b output: Active high output indicating the End Of Startup. |
.EOS(su_nc[2]), |
// PREQ, 1'b output: PROGRAM request to fabric output |
// Only enabled if PROG_USR is set. This lets the fabric know |
// that a request has been made (either JTAG or pin pulled low) |
// to program the device |
.PREQ(su_nc[3]), |
// CLK, 1'b input: User start-up clock input |
.CLK(1'b0), |
// GSR, 1'b input: Global Set/Reset input |
.GSR(1'b0), |
// GTS, 1'b input: Global 3-state input |
.GTS(1'b0), |
// KEYCLEARB, 1'b input: Clear AES Decrypter Key input from BBRAM |
.KEYCLEARB(1'b0), |
// PACK, 1-bit input: PROGRAM acknowledge input |
// This pin is only enabled if PROG_USR is set. This allows the |
// FPGA to acknowledge a request for reprogram to allow the FPGA |
// to get itself into a reprogrammable state first. |
.PACK(1'b0), |
// USRCLKO, 1-bit input: User CCLK input -- This is why I am using this |
// module at all. |
.USRCCLKO(qspi_sck), |
// USRCCLKTS, 1'b input: User CCLK 3-state enable input |
// An active high here places the clock into a high impedence |
// state. Since we wish to use the clock as an active output |
// always, we drive this pin low. |
.USRCCLKTS(1'b0), |
// USRDONEO, 1'b input: User DONE pin output control |
// Set this to "high" to make sure that the DONE LED pin is |
// high. |
.USRDONEO(1'b1), |
// USRDONETS, 1'b input: User DONE 3-state enable output |
// This enables the FPGA DONE pin to be active. Setting this |
// active high sets the DONE pin to high impedence, setting it |
// low allows the output of this pin to be as stated above. |
.USRDONETS(1'b1) |
); |
*/ |
|
|
|
// |
// |
// Wires for setting up the SD Card Controller |
377,7 → 360,6
assign io_sd[1] = w_sd_data[1]? 1'bz:1'b0; |
assign io_sd[2] = w_sd_data[2]? 1'bz:1'b0; |
assign io_sd[3] = w_sd_data[3]? 1'bz:1'b0; |
assign o_sd_wp = 1'b0; |
|
|
// |
387,73 → 369,31
// |
assign io_eth_mdio = (w_mdwe)?w_mdio : 1'bz; |
|
|
// |
// |
// Wires for setting up the DDR3 memory |
// Now, to set up our memory ... |
// |
// |
wire [31:0] r_ddr_data; |
migsdram rami( |
.i_clk(mem_clk_nobuf), .i_clk_200mhz(mem_clk_200mhz_nobuf), |
.o_sys_clk(s_clk), .i_rst(pwr_reset), .o_sys_reset(s_reset), |
.i_wb_cyc(ram_cyc), .i_wb_stb(ram_stb), .i_wb_we(ram_we), |
.i_wb_addr(ram_addr), .i_wb_data(ram_wdata), |
.i_wb_sel(4'hf), |
.o_wb_ack(ram_ack), .o_wb_stall(ram_stall), |
.o_wb_data(ram_rdata), .o_wb_err(ram_err), |
.o_ddr_ck_p(ddr3_ck_p), .o_ddr_ck_n(ddr3_ck_n), |
.o_ddr_reset_n(ddr3_reset_n), .o_ddr_cke(ddr3_cke), |
.o_ddr_cs_n(ddr3_cs_n), .o_ddr_ras_n(ddr3_ras_n), |
.o_ddr_cas_n(ddr3_cas_n), .o_ddr_we_n(ddr3_we_n), |
.o_ddr_ba(ddr3_ba), .o_ddr_addr(ddr3_addr), |
.o_ddr_odt(ddr3_odt), .o_ddr_dm(ddr3_dm), |
.io_ddr_dqs_p(ddr3_dqs_p), .io_ddr_dqs_n(ddr3_dqs_n), |
.io_ddr_data(ddr3_dq), |
// |
.o_ram_dbg(ram_dbg) |
); |
|
xioddr p0(i_clk, ~o_ddr_we_n, { wo_ddr_data[16], wo_ddr_data[0] }, |
{ wi_ddr_data[16], wi_ddr_data[0] }, io_ddr_data[0]); |
|
xioddr p1(i_clk, ~o_ddr_we_n, { wo_ddr_data[17], wo_ddr_data[1] }, |
{ wi_ddr_data[17], wi_ddr_data[1] }, io_ddr_data[1]); |
|
xioddr p2(i_clk, ~o_ddr_we_n, { wo_ddr_data[18], wo_ddr_data[2] }, |
{ wi_ddr_data[18], wi_ddr_data[2] }, io_ddr_data[2]); |
|
xioddr p3(i_clk, ~o_ddr_we_n, { wo_ddr_data[19], wo_ddr_data[3] }, |
{ wi_ddr_data[19], wi_ddr_data[3] }, io_ddr_data[3]); |
|
xioddr p4(i_clk, ~o_ddr_we_n, { wo_ddr_data[20], wo_ddr_data[4] }, |
{ wi_ddr_data[20], wi_ddr_data[4] }, io_ddr_data[4]); |
|
xioddr p5(i_clk, ~o_ddr_we_n, { wo_ddr_data[21], wo_ddr_data[5] }, |
{ wi_ddr_data[21], wi_ddr_data[5] }, io_ddr_data[5]); |
|
xioddr p6(i_clk, ~o_ddr_we_n, { wo_ddr_data[22], wo_ddr_data[6] }, |
{ wi_ddr_data[22], wi_ddr_data[6] }, io_ddr_data[6]); |
|
xioddr p7(i_clk, ~o_ddr_we_n, { wo_ddr_data[23], wo_ddr_data[7] }, |
{ wi_ddr_data[23], wi_ddr_data[7] }, io_ddr_data[7]); |
|
xioddr p8(i_clk, ~o_ddr_we_n, { wo_ddr_data[24], wo_ddr_data[8] }, |
{ wi_ddr_data[24], wi_ddr_data[8] }, io_ddr_data[8]); |
|
xioddr p9(i_clk, ~o_ddr_we_n, { wo_ddr_data[25], wo_ddr_data[9] }, |
{ wi_ddr_data[25], wi_ddr_data[9] }, io_ddr_data[9]); |
|
xioddr pa(i_clk, ~o_ddr_we_n, { wo_ddr_data[26], wo_ddr_data[10] }, |
{ wi_ddr_data[26], wi_ddr_data[10] }, io_ddr_data[10]); |
|
xioddr pb(i_clk, ~o_ddr_we_n, { wo_ddr_data[27], wo_ddr_data[11] }, |
{ wi_ddr_data[27], wi_ddr_data[11] }, io_ddr_data[11]); |
|
xioddr pc(i_clk, ~o_ddr_we_n, { wo_ddr_data[28], wo_ddr_data[12] }, |
{ wi_ddr_data[28], wi_ddr_data[12] }, io_ddr_data[12]); |
|
xioddr pd(i_clk, ~o_ddr_we_n, { wo_ddr_data[29], wo_ddr_data[13] }, |
{ wi_ddr_data[29], wi_ddr_data[13] }, io_ddr_data[13]); |
|
xioddr pe(i_clk, ~o_ddr_we_n, { wo_ddr_data[30], wo_ddr_data[14] }, |
{ wi_ddr_data[30], wi_ddr_data[14] }, io_ddr_data[14]); |
|
xioddr pf(i_clk, ~o_ddr_we_n, { wo_ddr_data[31], wo_ddr_data[15] }, |
{ wi_ddr_data[31], wi_ddr_data[15] }, io_ddr_data[15]); |
|
OBUFTDS #(.IOSTANDARD("DIFF_SSTL135"), .SLEW("FAST")) |
dqsbuf0(.O(io_ddr_dqs_p[0]), .OB(io_ddr_dqs_n[0]), |
.I(w_ddr_dqs[1]), .T(w_ddr_dqs[2])); |
OBUFTDS #(.IOSTANDARD("DIFF_SSTL135"), .SLEW("FAST")) |
dqsbuf1(.O(io_ddr_dqs_p[1]), .OB(io_ddr_dqs_n[1]), |
.I(w_ddr_dqs[0]), .T(w_ddr_dqs[2])); |
|
OBUFDS #(.IOSTANDARD("DIFF_SSTL135"), .SLEW("FAST")) |
clkbuf(.O(o_ddr_ck_p), .OB(o_ddr_ck_n), .I(clk_for_ddr)); |
|
assign o_ddr_dm = 2'b00; |
assign o_ddr_odt = 1'b0; |
|
endmodule |
|
/openarty/trunk/rtl/gpsclock_tb.v
70,7 → 70,7
if ((i_wb_cyc_stb)&&(i_wb_we)) |
begin |
case(i_wb_addr) |
3'b000: r_maxcount <= i_wb_data; |
3'b000: r_maxcount <= i_wb_data; |
3'b001: r_jump <= i_wb_data; |
// 2'b11: r_def_step <= i_wb_data; |
default: begin end |
94,7 → 94,7
3'b101: o_wb_data <= r_count[31:0]; |
3'b110: o_wb_data <= r_step[63:32]; |
3'b111: begin o_wb_data <= r_step[31:0]; r_halt <= 1'b0; end |
default: o_wb_data <= 0; |
// default: o_wb_data <= 0; |
endcase |
|
always @(posedge i_clk) |
/openarty/trunk/rtl/rtcgps.v
54,10 → 54,12
// Our personal timing, for debug purposes |
o_rtc_pps); |
parameter DEFAULT_SPEED = 32'd2814750; //2af31e = 2^48 / 100e6 MHz |
input i_clk; |
input i_wb_cyc, i_wb_stb, i_wb_we; |
input [1:0] i_wb_addr; |
input [31:0] i_wb_data; |
// |
input i_clk; |
// |
input i_wb_cyc, i_wb_stb, i_wb_we; |
input [1:0] i_wb_addr; |
input [31:0] i_wb_data; |
// input i_btn; |
output reg [31:0] o_data; |
output wire o_interrupt, o_ppd; |
/openarty/trunk/rtl/migsdram.v
0,0 → 1,307
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: migsdram.v |
// |
// Project: OpenArty, an entirely open SoC based upon the Arty platform |
// |
// Purpose: To interface the Arty to a MIG Generated SDRAM |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015-2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
module migsdram(i_clk, i_clk_200mhz, o_sys_clk, i_rst, o_sys_reset, |
// Wishbone components |
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, i_wb_sel, |
o_wb_ack, o_wb_stall, o_wb_data, o_wb_err, |
// SDRAM connections |
o_ddr_ck_p, o_ddr_ck_n, |
o_ddr_reset_n, o_ddr_cke, |
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
o_ddr_ba, o_ddr_addr, |
o_ddr_odt, o_ddr_dm, |
io_ddr_dqs_p, io_ddr_dqs_n, |
io_ddr_data, |
// Debug connection |
o_ram_dbg |
); |
parameter DDRWIDTH = 16, WBDATAWIDTH=32; |
parameter AXIDWIDTH = 6; |
// The SDRAM address bits (RAMABITS) are a touch more difficult to work |
// out. Here we leave them as a fixed parameter, but there are |
// consequences to this. Specifically, the wishbone data width, the |
// wishbone address width, and this number have interactions not |
// well captured here. |
parameter RAMABITS = 28; |
// All DDR3 memories have 8 timeslots. This, if the DDR3 memory |
// has 16 bits to it (as above), the entire transaction must take |
// AXIWIDTH bits ... |
localparam AXIWIDTH= DDRWIDTH *8; |
localparam DW=WBDATAWIDTH; |
localparam AW=(WBDATAWIDTH==32)? RAMABITS-2 |
:((WBDATAWIDTH==64) ? RAMABITS-3 |
:((WBDATAWIDTH==128) ? RAMABITS-4 |
: RAMABITS-5)); // (WBDATAWIDTH==256) |
localparam SELW= (WBDATAWIDTH/8); |
// |
input i_clk, i_clk_200mhz, i_rst; |
output o_sys_clk; |
output reg o_sys_reset; |
// |
input i_wb_cyc, i_wb_stb, i_wb_we; |
input [(AW-1):0] i_wb_addr; |
input [(DW-1):0] i_wb_data; |
input [(SELW-1):0] i_wb_sel; |
output wire o_wb_ack, o_wb_stall; |
output wire [(DW-1):0] o_wb_data; |
output wire o_wb_err; |
// |
output wire [0:0] o_ddr_ck_p, o_ddr_ck_n; |
output wire [0:0] o_ddr_cke; |
output wire o_ddr_reset_n, |
o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n; |
output wire [0:0] o_ddr_cs_n; |
output wire [2:0] o_ddr_ba; |
output wire [13:0] o_ddr_addr; |
output wire [0:0] o_ddr_odt; |
output wire [(DDRWIDTH/8-1):0] o_ddr_dm; |
inout wire [1:0] io_ddr_dqs_p, io_ddr_dqs_n; |
inout wire [(DDRWIDTH-1):0] io_ddr_data; |
|
output wire [31:0] o_ram_dbg; |
|
|
`define SDRAM_ACCESS |
`ifdef SDRAM_ACCESS |
|
wire aresetn; |
assign aresetn = 1'b1; // Never reset |
|
// Write address channel |
wire [(AXIDWIDTH-1):0] s_axi_awid; |
wire [(RAMABITS-1):0] s_axi_awaddr; |
wire [7:0] s_axi_awlen; |
wire [2:0] s_axi_awsize; |
wire [1:0] s_axi_awburst; |
wire [0:0] s_axi_awlock; |
wire [3:0] s_axi_awcache; |
wire [2:0] s_axi_awprot; |
wire [3:0] s_axi_awqos; |
wire s_axi_awvalid; |
wire s_axi_awready; |
// Writei data channel |
wire [(AXIWIDTH-1):0] s_axi_wdata; |
wire [(AXIWIDTH/8-1):0] s_axi_wstrb; |
wire s_axi_wlast, s_axi_wvalid, s_axi_wready; |
// Write response channel |
wire s_axi_bready; |
wire [(AXIDWIDTH-1):0] s_axi_bid; |
wire [1:0] s_axi_bresp; |
wire s_axi_bvalid; |
|
// Read address channel |
wire [(AXIDWIDTH-1):0] s_axi_arid; |
wire [(RAMABITS-1):0] s_axi_araddr; |
wire [7:0] s_axi_arlen; |
wire [2:0] s_axi_arsize; |
wire [1:0] s_axi_arburst; |
wire [0:0] s_axi_arlock; |
wire [3:0] s_axi_arcache; |
wire [2:0] s_axi_arprot; |
wire [3:0] s_axi_arqos; |
wire s_axi_arvalid; |
// Read response/data channel |
wire [(AXIDWIDTH-1):0] s_axi_rid; |
wire [(AXIWIDTH-1):0] s_axi_rdata; |
wire [1:0] s_axi_rresp; |
wire s_axi_rlast; |
wire s_axi_rvalid; |
|
// Other wires ... |
wire init_calib_complete, mmcm_locked; |
wire app_sr_active, app_ref_ack, app_zq_ack; |
wire app_sr_req, app_ref_req, app_zq_req; |
wire w_sys_reset; |
wire [11:0] w_device_temp; |
|
|
mig_axis mig_sdram( |
.ddr3_ck_p(o_ddr_ck_p), .ddr3_ck_n(o_ddr_ck_n), |
.ddr3_reset_n(o_ddr_reset_n), .ddr3_cke(o_ddr_cke), |
.ddr3_cs_n(o_ddr_cs_n), .ddr3_ras_n(o_ddr_ras_n), |
.ddr3_we_n(o_ddr_we_n), .ddr3_cas_n(o_ddr_cas_n), |
.ddr3_ba(o_ddr_ba), .ddr3_addr(o_ddr_addr), |
.ddr3_odt(o_ddr_odt), |
.ddr3_dqs_p(io_ddr_dqs_p), .ddr3_dqs_n(io_ddr_dqs_n), |
.ddr3_dq(io_ddr_data), .ddr3_dm(o_ddr_dm), |
// |
.sys_clk_i(i_clk), |
.clk_ref_i(i_clk_200mhz), |
.ui_clk(o_sys_clk), |
.ui_clk_sync_rst(w_sys_reset), |
.mmcm_locked(mmcm_locked), |
.aresetn(aresetn), |
.app_sr_req(1'b0), |
.app_ref_req(1'b0), |
.app_zq_req(1'b0), |
.app_sr_active(app_sr_active), |
.app_ref_ack(app_ref_ack), |
.app_zq_ack(app_zq_ack), |
// |
.s_axi_awid(s_axi_awid), .s_axi_awaddr(s_axi_awaddr), |
.s_axi_awlen(s_axi_awlen), .s_axi_awsize(s_axi_awsize), |
.s_axi_awburst(s_axi_awburst), .s_axi_awlock(s_axi_awlock), |
.s_axi_awcache(s_axi_awcache), .s_axi_awprot(s_axi_awprot), |
.s_axi_awqos(s_axi_awqos), .s_axi_awvalid(s_axi_awvalid), |
.s_axi_awready(s_axi_awready), |
// |
.s_axi_wready( s_axi_wready), |
.s_axi_wdata( s_axi_wdata), |
.s_axi_wstrb( s_axi_wstrb), |
.s_axi_wlast( s_axi_wlast), |
.s_axi_wvalid( s_axi_wvalid), |
// |
.s_axi_bready(s_axi_bready), .s_axi_bid(s_axi_bid), |
.s_axi_bresp(s_axi_bresp), .s_axi_bvalid(s_axi_bvalid), |
// |
.s_axi_arid(s_axi_arid), .s_axi_araddr(s_axi_araddr), |
.s_axi_arlen(s_axi_arlen), .s_axi_arsize(s_axi_arsize), |
.s_axi_arburst(s_axi_arburst), .s_axi_arlock(s_axi_arlock), |
.s_axi_arcache(s_axi_arcache), .s_axi_arprot(s_axi_arprot), |
.s_axi_arqos(s_axi_arqos), .s_axi_arvalid(s_axi_arvalid), |
.s_axi_arready(s_axi_arready), |
// |
.s_axi_rready(s_axi_rready), .s_axi_rid(s_axi_rid), |
.s_axi_rdata(s_axi_rdata), .s_axi_rresp(s_axi_rresp), |
.s_axi_rlast(s_axi_rlast), .s_axi_rvalid(s_axi_rvalid), |
.init_calib_complete(init_calib_complete), |
.sys_rst(i_rst), |
.device_temp(w_device_temp) |
); |
|
wbm2axisp #( |
.C_AXI_ID_WIDTH(AXIDWIDTH), |
.C_AXI_DATA_WIDTH(AXIWIDTH), |
.C_AXI_ADDR_WIDTH(RAMABITS), |
.AW(AW), .DW(DW) |
) |
bus_translator ( |
.i_clk(o_sys_clk), |
// .i_reset(i_rst), // internally unused |
// Write address channel signals |
.o_axi_awid( s_axi_awid), |
.o_axi_awaddr( s_axi_awaddr), |
.o_axi_awlen( s_axi_awlen), |
.o_axi_awsize( s_axi_awsize), |
.o_axi_awburst( s_axi_awburst), |
.o_axi_awlock( s_axi_awlock), |
.o_axi_awcache( s_axi_awcache), |
.o_axi_awprot( s_axi_awprot), // s_axi_awqos |
.o_axi_awqos( s_axi_awqos), // s_axi_awqos |
.o_axi_awvalid( s_axi_awvalid), |
.i_axi_awready( s_axi_awready), |
// |
.i_axi_wready( s_axi_wready), |
.o_axi_wdata( s_axi_wdata), |
.o_axi_wstrb( s_axi_wstrb), |
.o_axi_wlast( s_axi_wlast), |
.o_axi_wvalid( s_axi_wvalid), |
// |
.o_axi_bready( s_axi_bready), |
.i_axi_bid( s_axi_bid), |
.i_axi_bresp( s_axi_bresp), |
.i_axi_bvalid( s_axi_bvalid), |
// |
.i_axi_arready( s_axi_arready), |
.o_axi_arid( s_axi_arid), |
.o_axi_araddr( s_axi_araddr), |
.o_axi_arlen( s_axi_arlen), |
.o_axi_arsize( s_axi_arsize), |
.o_axi_arburst( s_axi_arburst), |
.o_axi_arlock( s_axi_arlock), |
.o_axi_arcache( s_axi_arcache), |
.o_axi_arprot( s_axi_arprot), |
.o_axi_arqos( s_axi_arqos), |
.o_axi_arvalid( s_axi_arvalid), |
// |
.o_axi_rready( s_axi_rready), |
.i_axi_rid( s_axi_rid), |
.i_axi_rdata( s_axi_rdata), |
.i_axi_rresp( s_axi_rresp), |
.i_axi_rlast( s_axi_rlast), |
.i_axi_rvalid( s_axi_rvalid), |
// |
.i_wb_cyc( i_wb_cyc), |
.i_wb_stb( i_wb_stb), |
.i_wb_we( i_wb_we), |
.i_wb_addr( i_wb_addr), |
.i_wb_data( i_wb_data), |
.i_wb_sel( i_wb_sel), |
// |
.o_wb_ack( o_wb_ack), |
.o_wb_stall( o_wb_stall), |
.o_wb_data( o_wb_data), |
.o_wb_err( o_wb_err), |
// |
.o_dbg( o_ram_dbg) |
); |
|
// Convert from active low to active high, *and* hold the system in |
// reset until the memory comes up. |
initial o_sys_reset = 1'b1; |
always @(posedge o_sys_clk) |
o_sys_reset <= (w_sys_reset) |
||(!init_calib_complete) |
||(!mmcm_locked); |
`else |
BUFG sysclk(i_clk, o_sys_clk); |
initial o_sys_reset <= 1'b1; |
always @(posedge i_clk) |
o_sys_reset <= 1'b1; |
|
OBUFDS ckobuf(.I(i_clk), .O(o_ddr_ck_p), .OB(o_ddr_ck_n)); |
|
assign o_ddr_reset_n = 1'b0; |
assign o_ddr_cke[0] = 1'b0; |
assign o_ddr_cs_n[0] = 1'b1; |
assign o_ddr_cas_n = 1'b1; |
assign o_ddr_ras_n = 1'b1; |
assign o_ddr_we_n = 1'b1; |
assign o_ddr_ba = 3'h0; |
assign o_ddr_addr = 14'h00; |
assign o_ddr_dm = 2'b00; |
assign io_ddr_data = 16'h0; |
|
OBUFDS dqsbufa(.I(i_clk), .O(io_ddr_dqs_p[1]), .OB(io_ddr_dqs_n[1])); |
OBUFDS dqsbufb(.I(i_clk), .O(io_ddr_dqs_p[0]), .OB(io_ddr_dqs_n[0])); |
|
`endif |
|
endmodule |
|
|
/openarty/trunk/rtl/gpsclock.v
102,6 → 102,7
i_wb_cyc_stb, i_wb_we, i_wb_addr, i_wb_data, |
o_wb_ack, o_wb_stall, o_wb_data, |
o_tracking, o_count, o_step, o_err, o_locked, o_dbg); |
parameter DEFAULT_STEP = 32'h834d_c736;//2^64/81.25 MHz |
parameter RW=64, // Needs to be 2ceil(Log_2(i_clk frequency)) |
DW=32, // The width of our data bus |
ONE_SECOND = 0, |
177,8 → 178,9
// |
// |
// |
// DEFAULT_STEP = 64'h0000_002a_f31d_c461, // 2^64 / 100 MHz |
initial r_def_step = 32'h8_2af_31dc; |
// DEFAULT_STEP = 64'h0000_0034_dc73_67da, // 2^64 / 100 MHz |
// 28'h34d_c736 << 8, and hence we have 32'h834d_c736 |
initial r_def_step = DEFAULT_STEP; |
always @(posedge i_clk) |
pre_step <= { 16'h00, |
(({ r_def_step[27:0], 20'h00 })>>r_def_step[31:28])}; |
208,7 → 210,7
2'b01: r_beta <= wb_data; |
2'b10: r_gamma <= wb_data; |
2'b11: r_def_step <= wb_data; |
default: begin end |
// default: begin end |
// r_defstep <= i_wb_data; |
endcase |
end else |
219,7 → 221,7
2'b01: o_wb_data <= r_beta; |
2'b10: o_wb_data <= r_gamma; |
2'b11: o_wb_data <= r_def_step; |
default: o_wb_data <= 0; |
// default: o_wb_data <= 0; |
endcase |
|
reg dly_config; |
/openarty/trunk/rtl/Makefile
42,8 → 42,8
.PHONY: test |
test: $(VDIRFB)/Veqspiflash__ALL.a |
test: $(VDIRFB)/Venetctrl__ALL.a |
test: $(VDIRFB)/Vfastmaster__ALL.a |
# test: $(VDIRFB)/Vfastmaster__ALL.a |
test: $(VDIRFB)/Vbusmaster__ALL.a |
|
CPUDR := cpu |
CPUSOURCESnD := zipcpu.v fastops.v pfcache.v pipemem.v \ |
56,7 → 56,7
wbucompress.v wbudecompress.v wbudeword.v wbuexec.v \ |
wbuidleint.v wbuinput.v wbuoutput.v wbureadcw.v wbusixchar.v \ |
wbutohex.v |
PERIPHERALS:= enetctrl.v fastio.v icontrol.v rtcdate.v rtcgps.v \ |
PERIPHERALS:= enetctrl.v fastio.v rtcdate.v rtcgps.v \ |
rxuart.v txuart.v eqspiflash.v lleqspi.v flash_config.v \ |
wbicapetwo.v sdspi.v gpsclock_tb.v gpsclock.v wboled.v lloled.v \ |
wbscopc.v wbscope.v memdev.v wbddrsdram.v |
/openarty/trunk/rtl/bigsmpy.v
36,82 → 36,143
// |
// |
module bigsmpy(i_clk, i_sync, i_sgn, i_a, i_b, o_r, o_sync); |
parameter CLOCKS = 1; |
input i_clk, i_sync, i_sgn; |
input [31:0] i_a, i_b; |
output reg [63:0] o_r; |
output reg o_sync; |
|
// |
// A pipeline, shift register, to track our synchronization pulse |
reg [3:0] r_s; |
generate |
if (CLOCKS == 1) |
begin |
wire signed [31:0] w_sa, w_sb; |
wire [31:0] w_ua, w_ub; |
|
// |
reg r_mpy_signed; |
reg [31:0] r_mpy_a_input, r_mpy_b_input; |
always @(posedge i_clk) |
assign w_sa = i_a; |
assign w_sb = i_b; |
assign w_ua = i_a; |
assign w_ub = i_b; |
|
always @(posedge i_clk) |
begin |
o_sync <= i_sync; |
if (i_sgn) |
o_r <= w_sa * w_sb; |
else |
o_r <= w_ua * w_ub; |
end |
|
end else if (CLOCKS == 2) |
begin |
if (i_sgn) |
reg signed [31:0] r_sa, r_sb; |
wire [31:0] w_ua, w_ub; |
|
always @(posedge i_clk) |
begin |
r_mpy_a_input <= {(~i_a[31]), i_a[30:0] }; |
r_mpy_b_input <= {(~i_b[31]), i_b[30:0] }; |
end else begin |
r_mpy_a_input <= i_a[31:0]; |
r_mpy_b_input <= i_b[31:0]; |
r_sa = i_a; |
r_sb = i_b; |
end |
|
r_mpy_signed <= i_sgn; |
r_s[0] <= i_sync; |
end |
assign w_ua = r_sa; |
assign w_ub = r_sb; |
|
reg [31:0] pp_f, pp_o, pp_i, pp_l; |
reg [32:0] pp_s; |
always @(posedge i_clk) |
always @(posedge i_clk) |
begin |
o_sync <= i_sync; |
if (i_sgn) |
o_r <= r_sa * r_sb; |
else |
o_r <= w_ua * w_ub; |
end |
|
|
end else if (CLOCKS == 5) |
begin |
pp_f <= r_mpy_a_input[31:16] * r_mpy_b_input[31:16]; |
pp_o <= r_mpy_a_input[31:16] * r_mpy_b_input[15: 0]; |
pp_i <= r_mpy_a_input[15: 0] * r_mpy_b_input[31:16]; |
pp_l <= r_mpy_a_input[15: 0] * r_mpy_b_input[15: 0]; |
// |
// A pipeline, shift register, to track our |
// synchronization pulse as it transits our pipeline |
// |
reg [3:0] r_s; |
|
if (r_mpy_signed) |
pp_s <= 32'h8000_0000 - (r_mpy_a_input[31:0] |
+ r_mpy_b_input[31:0]); |
else |
pp_s <= 33'h0; |
r_s[1] <= r_s[0]; |
end |
// |
// Clock #1: Register our inputs, copy the value of the sign |
// bit. |
reg r_mpy_signed; |
reg [31:0] r_mpy_a_input, r_mpy_b_input; |
always @(posedge i_clk) |
begin |
if (i_sgn) |
begin |
// This is about more than making the inputs |
// unsigned, as you'll notice it makes positive |
// inputs otherwise negative. Instead, |
// this is about making the inputs have offset |
// mode. Hence |
// i_a = r_mpy_a_input - 2^31 |
// and so forth |
r_mpy_a_input <= {(~i_a[31]), i_a[30:0] }; |
r_mpy_b_input <= {(~i_b[31]), i_b[30:0] }; |
end else begin |
r_mpy_a_input <= i_a[31:0]; |
r_mpy_b_input <= i_b[31:0]; |
end |
|
reg [32:0] partial_mpy_oi, partial_mpy_lo; |
reg [31:0] partial_mpy_hi; |
always @(posedge i_clk) |
begin |
partial_mpy_lo[30: 0] <= pp_l[30:0]; |
partial_mpy_lo[32:31] <= pp_s[0] + pp_l[31]; |
partial_mpy_oi[32: 0] <= pp_o + pp_i; |
partial_mpy_hi[31: 0] <= pp_s[32:1] + pp_f; |
r_s[2] <= r_s[1]; |
end |
r_mpy_signed <= i_sgn; |
r_s[0] <= i_sync; |
end |
|
reg partial_mpy_2cl, partial_mpy_2ch; |
reg [31:0] partial_mpy_2lo, partial_mpy_2hi; |
always @(posedge i_clk) |
begin |
partial_mpy_2lo[15:0] <= partial_mpy_lo[15:0]; |
{ partial_mpy_2cl, partial_mpy_2lo[31:16] } |
<= { 1'b0, partial_mpy_oi[15:0]}+ partial_mpy_lo[32:16]; |
{ partial_mpy_2ch, partial_mpy_2hi[16:0] } |
<= partial_mpy_oi[32:16] + partial_mpy_hi[16:0]; |
partial_mpy_2hi[31:16] <= { partial_mpy_2hi[31:17], 1'b0 }; |
r_s[3] <= r_s[2]; |
end |
reg [31:0] pp_f, pp_o, pp_i, pp_l; |
reg [32:0] pp_s; |
always @(posedge i_clk) |
begin |
pp_f <= r_mpy_a_input[31:16] * r_mpy_b_input[31:16]; |
pp_o <= r_mpy_a_input[31:16] * r_mpy_b_input[15: 0]; |
pp_i <= r_mpy_a_input[15: 0] * r_mpy_b_input[31:16]; |
pp_l <= r_mpy_a_input[15: 0] * r_mpy_b_input[15: 0]; |
|
always @(posedge i_clk) |
begin |
o_r[31: 0] <= partial_mpy_2lo[31:0]; |
o_r[63:32] <= partial_mpy_2hi |
+ { 13'h0, partial_mpy_2ch, 1'b0, |
15'h0, partial_mpy_2cl }; |
o_sync <= r_s[3]; |
end |
if (r_mpy_signed) |
pp_s <= 32'h8000_0000 - (r_mpy_a_input[31:0] |
+ r_mpy_b_input[31:0]); |
else |
pp_s <= 33'h0; |
r_s[1] <= r_s[0]; |
end |
|
reg [32:0] partial_mpy_oi, partial_mpy_lo; |
reg [31:0] partial_mpy_hi; |
always @(posedge i_clk) |
begin |
partial_mpy_lo[30: 0] <= pp_l[30:0]; |
partial_mpy_lo[32:31] <= pp_s[0] + pp_l[31]; |
partial_mpy_oi[32: 0] <= pp_o + pp_i; |
partial_mpy_hi[31: 0] <= pp_s[32:1] + pp_f; |
r_s[2] <= r_s[1]; |
end |
|
reg partial_mpy_2cl, partial_mpy_2ch; |
reg [31:0] partial_mpy_2lo, partial_mpy_2hi; |
always @(posedge i_clk) |
begin |
partial_mpy_2lo[15:0] <= partial_mpy_lo[15:0]; |
{ partial_mpy_2cl, partial_mpy_2lo[31:16] } |
<= { 1'b0, partial_mpy_oi[15:0]} |
+ partial_mpy_lo[32:16]; |
{ partial_mpy_2ch, partial_mpy_2hi[16:0] } |
<= partial_mpy_oi[32:16] + partial_mpy_hi[16:0]; |
partial_mpy_2hi[31:16] <= { partial_mpy_2hi[31:17], |
1'b0 }; |
r_s[3] <= r_s[2]; |
end |
|
always @(posedge i_clk) |
begin |
o_r[31: 0] <= partial_mpy_2lo[31:0]; |
o_r[63:32] <= partial_mpy_2hi |
+ { 14'h0, partial_mpy_2ch, 1'b0, |
15'h0, partial_mpy_2cl }; |
o_sync <= r_s[3]; |
end |
end endgenerate |
|
|
endmodule |
/openarty/trunk/rtl/wbm2axisp.v
0,0 → 1,390
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: wbm2axisp.v |
// |
// Project: Pipelined Wishbone to AXI converter |
// |
// Purpose: The B4 Wishbone SPEC allows transactions at a speed as fast as |
// one per clock. The AXI bus allows transactions at a speed of |
// one read and one write transaction per clock. These capabilities work |
// by allowing requests to take place prior to responses, such that the |
// requests might go out at once per clock and take several clocks, and |
// the responses may start coming back several clocks later. In other |
// words, both protocols allow multiple transactions to be "in flight" at |
// the same time. Current wishbone to AXI converters, however, handle only |
// one transaction at a time: initiating the transaction, and then waiting |
// for the transaction to complete before initiating the next. |
// |
// The purpose of this core is to maintain the speed of both busses, while |
// transiting from the Wishbone (as master) to the AXI bus (as slave) and |
// back again. |
// |
// Since the AXI bus allows transactions to be reordered, whereas the |
// wishbone does not, this core can be configured to reorder return |
// transactions as well. |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2016, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or (at |
// your option) any later version. |
// |
// This program is distributed in the hope that it will be useful, but WITHOUT |
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
// License: GPL, v3, as defined and found on www.gnu.org, |
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
module wbm2axisp #( |
parameter C_AXI_ID_WIDTH = 6, // The AXI id width used for R&W |
// This is an int between 1-16 |
parameter C_AXI_DATA_WIDTH = 128,// Width of the AXI R&W data |
parameter C_AXI_ADDR_WIDTH = 28, // AXI Address width |
parameter DW = 32, // Wishbone data width |
parameter AW = 26, // Wishbone address width |
parameter STRICT_ORDER = 0 // Reorder, or not? 0 -> Reorder |
) ( |
input i_clk, // System clock |
// input i_reset,// Wishbone reset signal--unused |
|
// AXI write address channel signals |
input i_axi_awready, // Slave is ready to accept |
output reg [C_AXI_ID_WIDTH-1:0] o_axi_awid, // Write ID |
output reg [C_AXI_ADDR_WIDTH-1:0] o_axi_awaddr, // Write address |
output wire [7:0] o_axi_awlen, // Write Burst Length |
output wire [2:0] o_axi_awsize, // Write Burst size |
output wire [1:0] o_axi_awburst, // Write Burst type |
output wire [0:0] o_axi_awlock, // Write lock type |
output wire [3:0] o_axi_awcache, // Write Cache type |
output wire [2:0] o_axi_awprot, // Write Protection type |
output wire [3:0] o_axi_awqos, // Write Quality of Svc |
output reg o_axi_awvalid, // Write address valid |
|
// AXI write data channel signals |
input i_axi_wready, // Write data ready |
output reg [C_AXI_DATA_WIDTH-1:0] o_axi_wdata, // Write data |
output reg [C_AXI_DATA_WIDTH/8-1:0] o_axi_wstrb, // Write strobes |
output wire o_axi_wlast, // Last write transaction |
output reg o_axi_wvalid, // Write valid |
|
// AXI write response channel signals |
input [C_AXI_ID_WIDTH-1:0] i_axi_bid, // Response ID |
input [1:0] i_axi_bresp, // Write response |
input i_axi_bvalid, // Write reponse valid |
output wire o_axi_bready, // Response ready |
|
// AXI read address channel signals |
input i_axi_arready, // Read address ready |
output wire [C_AXI_ID_WIDTH-1:0] o_axi_arid, // Read ID |
output wire [C_AXI_ADDR_WIDTH-1:0] o_axi_araddr, // Read address |
output wire [7:0] o_axi_arlen, // Read Burst Length |
output wire [2:0] o_axi_arsize, // Read Burst size |
output wire [1:0] o_axi_arburst, // Read Burst type |
output wire [0:0] o_axi_arlock, // Read lock type |
output wire [3:0] o_axi_arcache, // Read Cache type |
output wire [2:0] o_axi_arprot, // Read Protection type |
output wire [3:0] o_axi_arqos, // Read Protection type |
output reg o_axi_arvalid, // Read address valid |
|
// AXI read data channel signals |
input [C_AXI_ID_WIDTH-1:0] i_axi_rid, // Response ID |
input [1:0] i_axi_rresp, // Read response |
input i_axi_rvalid, // Read reponse valid |
input [C_AXI_DATA_WIDTH-1:0] i_axi_rdata, // Read data |
input i_axi_rlast, // Read last |
output wire o_axi_rready, // Read Response ready |
|
// We'll share the clock and the reset |
input i_wb_cyc, |
input i_wb_stb, |
input i_wb_we, |
input [(AW-1):0] i_wb_addr, |
input [(DW-1):0] i_wb_data, |
input [(DW/8-1):0] i_wb_sel, |
output reg o_wb_ack, |
output wire o_wb_stall, |
output reg [(DW-1):0] o_wb_data, |
output reg o_wb_err, |
|
output wire [31:0] o_dbg |
); |
|
//***************************************************************************** |
// Parameter declarations |
//***************************************************************************** |
|
localparam CTL_SIG_WIDTH = 3; // Control signal width |
localparam RD_STS_WIDTH = 16; // Read status signal width |
localparam WR_STS_WIDTH = 16; // Write status signal width |
|
//***************************************************************************** |
// Internal register and wire declarations |
//***************************************************************************** |
|
// Things we're not changing ... |
assign o_axi_awlen = 8'h0; // Burst length is one |
assign o_axi_awsize = 3'b101; // maximum bytes per burst is 32 |
assign o_axi_awburst = 2'b01; // Incrementing address (ignored) |
assign o_axi_arburst = 2'b01; // Incrementing address (ignored) |
assign o_axi_awlock = 1'b0; // Normal signaling |
assign o_axi_arlock = 1'b0; // Normal signaling |
assign o_axi_awcache = 4'h2; // Normal: no cache, no buffer |
assign o_axi_arcache = 4'h2; // Normal: no cache, no buffer |
assign o_axi_awprot = 3'b010; // Unpriviledged, unsecure, data access |
assign o_axi_arprot = 3'b010; // Unpriviledged, unsecure, data access |
assign o_axi_awqos = 4'h0; // Lowest quality of service (unused) |
assign o_axi_arqos = 4'h0; // Lowest quality of service (unused) |
|
// Command logic |
// Write address logic |
|
always @(posedge i_clk) |
o_axi_awvalid <= (!o_wb_stall)&&(i_wb_stb)&&(i_wb_we) |
||(o_wb_stall)&&(o_axi_awvalid)&&(!i_axi_awready); |
|
generate |
if (DW == 32) |
begin |
always @(posedge i_clk) |
if (!o_wb_stall) // 26 bit address becomes 28 bit ... |
o_axi_awaddr <= { i_wb_addr[AW-1:2], 4'b00 }; |
end else if (DW == 128) |
begin |
always @(posedge i_clk) |
if (!o_wb_stall) // 28 bit address ... |
o_axi_awaddr <= { i_wb_addr[AW-1:0], 4'b00 }; |
end endgenerate |
|
reg [5:0] transaction_id; |
always @(posedge i_clk) |
if (!i_wb_cyc) |
transaction_id <= 6'h00; |
else if ((i_wb_stb)&&(~o_wb_stall)) |
transaction_id <= transaction_id + 6'h01; |
always @(posedge i_clk) |
if ((i_wb_stb)&&(~o_wb_stall)) |
o_axi_awid <= transaction_id; |
|
// Read address logic |
assign o_axi_arid = o_axi_awid; |
assign o_axi_araddr = o_axi_awaddr; |
assign o_axi_arlen = o_axi_awlen; |
assign o_axi_arsize = 3'b101; // maximum bytes per burst is 32 |
always @(posedge i_clk) |
o_axi_arvalid <= (!o_wb_stall)&&(i_wb_stb)&&(!i_wb_we) |
||(o_wb_stall)&&(o_axi_arvalid)&&(!i_axi_arready); |
|
|
// Write data logic |
generate |
if (DW == 32) |
begin |
always @(posedge i_clk) |
if (!o_wb_stall) |
o_axi_wdata <= { i_wb_data, i_wb_data, i_wb_data, i_wb_data }; |
always @(posedge i_clk) |
if (!o_wb_stall) |
case(i_wb_addr[1:0]) |
2'b00:o_axi_wstrb<={ 4'h0, 4'h0, 4'h0,i_wb_sel}; |
2'b01:o_axi_wstrb<={ 4'h0, 4'h0,i_wb_sel, 4'h0}; |
2'b10:o_axi_wstrb<={ 4'h0,i_wb_sel, 4'h0, 4'h0}; |
2'b11:o_axi_wstrb<={i_wb_sel, 4'h0, 4'h0, 4'h0}; |
endcase |
end else if (DW == 128) |
begin |
always @(posedge i_clk) |
if (!o_wb_stall) |
o_axi_wdata <= i_wb_data; |
always @(posedge i_clk) |
if (!o_wb_stall) |
o_axi_wstrb <= i_wb_sel; |
end endgenerate |
|
assign o_axi_wlast = 1'b1; |
always @(posedge i_clk) |
o_axi_wvalid <= ((!o_wb_stall)&&(i_wb_stb)&&(i_wb_we)) |
||(o_wb_stall)&&(o_axi_wvalid)&&(!i_axi_wready); |
|
// Read data channel / response logic |
assign o_axi_rready = 1'b1; |
assign o_axi_bready = 1'b1; |
|
wire w_fifo_full; |
generate |
if (STRICT_ORDER == 0) |
begin |
// Reorder FIFO |
// |
localparam LGFIFOLN = C_AXI_ID_WIDTH; |
localparam FIFOLN = (1<<LGFIFOLN); |
// FIFO reorder buffer |
reg [(LGFIFOLN-1):0] fifo_tail; |
reg [(C_AXI_DATA_WIDTH-1):0] reorder_fifo_data [0:(FIFOLN-1)]; |
reg [(FIFOLN-1):0] reorder_fifo_valid; |
reg [(FIFOLN-1):0] reorder_fifo_err; |
|
initial reorder_fifo_valid = 0; |
initial reorder_fifo_err = 0; |
|
if (DW == 32) |
begin |
reg [1:0] reorder_fifo_addr [0:(FIFOLN-1)]; |
|
|
reg [1:0] low_addr; |
always @(posedge i_clk) |
if ((i_wb_stb)&&(!o_wb_stall)) |
low_addr <= i_wb_addr[1:0]; |
always @(posedge i_clk) |
if ((o_axi_arvalid)&&(i_axi_arready)) |
reorder_fifo_addr[o_axi_arid] <= low_addr; |
|
always @(posedge i_clk) |
case(reorder_fifo_addr[fifo_tail][1:0]) |
2'b00: o_wb_data <=reorder_fifo_data[fifo_tail][ 31: 0]; |
2'b01: o_wb_data <=reorder_fifo_data[fifo_tail][ 63:32]; |
2'b10: o_wb_data <=reorder_fifo_data[fifo_tail][ 95:64]; |
2'b11: o_wb_data <=reorder_fifo_data[fifo_tail][127:96]; |
endcase |
|
end else if (DW == 128) |
begin |
always @(posedge i_clk) |
o_wb_data <= reorder_fifo_data[fifo_tail]; |
end |
|
|
wire [(LGFIFOLN-1):0] fifo_head; |
assign fifo_head = transaction_id; |
|
// Let's do some math to figure out where the FIFO head will |
// point to next, but let's also insist that it be LGFIFOLN |
// bits in size as well. This'll be part of the fifo_full |
// calculation below. |
wire [(LGFIFOLN-1):0] n_fifo_head, nn_fifo_head; |
assign n_fifo_head = fifo_head+1'b1; |
assign nn_fifo_head = { fifo_head[(LGFIFOLN-1):1]+1'b1, fifo_head[0] }; |
|
always @(posedge i_clk) |
begin |
if ((i_axi_rvalid)&&(o_axi_rready)) |
reorder_fifo_data[i_axi_rid]<= i_axi_rdata; |
if ((i_axi_rvalid)&&(o_axi_rready)) |
begin |
reorder_fifo_valid[i_axi_rid] <= 1'b1; |
reorder_fifo_err[i_axi_rid] <= i_axi_rresp[1]; |
end |
if ((i_axi_bvalid)&&(o_axi_bready)) |
begin |
reorder_fifo_valid[i_axi_bid] <= 1'b1; |
reorder_fifo_err[i_axi_bid] <= i_axi_bresp[1]; |
end |
|
if (reorder_fifo_valid[fifo_tail]) |
begin |
o_wb_ack <= 1'b1; |
o_wb_err <= reorder_fifo_err[fifo_tail]; |
fifo_tail <= fifo_tail + 6'h1; |
reorder_fifo_valid[fifo_tail] <= 1'b0; |
reorder_fifo_err[fifo_tail] <= 1'b0; |
end else begin |
o_wb_ack <= 1'b0; |
o_wb_err <= 1'b0; |
end |
|
if (!i_wb_cyc) |
begin |
reorder_fifo_valid <= {(FIFOLN){1'b0}}; |
reorder_fifo_err <= {(FIFOLN){1'b0}}; |
fifo_tail <= 6'h0; |
o_wb_err <= 1'b0; |
o_wb_ack <= 1'b0; |
end |
end |
|
assign o_dbg = { |
i_wb_stb, o_wb_stall, o_wb_ack, o_wb_err, |
fifo_head, fifo_tail, // 12 bits |
{ ((i_axi_rvalid)&&(o_axi_rready)) ? i_axi_rid |
: ((i_axi_bvalid)&&(o_axi_bready)) ? i_axi_bid |
: 6'hf }, // 6 bits |
o_axi_arvalid, i_axi_arready, |
o_axi_awvalid, i_axi_awready, |
o_axi_wvalid, i_axi_wready, // 28 bits so far ... |
i_axi_rvalid, i_axi_bvalid, 2'b00 |
}; |
|
|
reg r_fifo_full; |
always @(posedge i_clk) |
begin |
if (!i_wb_cyc) |
r_fifo_full <= 1'b0; |
else if ((i_wb_stb)&&(~o_wb_stall) |
&&(reorder_fifo_valid[fifo_tail])) |
r_fifo_full <= (fifo_tail==n_fifo_head); |
else if ((i_wb_stb)&&(~o_wb_stall)) |
r_fifo_full <= (fifo_tail==nn_fifo_head); |
else if (reorder_fifo_valid[fifo_tail]) |
r_fifo_full <= 1'b0; |
else |
r_fifo_full <= (fifo_tail==n_fifo_head); |
end |
assign w_fifo_full = r_fifo_full; |
end else begin |
// |
// Strict ordering, but can only read every fourth addresses |
// |
assign w_fifo_full = 1'b0; |
always @(posedge i_clk) |
o_wb_data <= i_axi_rdata[31:0]; |
always @(posedge i_clk) |
o_wb_ack <= (i_wb_cyc)&&( |
((i_axi_rvalid)&&(o_axi_rready)) |
||((i_axi_bvalid)&&(o_axi_bready))); |
always @(posedge i_clk) |
o_wb_err <= (i_wb_cyc)&&((o_wb_err) |
||((i_axi_rvalid)&&(i_axi_rresp[1])) |
||((i_axi_bvalid)&&(i_axi_bresp[1]))); |
|
assign o_dbg = { |
i_wb_stb, o_wb_stall, o_wb_ack, o_wb_err, |
12'h00, // 12 bits |
{ ((i_axi_rvalid)&&(o_axi_rready)) ? i_axi_rid |
: ((i_axi_bvalid)&&(o_axi_bready)) ? i_axi_bid |
: 6'hf }, // 6 bits |
o_axi_arvalid, i_axi_arready, |
o_axi_awvalid, i_axi_awready, |
o_axi_wvalid, i_axi_wready, // 28 bits so far ... |
i_axi_rvalid, i_axi_bvalid, 2'b00 |
}; |
end endgenerate |
|
|
// Now, the difficult signal ... the stall signal |
// Let's build for a single cycle input ... and only stall if something |
// outgoing is valid and nothing is ready. |
assign o_wb_stall = (i_wb_cyc)&&( |
(w_fifo_full) |
||((o_axi_awvalid)&&(!i_axi_awready)) |
||((o_axi_wvalid )&&(!i_axi_wready )) |
||((o_axi_arvalid)&&(!i_axi_arready))); |
endmodule |
|
/openarty/trunk/rtl/fasttop.v
110,37 → 110,20
|
`define FULLCLOCK |
// Build our master clock |
wire i_clk, clk_for_ddr, mem_serial_clk, mem_serial_clk_inv, |
wire s_clk_pll, s_clk, clk_for_ddr, mem_serial_clk, mem_serial_clk_inv, |
enet_clk, clk_halfspeed, clk_feedback, clk_locked, clk_unused; |
PLLE2_BASE #( |
.BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW |
.CLKFBOUT_PHASE(0.0), // Phase off. in deg of CLKFB,(-360-360) |
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360-360) |
.CLKIN1_PERIOD(10.0), // Input clock period in ns resolution |
`ifdef FULLCLOCK |
// CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: |
// divide amount for each CLKOUT(1-128) |
// CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: divide amount for each CLKOUT(1-128) |
.CLKFBOUT_MULT(8), // Multiply value for all CLKOUT (2-64) |
.CLKOUT0_DIVIDE(4), // 200 MHz |
.CLKOUT1_DIVIDE(1), // 800 MHz clock for DDR memory |
.CLKOUT2_DIVIDE(1), // 800 MHz clock to run DDR I/O |
.CLKOUT3_DIVIDE(1), // 800MHz clk inv to run DDR I/O |
.CLKOUT4_DIVIDE(8), // 100 MHz |
.CLKOUT5_DIVIDE(32), // 25 MHz |
`else |
// 100*64/40 = 160 -- the fastest speed where the UART will |
// still work at 4MBaud. Others will still support 115200 |
// Baud |
// 100*64/36 = 177.78 |
// 100*64/34 = 188.24 |
// 100*64/33 = 193.94 |
.CLKFBOUT_MULT(8), // Multiply value for all CLKOUT (2-64) |
.CLKOUT0_DIVIDE(5), // 160 MHz |
.CLKOUT1_DIVIDE(5), // 160 MHz //Clock too slow for DDR mem |
.CLKOUT2_DIVIDE(5), // 160 MHz // Clock too slow for DDR |
.CLKOUT3_DIVIDE(5), // 160 MHz // Clock too slow for DDR |
.CLKOUT4_DIVIDE(20), // 40 MHz |
.CLKOUT5_DIVIDE(5), |
`endif |
.CLKOUT1_DIVIDE(10), // 80 MHz (Unused) |
.CLKOUT2_DIVIDE(16), // 50 MHz (Unused) |
.CLKOUT3_DIVIDE(32), // 25 MHz (Unused/Ethernet clock) |
.CLKOUT4_DIVIDE(16), // 50 MHz (Unused clock?) |
.CLKOUT5_DIVIDE(24), |
// CLKOUT0_DUTY_CYCLE -- Duty cycle for each CLKOUT |
.CLKOUT0_DUTY_CYCLE(0.5), |
.CLKOUT1_DUTY_CYCLE(0.5), |
150,9 → 133,9
.CLKOUT5_DUTY_CYCLE(0.5), |
// CLKOUT0_PHASE -- phase offset for each CLKOUT |
.CLKOUT0_PHASE(0.0), |
.CLKOUT1_PHASE(270.0), |
.CLKOUT1_PHASE(0.0), |
.CLKOUT2_PHASE(0.0), |
.CLKOUT3_PHASE(180.0), |
.CLKOUT3_PHASE(0.0), |
.CLKOUT4_PHASE(0.0), |
.CLKOUT5_PHASE(0.0), |
.DIVCLK_DIVIDE(1), // Master division value , (1-56) |
160,28 → 143,27
.STARTUP_WAIT("TRUE") // Delay DONE until PLL Locks, ("TRUE"/"FALSE") |
) genclock( |
// Clock outputs: 1-bit (each) output |
.CLKOUT0(i_clk), |
.CLKOUT1(clk_for_ddr), |
.CLKOUT2(mem_serial_clk), |
.CLKOUT3(mem_serial_clk_inv), |
.CLKOUT4(clk_unused), |
.CLKOUT5(enet_clk), |
.CLKOUT0(s_clk_pll), |
.CLKOUT1(mem_clk), |
.CLKOUT2(clk2_unused), |
.CLKOUT3(enet_clk), |
.CLKOUT4(clk4_unused), |
.CLKOUT5(clk5_unused), |
.CLKFBOUT(clk_feedback), // 1-bit output, feedback clock |
.LOCKED(clk_locked), |
.CLKIN1(i_clk_100mhz), |
.PWRDWN(1'b0), |
.RST(1'b0), |
.CLKFBIN(clk_feedback) // 1-bit input, feedback clock |
.CLKFBIN(clk_feedback_bufd) // 1-bit input, feedback clock |
); |
|
|
// Help reduce skew ... |
BUFG sys_clk_buffer( .I(s_clk_pll), .O(s_clk)); |
BUFG feedback_buffer(.I(clk_feedback),.O(clk_feedback_bufd)); |
|
// UART interface |
wire [29:0] bus_uart_setup; |
`ifdef FULLCLOCK |
assign bus_uart_setup = 30'h10000032; // 4MBaud, 7 bits |
`else |
assign bus_uart_setup = 30'h10000028;//4MBaud,7 bits,@160MHzClk |
//assign bus_uart_setup = 30'h10000019;//4MBaud,7 bits,@100MHzClk |
`endif |
assign bus_uart_setup = 30'h10000028; // 4MBaud, 7 bits |
|
wire [7:0] rx_data, tx_data; |
wire rx_break, rx_parity_err, rx_frame_err, rx_stb; |
202,20 → 184,20
// Logic description starts with the PRE-reset, so as to make certain |
// we include the reset button |
initial pre_reset = 1'b0; |
always @(posedge i_clk) |
always @(posedge s_clk) |
pre_reset <= ~i_reset_btn; |
// |
// and then continues with the actual reset, now that we've |
// synchronized our reset button wire. |
initial pwr_reset = 1'b1; |
always @(posedge i_clk) |
always @(posedge s_clk) |
pwr_reset <= pre_reset; |
|
wire w_ck_uart, w_uart_tx; |
rxuart rcv(i_clk, pwr_reset, bus_uart_setup, i_uart_rx, |
rxuart rcv(s_clk, pwr_reset, bus_uart_setup, i_uart_rx, |
rx_stb, rx_data, rx_break, |
rx_parity_err, rx_frame_err, w_ck_uart); |
txuart txv(i_clk, pwr_reset, bus_uart_setup, 1'b0, |
txuart txv(s_clk, pwr_reset, bus_uart_setup, 1'b0, |
tx_stb, tx_data, o_uart_tx, tx_busy); |
|
|
402,11 → 384,14
wire [3:0] i_qspi_dat; |
|
// |
wire [2:0] w_ddr_dqs; |
wire [31:0] wo_ddr_data, wi_ddr_data; |
// |
wire w_mdio, w_mdwe; |
// |
wire w_sd_cmd; |
wire [3:0] w_sd_data; |
fastmaster wbbus(i_clk, pwr_reset, |
fastmaster wbbus(s_clk, pwr_reset, |
// External USB-UART bus control |
rx_stb, rx_data, tx_stb, tx_data, tx_busy, |
// Board lights and switches |
450,34 → 435,36
// ?? Dual mode out (not yet) |
// |
// |
// `define QSPI_OUT_VERSION_ONE |
`ifdef QSPI_OUT_VERSION_ONE |
assign io_qspi_dat = (~qspi_bmod[1])?({2'b11,1'bz,qspi_dat[0]}) |
:((qspi_bmod[0])?(4'bzzzz):(qspi_dat[3:0])); |
assign i_qspi_dat = io_qspi_dat; |
assign o_qspi_sck = w_qspi_sck; |
`else |
wire [3:0] i_qspi_pedge, i_qspi_nedge; |
|
xoddr xqspi_sck( i_clk, { w_qspi_sck, w_qspi_sck }, o_qspi_sck); |
xoddr xqspi_csn( i_clk, { w_qspi_cs_n, w_qspi_cs_n },o_qspi_cs_n); |
// |
xioddr xqspi_d0( i_clk, (qspi_bmod != 2'b11), |
xioddr xqspi_d0( s_clk, (qspi_bmod != 2'b11), |
{ qspi_dat[0], qspi_dat[0] }, |
{ i_qspi_pedge[0], i_qspi_nedge[0] }, io_qspi_dat[0]); |
xioddr xqspi_d1( i_clk, (qspi_bmod==2'b10), |
xioddr xqspi_d1( s_clk, (qspi_bmod==2'b10), |
{ qspi_dat[1], qspi_dat[1] }, |
{ i_qspi_pedge[1], i_qspi_nedge[1] }, io_qspi_dat[1]); |
xioddr xqspi_d2( i_clk, (qspi_bmod!=2'b11), |
xioddr xqspi_d2( s_clk, (qspi_bmod!=2'b11), |
(qspi_bmod[1])?{ qspi_dat[2], qspi_dat[2] }:2'b11, |
{ i_qspi_pedge[2], i_qspi_nedge[2] }, io_qspi_dat[2]); |
xioddr xqspi_d3( i_clk, (qspi_bmod!=2'b11), |
xioddr xqspi_d3( s_clk, (qspi_bmod!=2'b11), |
(qspi_bmod[1])?{ qspi_dat[3], qspi_dat[3] }:2'b11, |
{ i_qspi_pedge[3], i_qspi_nedge[3] }, io_qspi_dat[3]); |
|
assign i_qspi_dat = i_qspi_pedge; |
`endif |
// |
// Proposed QSPI mode select, to allow dual I/O mode |
// 000 Normal SPI mode |
// 001 Dual mode input |
// 010 Dual mode, output |
// 101 Quad I/O mode input |
// 110 Quad I/O mode output |
// |
// |
|
|
// |
// |
// Wires for setting up the SD Card Controller |
/openarty/trunk/rtl/fastio.v
50,7 → 50,8
// Cross-board I/O |
i_rtc_ppd, i_buserr, i_other_ints, o_bus_int, o_board_ints); |
parameter AUXUART_SETUP = 30'd1736, // 115200 baud from 200MHz clk |
GPSUART_SETUP = 30'd20833; // 9600 baud from 200MHz clk |
GPSUART_SETUP = 30'd20833, // 9600 baud from 200MHz clk |
EXTRACLOCK = 1; // Do we need an extra clock to process? |
input i_clk; |
// Board level I/O |
input [3:0] i_sw; |
94,17 → 95,33
output wire o_bus_int; |
output wire [5:0] o_board_ints; // Button and switch interrupts |
|
reg last_wb_stb; |
reg [4:0] last_wb_addr; |
reg [31:0] last_wb_data; |
initial last_wb_stb = 1'b0; |
always @(posedge i_clk) |
wire [31:0] w_wb_data; |
wire [4:0] w_wb_addr; |
wire w_wb_stb; |
|
generate |
if (EXTRACLOCK == 0) |
begin |
last_wb_addr <= i_wb_addr; |
last_wb_data <= i_wb_data; |
last_wb_stb <= (i_wb_stb)&&(i_wb_we); |
end |
assign w_wb_data = i_wb_data; |
assign w_wb_addr = i_wb_addr; |
assign w_wb_stb = (i_wb_stb)&&(i_wb_we); |
end else begin |
reg last_wb_stb; |
reg [4:0] last_wb_addr; |
reg [31:0] last_wb_data; |
initial last_wb_stb = 1'b0; |
always @(posedge i_clk) |
begin |
last_wb_addr <= i_wb_addr; |
last_wb_data <= i_wb_data; |
last_wb_stb <= (i_wb_stb)&&(i_wb_we); |
end |
|
assign w_wb_data = last_wb_data; |
assign w_wb_addr = last_wb_addr; |
assign w_wb_stb = last_wb_stb; |
end endgenerate |
|
wire [31:0] pic_data; |
reg sw_int, btn_int; |
wire pps_int, rtc_int, netrx_int, nettx_int, |
118,7 → 135,7
// The BUS Interrupt controller |
// |
icontrol #(15) buspic(i_clk, 1'b0, |
(last_wb_stb)&&(last_wb_addr==5'h1), |
(w_wb_stb)&&(w_wb_addr==5'h1), |
i_wb_data, pic_data, |
{ zip_int, oled_int, sd_int, |
gpsrx_int, scop_int, flash_int, gpio_int, |
152,18 → 169,18
swlast<= swnow; |
sw_int <= |((swnow^swlast)|swcfg); |
|
if ((last_wb_stb)&&(last_wb_addr == 5'h4)) |
swcfg <= ((last_wb_data[3:0])&(last_wb_data[11:8])) |
|((~last_wb_data[3:0])&(swcfg)); |
if ((w_wb_stb)&&(w_wb_addr == 5'h4)) |
swcfg <= ((w_wb_data[3:0])&(w_wb_data[11:8])) |
|((~w_wb_data[3:0])&(swcfg)); |
|
r_btn <= i_btn; |
btnnow <= r_btn; |
btn_int <= |(btnnow&btncfg); |
if ((last_wb_stb)&&(last_wb_addr == 5'h4)) |
if ((w_wb_stb)&&(w_wb_addr == 5'h4)) |
begin |
btncfg <= ((last_wb_data[7:4])&(last_wb_data[15:12])) |
|((~last_wb_data[7:4])&(btncfg)); |
btnstate<= (btnnow)|((btnstate)&(~last_wb_data[7:4])); |
btncfg <= ((w_wb_data[7:4])&(w_wb_data[15:12])) |
|((~w_wb_data[7:4])&(btncfg)); |
btnstate<= (btnnow)|((btnstate)&(~w_wb_data[7:4])); |
end else |
btnstate <= (btnstate)|(btnnow); |
end |
174,14 → 191,11
// |
reg [3:0] r_leds; |
wire [31:0] w_ledreg; |
reg last_cyc; |
always @(posedge i_clk) |
last_cyc <= i_wb_cyc; |
initial r_leds = 4'h0; |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'h5)) |
r_leds <= ((last_wb_data[7:4])&(last_wb_data[3:0])) |
|((~last_wb_data[7:4])&(r_leds)); |
if ((w_wb_stb)&&(w_wb_addr == 5'h5)) |
r_leds <= ((w_wb_data[7:4])&(w_wb_data[3:0])) |
|((~w_wb_data[7:4])&(r_leds)); |
assign o_led = r_leds; |
assign w_ledreg = { 28'h0, r_leds }; |
|
202,8 → 216,8
reg [29:0] aux_setup; |
initial aux_setup = AUXUART_SETUP; |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'h6)) |
aux_setup[29:0] <= last_wb_data[29:0]; |
if ((w_wb_stb)&&(w_wb_addr == 5'h6)) |
aux_setup[29:0] <= w_wb_data[29:0]; |
|
// |
// GPSSETUP |
212,8 → 226,8
reg [29:0] gps_setup; |
initial gps_setup = GPSUART_SETUP; |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'h7)) |
gps_setup[29:0] <= last_wb_data[29:0]; |
if ((w_wb_stb)&&(w_wb_addr == 5'h7)) |
gps_setup[29:0] <= w_wb_data[29:0]; |
|
// |
// CLR LEDs |
226,11 → 240,11
initial r_clr_led0_g = 9'h000; |
initial r_clr_led0_b = 9'h000; |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'h8)) |
if ((w_wb_stb)&&(w_wb_addr == 5'h8)) |
begin |
r_clr_led0_r <= { last_wb_data[26], last_wb_data[23:16] }; |
r_clr_led0_g <= { last_wb_data[25], last_wb_data[15: 8] }; |
r_clr_led0_b <= { last_wb_data[24], last_wb_data[ 7: 0] }; |
r_clr_led0_r <= { w_wb_data[26], w_wb_data[23:16] }; |
r_clr_led0_g <= { w_wb_data[25], w_wb_data[15: 8] }; |
r_clr_led0_b <= { w_wb_data[24], w_wb_data[ 7: 0] }; |
end |
assign w_clr_led0 = { 5'h0, |
r_clr_led0_r[8], r_clr_led0_g[8], r_clr_led0_b[8], |
248,11 → 262,11
initial r_clr_led1_g = 9'h000; |
initial r_clr_led1_b = 9'h000; |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'h9)) |
if ((w_wb_stb)&&(w_wb_addr == 5'h9)) |
begin |
r_clr_led1_r <= { last_wb_data[26], last_wb_data[23:16] }; |
r_clr_led1_g <= { last_wb_data[25], last_wb_data[15: 8] }; |
r_clr_led1_b <= { last_wb_data[24], last_wb_data[ 7: 0] }; |
r_clr_led1_r <= { w_wb_data[26], w_wb_data[23:16] }; |
r_clr_led1_g <= { w_wb_data[25], w_wb_data[15: 8] }; |
r_clr_led1_b <= { w_wb_data[24], w_wb_data[ 7: 0] }; |
end |
assign w_clr_led1 = { 5'h0, |
r_clr_led1_r[8], r_clr_led1_g[8], r_clr_led1_b[8], |
269,11 → 283,11
initial r_clr_led2_g = 9'h000; |
initial r_clr_led2_b = 9'h000; |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'ha)) |
if ((w_wb_stb)&&(w_wb_addr == 5'ha)) |
begin |
r_clr_led2_r <= { last_wb_data[26], last_wb_data[23:16] }; |
r_clr_led2_g <= { last_wb_data[25], last_wb_data[15: 8] }; |
r_clr_led2_b <= { last_wb_data[24], last_wb_data[ 7: 0] }; |
r_clr_led2_r <= { w_wb_data[26], w_wb_data[23:16] }; |
r_clr_led2_g <= { w_wb_data[25], w_wb_data[15: 8] }; |
r_clr_led2_b <= { w_wb_data[24], w_wb_data[ 7: 0] }; |
end |
assign w_clr_led2 = { 5'h0, |
r_clr_led2_r[8], r_clr_led2_g[8], r_clr_led2_b[8], |
290,11 → 304,11
initial r_clr_led3_g = 9'h000; |
initial r_clr_led3_b = 9'h000; |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'hb)) |
if ((w_wb_stb)&&(w_wb_addr == 5'hb)) |
begin |
r_clr_led3_r <= { last_wb_data[26], last_wb_data[23:16] }; |
r_clr_led3_g <= { last_wb_data[25], last_wb_data[15: 8] }; |
r_clr_led3_b <= { last_wb_data[24], last_wb_data[ 7: 0] }; |
r_clr_led3_r <= { w_wb_data[26], w_wb_data[23:16] }; |
r_clr_led3_g <= { w_wb_data[25], w_wb_data[15: 8] }; |
r_clr_led3_b <= { w_wb_data[24], w_wb_data[ 7: 0] }; |
end |
assign w_clr_led3 = { 5'h0, |
r_clr_led3_r[8], r_clr_led3_g[8], r_clr_led3_b[8], |
313,7 → 327,7
`ifdef GET_DATE |
wire date_ack, date_stall; |
rtcdate thedate(i_clk, i_rtc_ppd, |
i_wb_cyc, last_wb_stb, (last_wb_addr==5'hc), last_wb_data, |
i_wb_cyc, w_wb_stb, (w_wb_addr==5'hc), w_wb_data, |
date_ack, date_stall, date_data); |
`else |
assign date_data = 32'h20160000; |
346,7 → 360,7
end |
always @(posedge i_clk) |
if(((i_wb_stb)&&(~i_wb_we)&&(i_wb_addr == 5'h0e))||(auxrx_stb)) |
r_auxrx_data[8] <= auxrx_stb; |
r_auxrx_data[8] <= !auxrx_stb; |
assign o_aux_cts = auxrx_stb; |
assign auxrx_data = { 20'h00, r_auxrx_data }; |
assign auxrx_int = r_auxrx_data[8]; |
362,11 → 376,11
r_auxtx_break, r_auxtx_stb, r_auxtx_data, |
o_aux_tx, auxtx_busy); |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'h0f)) |
if ((w_wb_stb)&&(w_wb_addr == 5'h0f)) |
begin |
r_auxtx_stb <= 1'b1; |
r_auxtx_data <= last_wb_data[7:0]; |
r_auxtx_break<= last_wb_data[9]; |
r_auxtx_stb <= (!r_auxtx_break)&&(!w_wb_data[9]); |
r_auxtx_data <= w_wb_data[7:0]; |
r_auxtx_break<= w_wb_data[9]; |
end else if (~auxtx_busy) |
begin |
r_auxtx_stb <= 1'b0; |
416,11 → 430,11
r_gpstx_break, r_gpstx_stb, r_gpstx_data, |
o_gps_tx, gpstx_busy); |
always @(posedge i_clk) |
if ((last_wb_stb)&&(last_wb_addr == 5'h11)) |
if ((w_wb_stb)&&(w_wb_addr == 5'h11)) |
begin |
r_gpstx_stb <= 1'b1; |
r_gpstx_data <= last_wb_data[7:0]; |
r_gpstx_break<= last_wb_data[9]; |
r_gpstx_data <= w_wb_data[7:0]; |
r_gpstx_break<= w_wb_data[9]; |
end else if (~gpstx_busy) |
begin |
r_gpstx_stb <= 1'b0; |
/openarty/trunk/rtl/txuart.v
167,6 → 167,7
// baud_counter <= 0; |
r_setup <= i_setup; |
calc_parity <= 1'b0; |
lcl_data <= i_data; |
if ((i_wr)&&(~r_busy)) |
begin // Immediately start us off with a start bit |
o_uart <= 1'b0; |
177,12 → 178,10
2'b10: state <= `TXU_BIT_TWO; |
2'b11: state <= `TXU_BIT_THREE; |
endcase |
lcl_data <= i_data; |
// baud_counter <= clocks_per_baud-28'h01; |
end else begin // Stay in idle |
o_uart <= 1'b1; |
r_busy <= 0; |
// lcl_data is irrelevant |
// state <= state; |
end |
end else begin |
227,7 → 226,8
assign o_busy = (r_busy); |
|
|
initial zero_baud_counter = 1'b0; |
initial zero_baud_counter = 1'b1; |
initial baud_counter = 28'd200000; // 1ms @ 200MHz |
always @(posedge i_clk) |
begin |
zero_baud_counter <= (baud_counter == 28'h01); |
/openarty/trunk/rtl/builddate.v
38,4 → 38,4
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
`define DATESTAMP 32'h20160811 |
`define DATESTAMP 32'h20160909 |
/openarty/trunk/rtl/wbscope.v
101,17 → 101,6
// being stopped. It is not maskable here. |
output wire o_interrupt; |
|
// For timing's sake, let's remove ourselves from the bus a touch |
reg r_wb_stb, r_wb_addr, r_wb_we; |
reg [31:0] r_wb_data; |
always @(posedge i_clk) |
begin |
r_wb_stb <= i_wb_stb; |
r_wb_we <= i_wb_we; |
r_wb_addr<= i_wb_addr; |
r_wb_data<= i_wb_data; |
end |
|
reg [(LGMEM-1):0] raddr; |
reg [(BUSW-1):0] mem[0:((1<<LGMEM)-1)]; |
|
122,13 → 111,13
wire [19:0] bw_holdoff; |
initial br_config = ((1<<(LGMEM-1))-4); |
always @(posedge i_wb_clk) |
if ((r_wb_stb)&&(~r_wb_addr)) |
if ((i_wb_cyc)&&(i_wb_stb)&&(~i_wb_addr)) |
begin |
if (r_wb_we) |
br_config <= { r_wb_data[31], |
(r_wb_data[27]), |
r_wb_data[26], |
r_wb_data[19:0] }; |
if (i_wb_we) |
br_config <= { i_wb_data[31], |
(i_wb_data[27]), |
i_wb_data[26], |
i_wb_data[19:0] }; |
end else if (bw_reset_complete) |
br_config[22] <= 1'b1; |
assign bw_reset_request = (~br_config[22]); |
200,14 → 189,11
// Determine when memory is full and capture is complete |
// |
// Writes take place on the data clock |
reg dr_stopped, dr_past_holdoff; |
reg dr_stopped; |
reg [19:0] counter; // This is unsigned |
initial dr_stopped = 1'b0; |
initial counter = 20'h0000; |
initial dr_past_holdoff = 1'b0; |
always @(posedge i_clk) |
dr_past_holdoff <= (counter >= bw_holdoff); |
always @(posedge i_clk) |
if (dw_reset) |
begin |
counter <= 0; |
216,9 → 202,10
begin // MUST BE a < and not <=, so that we can keep this w/in |
// 20 bits. Else we'd need to add a bit to comparison |
// here. |
if (~dr_stopped) |
if (counter < bw_holdoff) |
counter <= counter + 20'h01; |
dr_stopped <= (dr_stopped)||(dr_past_holdoff); |
else |
dr_stopped <= 1'b1; |
end |
|
// |
239,7 → 226,7
begin |
waddr <= 0; // upon reset. |
dr_primed <= 1'b0; |
end else if ((i_ce)&&(~dr_stopped)) |
end else if ((i_ce)&&((~dr_triggered)||(counter < bw_holdoff))) |
begin |
// mem[waddr] <= i_data; |
waddr <= waddr + {{(LGMEM-1){1'b0}},1'b1}; |
246,7 → 233,7
dr_primed <= (dr_primed)||(&waddr); |
end |
always @(posedge i_clk) |
if ((i_ce)&&(~dr_stopped)) |
if ((i_ce)&&((~dr_triggered)||(counter < bw_holdoff))) |
mem[waddr] <= i_data; |
|
// |
284,50 → 271,38
end endgenerate |
|
// Reads use the bus clock |
reg br_wb_ack, r_wb_ack, s_wb_ack; // takes two clock to read |
reg s_wb_addr, q_wb_addr; |
reg bw_cyc_stb, bus_read_fifo, bus_write_fifo; |
always @(posedge i_clk) |
bw_cyc_stb = (r_wb_stb); |
always @(posedge i_clk) |
bus_read_fifo <= (r_wb_stb)&&(r_wb_addr)&&(~r_wb_we); |
always @(posedge i_clk) |
bus_write_fifo <= (r_wb_stb)&&(r_wb_addr)&&(r_wb_we); |
reg br_wb_ack; |
initial br_wb_ack = 1'b0; |
wire bw_cyc_stb; |
assign bw_cyc_stb = ((i_wb_cyc)&&(i_wb_stb)); |
always @(posedge i_wb_clk) |
begin // CE depends upon 5 inputs, output on 7 (ignoring add&carries) |
if ((bw_reset_request)||(bus_write_fifo)) |
begin |
if ((bw_reset_request) |
||((bw_cyc_stb)&&(i_wb_addr)&&(i_wb_we))) |
raddr <= 0; |
else if ((bus_read_fifo)&&(bw_stopped)) |
else if ((bw_cyc_stb)&&(i_wb_addr)&&(~i_wb_we)&&(bw_stopped)) |
raddr <= raddr + {{(LGMEM-1){1'b0}},1'b1}; // Data read, when stopped |
|
r_wb_ack <= r_wb_stb; |
s_wb_ack <= r_wb_ack; |
br_wb_ack <= s_wb_ack; |
if ((bw_cyc_stb)&&(~i_wb_we)) |
begin // Read from the bus |
br_wb_ack <= 1'b1; |
end else if ((bw_cyc_stb)&&(i_wb_we)) |
// We did this write above |
br_wb_ack <= 1'b1; |
else // Do nothing if either i_wb_cyc or i_wb_stb are low |
br_wb_ack <= 1'b0; |
end |
|
reg [(LGMEM-1):0] nxt_addr; |
always @(posedge i_wb_clk) // 2 adds, then 5 inputs |
if (bus_read_fifo) |
nxt_addr <= nxt_addr + {{(LGMEM-1){1'b0}},1'b1}; |
else |
nxt_addr <= raddr + waddr; |
// nxt_addr <= raddr + waddr + (bus_read_fifo) |
// ? {{(LGMEM-1){1'b0}},1'b1}: 0; |
|
reg [31:0] nxt_mem; |
always @(posedge i_wb_clk) |
nxt_mem <= mem[nxt_addr]; |
nxt_mem <= mem[raddr+waddr+ |
(((bw_cyc_stb)&&(i_wb_addr)&&(~i_wb_we)) ? |
{{(LGMEM-1){1'b0}},1'b1} : { (LGMEM){1'b0}} )]; |
|
always @(posedge i_clk) |
s_wb_addr <= r_wb_addr; |
always @(posedge i_clk) |
q_wb_addr <= s_wb_addr; |
|
wire [4:0] bw_lgmem; |
assign bw_lgmem = LGMEM; |
always @(posedge i_wb_clk) |
if (~q_wb_addr) // Control register read |
if (~i_wb_addr) // Control register read |
o_wb_data <= { bw_reset_request, |
bw_stopped, |
bw_triggered, |
343,7 → 318,7
o_wb_data <= nxt_mem; // mem[raddr+waddr]; |
|
assign o_wb_stall = 1'b0; |
assign o_wb_ack = (s_wb_ack); |
assign o_wb_ack = (i_wb_cyc)&&(br_wb_ack); |
|
reg br_level_interrupt; |
initial br_level_interrupt = 1'b0; |
/openarty/trunk/rtl/wbicapetwo.v
96,6 → 96,7
module wbicapetwo(i_clk, |
i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, |
o_wb_ack, o_wb_stall, o_wb_data, o_dbg); |
parameter LGDIV = 3; /// Log of the clock divide |
input i_clk; |
// Wishbone inputs |
input i_wb_cyc, i_wb_stb, i_wb_we; |
113,38 → 114,45
reg [31:0] r_data; |
reg [4:0] r_addr; |
|
`ifdef DIVIDE_BY_FOUR |
reg [1:0] slow_clk_counter; |
|
reg clk_stb, clk_stall; |
wire slow_clk; |
always @(posedge i_clk) |
begin |
slow_clk <= slow_clk + 2'b01; |
// We'll move on the positive edge of the clock, so therefore |
// clk_stb must be true one clock before that, so we test for |
// it one clock before that. |
clk_stb <= (slow_clk_counter == 2'b10); |
// CLK_STALL is set to true two clocks before any cycle that |
// will, by necessity, stall. |
clk_stall <= (slow_clk_counter != 2'b01); |
end |
|
assign slow_clk = slow_clk_counter[1]; |
`else |
reg slow_clk, clk_stb, clk_stall; |
always @(posedge i_clk) |
generate |
if (LGDIV <= 1) |
begin |
slow_clk <= (slow_clk + 1'b1); |
// We'll move on the positive edge of the clock, so therefore |
// clk_stb must be true one clock before that, so we test for |
// it one clock before that. |
clk_stb <= (slow_clk == 1'b1); |
// CLK_STALL is set to true two clocks before any cycle that |
// will, by necessity, stall. |
clk_stall <= (slow_clk != 1'b0); //True all but one clock |
end |
`endif |
reg r_slow_clk; |
always @(posedge i_clk) |
begin |
r_slow_clk <= (slow_clk + 1'b1); |
// We'll move on the positive edge of the clock, |
// so therefore clk_stb must be true one clock before |
// that, so we test for it one clock before that. |
clk_stb <= (slow_clk == 1'b1); |
// CLK_STALL is set to true two clocks before any |
// cycle that will, by necessity, stall. |
clk_stall <= (slow_clk != 1'b0); //True all but 1ckcycle |
end |
|
assign slow_clk = r_slow_clk; |
end else begin |
reg [(LGDIV-1):0] slow_clk_counter; |
|
always @(posedge i_clk) |
begin |
slow_clk_counter <= slow_clk_counter + 1'b1; |
// We'll move on the positive edge of the clock, so therefore |
// clk_stb must be true one clock before that, so we test for |
// it one clock before that. |
clk_stb <= (slow_clk_counter=={{(LGDIV){1'b1}},1'b0}); |
// CLK_STALL is set to true two clocks before any cycle that |
// will, by necessity, stall. |
clk_stall <= (slow_clk_counter!={{(LGDIV){1'b0}},1'b1}); |
end |
|
assign slow_clk = slow_clk_counter[(LGDIV-1)]; |
end endgenerate |
|
reg [31:0] cfg_in; |
reg cfg_cs_n, cfg_rdwrn; |
wire [31:0] cfg_out; |
/openarty/trunk/rtl/busmaster.v
40,12 → 40,6
// |
`define NO_ZIP_WBU_DELAY |
`define ZIPCPU |
`ifdef ZIPCPU |
`define ZIP_SYSTEM |
`ifndef ZIP_SYSTEM |
`define ZIP_BONES |
`endif // ZIP_SYSTEM |
`endif // ZipCPU |
// |
// |
`define SDCARD_ACCESS |
54,7 → 48,7
`define ICAPE_ACCESS |
`endif |
`define FLASH_ACCESS |
//`define SDRAM_ACCESS |
`define SDRAM_ACCESS |
`define GPS_CLOCK |
// UART_ACCESS and GPS_UART have both been placed within fastio |
// `define UART_ACCESS |
62,10 → 56,43
`define RTC_ACCESS |
`define OLEDRGB_ACCESS |
// |
// `define CPU_SCOPE |
// `define GPS_SCOPE |
`define FLASH_SCOPE |
// `define SDRAM_SCOPE |
// |
// |
// |
// |
// Now, conditional compilation based upon what capabilities we have turned |
// on |
// |
`ifdef ZIPCPU |
`define ZIP_SYSTEM |
`ifndef ZIP_SYSTEM |
`define ZIP_BONES |
`endif // ZIP_SYSTEM |
`endif // ZipCPU |
// |
// |
// SCOPE POSITION ZERO |
// |
`ifdef FLASH_ACCESS |
`define FLASH_SCOPE // Position zero |
`else |
`ifdef ZIPCPU |
// `define CPU_SCOPE // Position zero |
`endif |
`endif |
// |
// SCOPE POSITION ONE |
// |
// `define GPS_SCOPE // Position one |
`ifdef ICAPE_ACCESS |
`define CFG_SCOPE // Position one |
`endif |
// |
// SCOPE POSITION TWO |
// |
`ifdef SDRAM_ACCESS |
`define SDRAM_SCOPE // Position two |
`endif |
// `define ENET_SCOPE |
// |
// |
80,9 → 107,16
// The Quad SPI Flash |
o_qspi_cs_n, o_qspi_sck, o_qspi_dat, i_qspi_dat, o_qspi_mod, |
// The DDR3 SDRAM |
o_ddr_reset_n, o_ddr_cke, |
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
o_ddr_dqs, o_ddr_addr, o_ddr_ba, o_ddr_data, i_ddr_data, |
// The actual wires need to be controlled from the device |
// dependent file. In order to keep this device independent, |
// we export only the wishbone interface to the RAM. |
// o_ddr_ck_p, o_ddr_ck_n, o_ddr_reset_n, o_ddr_cke, |
// o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
// o_ddr_ba, o_ddr_addr, o_ddr_odt, o_ddr_dm, |
// io_ddr_dqs_p, io_ddr_dqs_n, io_ddr_data, |
o_ram_cyc, o_ram_stb, o_ram_we, o_ram_addr, o_ram_wdata, |
i_ram_ack, i_ram_stall, i_ram_rdata, i_ram_err, |
i_ram_dbg, |
// The SD Card |
o_sd_sck, o_sd_cmd, o_sd_data, i_sd_cmd, i_sd_data, i_sd_detect, |
// Ethernet control (MDIO) lines |
93,8 → 127,8
// The GPS PMod |
i_gps_pps, i_gps_3df |
); |
parameter ZA=24, ZIPINTS=13; |
input i_clk, i_rst; |
parameter ZA=24, ZIPINTS=14; |
input i_clk, i_rst; |
// The bus commander, via an external uart port |
input i_rx_stb; |
input [7:0] i_rx_data; |
116,14 → 150,31
output wire [3:0] o_qspi_dat; |
input [3:0] i_qspi_dat; |
output wire [1:0] o_qspi_mod; |
// |
// DDR3 RAM controller |
output wire o_ddr_reset_n, o_ddr_cke, |
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n,o_ddr_we_n; |
output wire [2:0] o_ddr_dqs; |
output wire [13:0] o_ddr_addr; |
output wire [2:0] o_ddr_ba; |
output wire [31:0] o_ddr_data; |
input [31:0] i_ddr_data; |
// |
// These would be our RAM control lines. However, these are device, |
// implementation, and architecture dependent, rather than just simply |
// logic dependent. Therefore, this interface as it exists cannot |
// exist here. Instead, we export a device independent wishbone to |
// the RAM rather than the RAM wires themselves. |
// |
// output wire o_ddr_ck_p, o_ddr_ck_n,o_ddr_reset_n, o_ddr_cke, |
// o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n,o_ddr_we_n; |
// output wire [2:0] o_ddr_ba; |
// output wire [13:0] o_ddr_addr; |
// output wire o_ddr_odt; |
// output wire [1:0] o_ddr_dm; |
// inout wire [1:0] io_ddr_dqs_p, io_ddr_dqs_n; |
// inout wire [15:0] io_ddr_data; |
// |
output wire o_ram_cyc, o_ram_stb, o_ram_we; |
output wire [25:0] o_ram_addr; |
output wire [31:0] o_ram_wdata; |
input i_ram_ack, i_ram_stall; |
input [31:0] i_ram_rdata; |
input i_ram_err; |
input [31:0] i_ram_dbg; |
// The SD Card |
output wire o_sd_sck; |
output wire o_sd_cmd; |
147,7 → 198,7
// Master wishbone wires |
// |
// |
wire wb_cyc, wb_stb, wb_we, wb_stall, wb_err; |
wire wb_cyc, wb_stb, wb_we, wb_stall, wb_err, ram_err; |
wire [31:0] wb_data, wb_addr; |
reg wb_ack; |
reg [31:0] wb_idata; |
375,16 → 426,17
mem_ack, flash_ack, ram_ack; |
reg many_ack, slow_many_ack; |
reg slow_ack, scop_ack; |
wire [4:0] ack_list; |
assign ack_list = { ram_ack, flash_ack, mem_ack, netb_ack, cfg_ack }; |
wire [5:0] ack_list; |
assign ack_list = { ram_ack, flash_ack, mem_ack, netb_ack, netp_ack, slow_ack }; |
initial many_ack = 1'b0; |
always @(posedge i_clk) |
many_ack <= ((ack_list != 5'h10) |
&&(ack_list != 5'h8) |
&&(ack_list != 5'h4) |
&&(ack_list != 5'h2) |
&&(ack_list != 5'h1) |
&&(ack_list != 5'h0)); |
many_ack <= ((ack_list != 6'h20) |
&&(ack_list != 6'h10) |
&&(ack_list != 6'h8) |
&&(ack_list != 6'h4) |
&&(ack_list != 6'h2) |
&&(ack_list != 6'h1) |
&&(ack_list != 6'h0)); |
/* |
assign many_ack = ( { 2'h0, ram_ack} |
+{2'h0, flash_ack } |
394,7 → 446,7
*/ |
|
wire [7:0] slow_ack_list; |
assign slow_ack_list = { mio_ack, gps_ack, netp_ack, |
assign slow_ack_list = { cfg_ack, mio_ack, gps_ack, |
sdcard_ack, rtc_ack, scop_ack, oled_ack, io_ack }; |
initial slow_many_ack = 1'b0; |
always @(posedge i_clk) |
409,12 → 461,9
&&(slow_ack_list != 8'h00)); |
|
always @(posedge i_clk) |
wb_ack <= (wb_cyc)&&(|{ ram_ack, flash_ack, mem_ack, |
netb_ack, cfg_ack, slow_ack }); |
wb_ack <= (wb_cyc)&&(|ack_list); |
always @(posedge i_clk) |
slow_ack <= (wb_cyc)&&(|{oled_ack, mio_ack, gps_ack, |
netp_ack, sdcard_ack, rtc_ack, scop_ack, |
oled_ack, io_ack}); |
slow_ack <= (wb_cyc)&&(|slow_ack_list); |
|
// |
// Peripheral data lines |
432,20 → 481,18
else if ((mem_ack)||(netb_ack)) |
wb_idata <= (mem_ack)?mem_data:netb_data; |
else |
wb_idata <= slow_data; |
wb_idata <= (netp_ack)?netp_data: slow_data; |
|
// 7 control lines, 8x32 data lines |
always @(posedge i_clk) |
if ((cfg_ack)||(mio_ack)) |
slow_data <= (cfg_ack) ? cfg_data : mio_data; |
else if ((gps_ack)||(netp_ack)) |
slow_data <= (gps_ack) ? gps_data : netp_data; |
else if ((sdcard_ack)||(rtc_ack)) |
slow_data <= (sdcard_ack)?sdcard_data : rtc_data; |
else if ((scop_ack)|(oled_ack)) |
slow_data <= (scop_ack)?scop_data:oled_data; |
else |
slow_data <= io_data; |
slow_data <= (gps_ack) ? gps_data : io_data; |
|
// |
// Peripheral stall lines |
465,7 → 512,7
||((sdcard_sel)&&(sdcard_stall))// Never stalls |
||((netp_sel)&&(netp_stall)) |
||((gps_sel)&&(gps_stall)) //(maybe? never stalls?) |
||((oled_sel)&&(oled_stall)) |
||((oled_sel)&&(oled_stall)) // Never stalls |
||((mio_sel)&&(mio_stall)) |
||((cfg_sel)&&(cfg_stall)) |
||((netb_sel)&&(netb_stall)) // Never stalls |
545,7 → 592,7
||((single_sel_a)&&(single_sel_b)) |
||((single_sel_a)&&(many_sel_a)) |
||((single_sel_b)&&(many_sel_b)); |
assign wb_err = (wb_cyc)&&(sel_err || many_ack || slow_many_ack); |
assign wb_err = (wb_cyc)&&(sel_err || many_ack || slow_many_ack||ram_err); |
|
|
// Finally, if we ever encounter a bus error, knowing the address of |
579,8 → 626,9
wire [3:0] w_led; |
wire rtc_ppd; |
fastio #( |
.AUXUART_SETUP(30'hd50), |
.GPSUART_SETUP(30'hd20833) |
.AUXUART_SETUP(30'hd705), // 115200 Baud, 8N1, from 81.25M |
.GPSUART_SETUP(30'hd8464), // 9600 Baud, 8N1 |
.EXTRACLOCK(0) |
) runio(i_clk, i_sw, i_btn, |
w_led, o_clr_led0, o_clr_led1, o_clr_led2, o_clr_led3, |
i_aux_rx, o_aux_tx, o_aux_cts, i_gps_rx, o_gps_tx, |
632,7 → 680,11
wire gps_tracking, ck_pps; |
wire [63:0] gps_step; |
`ifdef RTC_ACCESS |
rtcgps #(32'h15798f) // 2^48 / 200MHz |
rtcgps |
// #(32'h15798f) // 2^48 / 200MHz |
// #(32'h1a6e3a) // 2^48 / 162.5 MHz |
#(32'h34dc74) // 2^48 / 81.25MHz |
// #(32'h35afe6) // 2^48 / 80.0 MHz |
thertc(i_clk, |
wb_cyc, (wb_stb)&&(rtc_sel), wb_we, |
wb_addr[1:0], wb_data, |
743,7 → 795,9
// |
// GPS CLOCK CONTROL |
// |
gpsclock ppsck(i_clk, 1'b0, gps_pps, ck_pps, gps_led, |
gpsclock #( |
.DEFAULT_STEP(32'h834d_c736) |
) ppsck(i_clk, 1'b0, gps_pps, ck_pps, gps_led, |
(wb_stb)&&(gps_sel)&&(~wb_addr[3]), |
wb_we, wb_addr[1:0], |
wb_data, gck_ack, gck_stall, gck_data, |
795,7 → 849,7
assign enet_rx_int = 1'b0; |
assign enet_tx_int = 1'b0; |
|
enetctrl #(3) |
enetctrl #(2) |
mdio(i_clk, i_rst, wb_cyc, (wb_stb)&&(netb_sel), wb_we, |
wb_addr[4:0], wb_data[15:0], |
netb_ack, netb_stall, netb_data, |
836,9 → 890,11
// MULTIBOOT/ICAPE2 CONFIGURATION ACCESS |
// |
`ifdef ICAPE_ACCESS |
wbicapetwo fpga_cfg(i_clk, wb_cyc,(cfg_sel)&&(wb_stb), wb_we, |
wire [31:0] cfg_debug; |
wbicapetwo #(.LGDIV(1)) // Divide the clock by two |
fpga_cfg(i_clk, wb_cyc,(cfg_sel)&&(wb_stb), wb_we, |
wb_addr[4:0], wb_data, |
cfg_ack, cfg_stall, cfg_data); |
cfg_ack, cfg_stall, cfg_data, cfg_debug); |
`else |
reg r_cfg_ack; |
always @(posedge i_clk) |
853,7 → 909,8
// |
// There is no option to turn this off--this RAM must always be |
// present in the design. |
memdev #(15) // 32kW, or 128kB, 15 address lines |
memdev #(.AW(15), |
.EXTRACLOCK(0)) // 32kW, or 128kB, 15 address lines |
blkram(i_clk, wb_cyc, (wb_stb)&&(mem_sel), wb_we, wb_addr[14:0], |
wb_data, mem_ack, mem_stall, mem_data); |
|
897,13 → 954,39
// |
// |
`ifdef SDRAM_ACCESS |
wbddrsdram rami(i_clk, |
//wbddrsdram rami(i_clk, |
// wb_cyc, (wb_stb)&&(ram_sel), wb_we, wb_addr[25:0], wb_data, |
// ram_ack, ram_stall, ram_data, |
// o_ddr_reset_n, o_ddr_cke, |
// o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
// o_ddr_dqs, |
// o_ddr_addr, o_ddr_ba, o_ddr_data, i_ddr_data); |
|
assign o_ram_cyc = wb_cyc; |
assign o_ram_stb = (wb_stb)&&(ram_sel); |
assign o_ram_we = wb_we; |
assign o_ram_addr = wb_addr[25:0]; |
assign o_ram_wdata = wb_data; |
assign ram_ack = i_ram_ack; |
assign ram_stall = i_ram_stall; |
assign ram_data = i_ram_rdata; |
assign ram_err = i_ram_err; |
/* |
migsdram rami(i_clk, i_memref_clk_200mhz, i_rst, |
wb_cyc, (wb_stb)&&(ram_sel), wb_we, wb_addr[25:0], wb_data, |
ram_ack, ram_stall, ram_data, |
4'hf, |
ram_ack, ram_stall, ram_data, ram_err, |
// |
o_ddr_ck_p, o_ddr_ck_n, |
o_ddr_reset_n, o_ddr_cke, |
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
o_ddr_dqs, |
o_ddr_addr, o_ddr_ba, o_ddr_data, i_ddr_data); |
o_ddr_ba, o_ddr_addr, |
o_ddr_odt, o_ddr_dm, |
io_ddr_dqs_p, io_ddr_dqs_n, |
io_ddr_data, |
ram_ready |
); |
*/ |
`else |
assign ram_data = 32'h00; |
assign ram_stall = 1'b0; |
947,8 → 1030,8
&&(wb_err)||(zip_scope_data[31]); |
wbscope #(5'd13) cpuscope(i_clk, 1'b1,(scop_cpu_trigger), zip_scope_data, |
// Wishbone interface |
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)), wb_we, wb_addr[0], |
wb_data, |
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)), |
wb_we, wb_addr[0], wb_data, |
scop_cpu_ack, scop_cpu_stall, scop_cpu_data, |
scop_cpu_interrupt); |
|
966,8 → 1049,8
wbscope #(5'd13) flashscope(i_clk, 1'b1, |
(scop_flash_trigger), flash_debug, |
// Wishbone interface |
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)), wb_we, wb_addr[0], |
wb_data, |
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b00)), |
wb_we, wb_addr[0], wb_data, |
scop_flash_ack, scop_flash_stall, scop_flash_data, |
scop_flash_interrupt); |
|
1007,7 → 1090,33
wb_we, wb_addr[0], wb_data, |
scop_gps_ack, scop_gps_stall, scop_gps_data, |
scop_gps_interrupt); |
|
assign scop_b_ack = scop_gps_ack; |
assign scop_b_stall = scop_gps_stall; |
assign scop_b_data = scop_gps_data; |
assign scop_b_interrupt = scop_gps_interrupt; |
`else |
`ifdef CFG_SCOPE |
wire [31:0] scop_cfg_data; |
wire scop_cfg_ack, scop_cfg_stall, scop_cfg_interrupt; |
wire [31:0] cfg_debug_2; |
assign cfg_debug_2 = { |
wb_ack, cfg_debug[30:17], slow_ack, |
slow_data[7:0], wb_data[7:0] |
}; |
wbscope #(5'd8,32,1) cfgscope(i_clk, 1'b1, (cfg_sel)&&(wb_stb), |
cfg_debug_2, |
// Wishbone interface |
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b01)), |
wb_we, wb_addr[0], wb_data, |
scop_cfg_ack, scop_cfg_stall, scop_cfg_data, |
scop_cfg_interrupt); |
|
assign scop_b_data = scop_cfg_data; |
assign scop_b_stall = scop_cfg_stall; |
assign scop_b_ack = scop_cfg_ack; |
assign scop_b_interrupt = scop_cfg_interrupt; |
`else |
assign scop_b_data = 32'h00; |
assign scop_b_stall = 1'b0; |
assign scop_b_interrupt = 1'b0; |
1017,6 → 1126,7
r_scop_b_ack <= (wb_stb)&&(scop_sel)&&(wb_addr[2:1] == 2'b01); |
assign scop_b_ack = r_scop_b_ack; |
`endif |
`endif |
|
// |
// SCOPE C |
1024,7 → 1134,26
wire [31:0] scop_c_data; |
wire scop_c_ack, scop_c_stall, scop_c_interrupt; |
// |
//`else |
`ifdef SDRAM_SCOPE |
wire [31:0] scop_sdram_data; |
wire scop_sdram_ack, scop_sdram_stall, scop_sdram_interrupt; |
wire sdram_trigger; |
wire [31:0] sdram_debug; |
assign sdram_trigger = (ram_sel)&&(wb_stb); |
assign sdram_debug= i_ram_dbg; |
|
wbscope #(5'd10,32,1) ramscope(i_clk, 1'b1, sdram_trigger, sdram_debug, |
// Wishbone interface |
i_clk, wb_cyc, ((wb_stb)&&(scop_sel)&&(wb_addr[2:1]==2'b10)), |
wb_we, wb_addr[0], wb_data, |
scop_sdram_ack, scop_sdram_stall, scop_sdram_data, |
scop_sdram_interrupt); |
|
assign scop_c_ack = scop_sdram_ack; |
assign scop_c_stall = scop_sdram_stall; |
assign scop_c_data = scop_sdram_data; |
assign scop_c_interrupt = scop_sdram_interrupt; |
`else |
assign scop_c_data = 32'h00; |
assign scop_c_stall = 1'b0; |
assign scop_c_interrupt = 1'b0; |
1033,7 → 1162,7
always @(posedge i_clk) |
r_scop_c_ack <= (wb_stb)&&(scop_sel)&&(wb_addr[2:1] == 2'b10); |
assign scop_c_ack = r_scop_c_ack; |
//`endif |
`endif |
|
// |
// SCOPE D |
1052,13 → 1181,19
assign scop_d_ack = r_scop_d_ack; |
//`endif |
|
assign scop_int = scop_a_interrupt |
|| scop_b_interrupt |
|| scop_c_interrupt |
|| scop_d_interrupt; |
reg all_scope_interrupts; |
always @(posedge i_clk) |
all_scope_interrupts <= (scop_a_interrupt) |
|| (scop_b_interrupt) |
|| (scop_c_interrupt) |
|| (scop_d_interrupt); |
assign scop_int = all_scope_interrupts; |
|
// Scopes don't stall, so this line is more formality than anything |
// else. |
assign scop_stall = ((wb_addr[2:1]==2'b0)?scop_a_stall |
: ((wb_addr[2:1]==2'b01)?scop_b_stall |
: ((wb_addr[2:1]==2'b11)?scop_c_stall |
: ((wb_addr[2:1]==2'b10)?scop_c_stall |
: scop_d_stall))); // Will always be 1'b0; |
initial scop_ack = 1'b0; |
always @(posedge i_clk) |