URL
https://opencores.org/ocsvn/openarty/openarty/trunk
Subversion Repositories openarty
Compare Revisions
- This comparison shows the changes necessary to convert path
/openarty/trunk/rtl
- from Rev 12 to Rev 13
- ↔ Reverse comparison
Rev 12 → Rev 13
/xioddr.v
5,7 → 5,11
// Project: OpenArty, an entirely open SoC based upon the Arty platform |
// |
// Purpose: For the DDR3 SDRAM, this handles the Xilinx specific portions |
// of the IO necessary to make this happen for one pin only. |
// of the IO necessary to make this happen for one pin only. (In |
// the end, this never worked for the DDR3 SDRAM ...) In the case of the |
// QSPI flash, this module helps to reduce the logic delays on the "high |
// speed" flash data wires (it's not really used in any DDR mode in that |
// case ...). |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
36,16 → 40,19
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
module xioddr(i_clk, i_oe, i_v, o_v, io_w); |
module xioddr(i_clk, i_oe, i_v, o_v, io_pin); |
input i_clk, i_oe; |
input [1:0] i_v; |
output [1:0] o_v; |
inout io_w; |
inout io_pin; |
|
wire w_internal; |
reg last; |
always @(posedge i_clk) |
last <= i_v[1]; |
|
ODDR #( |
.DDR_CLK_EDGE("OPPOSITE_EDGE"), |
.DDR_CLK_EDGE("SAME_EDGE"), |
.INIT(1'b0), |
.SRTYPE("SYNC") |
) ODDRi( |
52,13 → 59,13
.Q(w_internal), |
.C(i_clk), |
.CE(1'b1), |
.D1(i_v[0]), |
.D2(i_v[1]), |
.D1(last), // Negative clock edge |
.D2(i_v[0]), // Positive clock edge |
.R(1'b0), |
.S(1'b0)); |
|
IDDR #( |
.DDR_CLK_EDGE("OPPOSITE_EDGE"), |
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), |
.INIT_Q1(1'b0), |
.INIT_Q2(1'b0), |
.SRTYPE("SYNC") |
67,10 → 74,10
.Q2(o_v[1]), |
.C(i_clk), |
.CE(1'b1), |
.D(io_w), |
.D(io_pin), |
.R(1'b0), |
.S(1'b0)); |
|
assign io_w = (i_oe) ? w_internal:1'bz; |
assign io_pin = (i_oe) ? w_internal:1'bz; |
|
endmodule |
/eqspiflash.v
724,7 → 724,8
accepted <= (~i_spi_busy)&&(i_grant)&&(o_spi_wr)&&(~accepted); |
|
reg [3:0] rd_state; |
reg r_leave_xip, r_xip, r_quad, r_requested, ack_valid; |
reg r_leave_xip, r_xip, r_quad, r_requested; |
reg [3:0] invalid_ack_pipe; |
initial rd_state = `RD_IDLE; |
initial o_data_ack = 1'b0; |
initial o_bus_ack = 1'b0; |
736,9 → 737,9
o_spi_recycle <= 1'b0; |
if (i_spi_valid) |
o_data <= i_spi_data; |
invalid_ack_pipe <= { invalid_ack_pipe[2:0], accepted }; |
case(rd_state) |
`RD_IDLE: begin |
ack_valid <= 1'b0; |
r_requested <= 1'b0; |
o_qspi_req <= 1'b0; |
o_spi_word <= { ((i_quad)? 8'h6B: 8'h0b), i_addr, 2'b00 }; |
757,7 → 758,6
`RD_IDLE_GET_PORT: begin |
o_spi_wr <= 1'b1; // Write the address |
o_qspi_req <= 1'b1; |
ack_valid <= 1'b0; |
if (accepted) |
rd_state <= `RD_SLOW_DUMMY; |
end |
768,7 → 768,6
o_spi_spd <= 1'b0; |
o_spi_word[31:24] <= (r_xip) ? 8'h00 : 8'hff; |
o_spi_len <= 2'b00; // 8 clocks = 8-bits |
ack_valid <= 1'b0; |
if (accepted) |
rd_state <= (r_quad)?`RD_QUAD_READ_DATA |
: `RD_SLOW_READ_DATA; |
779,12 → 778,10
o_spi_spd <= 1'b0; |
o_spi_len <= 2'b11; |
o_spi_wr <= (~r_requested)||(i_piperd); |
// if (accepted) |
// o_spi_wr <= (i_piperd); |
o_data_ack <= (ack_valid)&&(i_spi_valid); |
invalid_ack_pipe[0] <= (!r_requested); |
o_data_ack <= (!invalid_ack_pipe[3])&&(i_spi_valid)&&(r_requested); |
o_bus_ack <= (r_requested)&&(accepted)&&(i_piperd); |
r_requested <= (r_requested)||(accepted); |
ack_valid <= (accepted)?(r_requested):ack_valid; |
if ((i_spi_valid)&&(~o_spi_wr)) |
rd_state <= `RD_GO_TO_IDLE; |
end |
794,9 → 791,9
o_spi_spd <= 1'b1; |
o_spi_len <= 2'b11; |
o_spi_recycle <= (r_leave_xip)? 1'b1: 1'b0; |
invalid_ack_pipe[0] <= (!r_requested); |
r_requested <= (r_requested)||(accepted); |
ack_valid <= (r_requested); |
o_data_ack <= (ack_valid)&&(i_spi_valid)&&(~r_leave_xip); |
o_data_ack <= (!invalid_ack_pipe[3])&&(i_spi_valid)&&(r_requested)&&(~r_leave_xip); |
o_bus_ack <= (r_requested)&&(accepted)&&(i_piperd)&&(~r_leave_xip); |
o_spi_wr <= (~r_requested)||(i_piperd); |
// if (accepted) |
844,8 → 841,8
o_bus_ack <= i_readreq; |
end end |
`RD_GO_TO_IDLE: begin |
r_requested <= 1'b0; |
ack_valid <= 1'b0; |
if ((!invalid_ack_pipe[3])&&(i_spi_valid)&&(~r_leave_xip)) |
o_data_ack <= 1'b1; |
o_spi_wr <= 1'b0; |
o_qspi_req <= 1'b0; |
if ((i_spi_stopped)&&(~i_grant)) |
853,7 → 850,8
end |
`RD_GO_TO_XIP: begin |
r_requested <= 1'b0; |
ack_valid <= 1'b0; |
if ((i_spi_valid)&&(!invalid_ack_pipe[3])) |
o_data_ack <= 1'b1; |
o_qspi_req <= 1'b1; |
o_spi_wr <= 1'b0; |
if (i_spi_stopped) |
943,7 → 941,6
chk_wip <= 1'b0; |
o_bus_ack <= 1'b0; |
o_data_ack <= 1'b0; |
cyc <= (cyc)&&(~i_endpipe); |
case(wr_state) |
`WR_IDLE: begin |
valid_status <= 1'b0; |
1010,6 → 1007,7
o_spi_spd <= i_quad; |
o_spi_hold <= 1'b1; |
o_spi_word <= i_data; |
cyc <= (cyc)&&(~i_endpipe); |
if (~cyc) |
wr_state <= `WR_WAIT_ON_STOP; |
else if (i_pipewr) |
1160,6 → 1158,7
|
reg [2:0] ctstate; |
reg accepted; |
reg [3:0] invalid_ack_pipe; |
|
|
initial accepted = 1'b0; |
1278,6 → 1277,7
o_spi_wr <= 1'b1; |
o_bus_ack <= 1'b0; |
o_data_ack <= 1'b0; |
invalid_ack_pipe <= { invalid_ack_pipe[2:0], accepted }; |
if (i_spi_valid) |
o_data <= i_spi_data; |
case(ctstate) |
1322,9 → 1322,8
`CT_READ_DATA: begin |
o_spi_wr <= 1'b0; // No more words to go, just to wait |
o_spi_req <= 1'b1; |
if (i_spi_valid) |
first_valid <= 1'b1; |
if ((i_spi_valid)&&(first_valid)) // for a value to read |
invalid_ack_pipe[0] <= 1'b0; |
if ((i_spi_valid)&&(!invalid_ack_pipe[3])) // for a value to read |
begin |
o_data_ack <= 1'b1; |
o_data <= i_spi_data; |
1442,8 → 1441,9
reg nxt_data_ack, nxt_data_spi; |
reg [31:0] nxt_data; |
|
reg set_val, chk_wip, first_valid, valid_status; |
reg set_val, chk_wip, first_valid; |
reg [2:0] set_addr; |
reg [3:0] invalid_ack_pipe; |
|
always @(posedge i_clk) |
begin // Depends upon state[4], otp_rd, otp_wr, otp_pipe, id_req, accepted, last_addr |
1454,6 → 1454,7
nxt_data_spi <= 1'b0; |
chk_wip <= 1'b0; |
set_val <= 1'b0; |
invalid_ack_pipe <= { invalid_ack_pipe[2:0], accepted }; |
if ((id_loaded)&&(id_read_request)) |
begin |
nxt_data_ack <= 1'b1; |
1527,9 → 1528,8
o_spi_wr <= (~last_addr); // Still transmitting |
o_spi_dir <= 1'b1; // Read from SPI |
o_qspi_req <= 1'b1; |
if (i_spi_valid) // two clocks after accepted |
first_valid <= 1'b1; |
if((i_spi_valid)&&(first_valid)) |
invalid_ack_pipe[0] <= 1'b0; |
if((i_spi_valid)&&(!invalid_ack_pipe[3])) |
begin |
set_val <= 1'b1; |
set_addr <= lcl_id_addr[2:0]; |
1567,9 → 1567,8
id_state <= `ID_OTP_GET_DATA; |
end |
`ID_OTP_GET_DATA: begin |
if (i_spi_valid) |
first_valid <= 1'b1; |
if ((i_spi_valid)&&(first_valid)) |
invalid_ack_pipe[0] <= 1'b0; |
if ((i_spi_valid)&&(!invalid_ack_pipe[3])) |
begin |
id_state <= `ID_FINAL_STOP; |
nxt_data_ack <= 1'b1; |
1609,7 → 1608,6
o_spi_dir <= 1'b1; // Read |
o_spi_len <= 2'b00; // 8 bits |
// o_spi_word <= dont care |
valid_status <= 1'b0; |
if (accepted) |
id_state <= `ID_READ_STATUS; |
end |
1619,9 → 1617,8
o_spi_dir <= 1'b1; // Read |
o_spi_len <= 2'b00; // 8 bits |
// o_spi_word <= dont care |
if (i_spi_valid) |
valid_status <= 1'b1; |
if ((i_spi_valid)&&(valid_status)) |
invalid_ack_pipe[0] <= 1'b0; |
if ((i_spi_valid)&&(~invalid_ack_pipe[3])) |
chk_wip <= 1'b1; |
if ((chk_wip)&&(~i_spi_data[0])) |
begin |
/fastmaster.v
62,10 → 62,20
`define RTC_ACCESS |
`define OLEDRGB_ACCESS |
// |
`define FLASH_SCOPE // Position zero |
`ifdef FLASH_ACCESS |
`define FLASH_SCOPE // Position zero |
`else |
`ifdef ZIPCPU |
// `define CPU_SCOPE // Position zero |
`endif |
`endif |
// `define GPS_SCOPE // Position one |
`ifdef ICAPE_ACCESS |
`define CFG_SCOPE // Position one |
`endif |
`ifdef SDRAM_ACCESS |
// `define SDRAM_SCOPE // Position two |
`endif |
// `define ENET_SCOPE |
// |
// |
377,16 → 387,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 } |
396,7 → 407,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) |
411,12 → 422,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 |
434,20 → 442,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 |
467,7 → 473,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 |
847,9 → 853,10
// MULTIBOOT/ICAPE2 CONFIGURATION ACCESS |
// |
`ifdef ICAPE_ACCESS |
wire [31:0] cfg_debug; |
wbicapetwo 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) |
1018,7 → 1025,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; |
1028,6 → 1061,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 |
1088,10 → 1122,16
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 |
/xoddr.v
0,0 → 1,66
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: xoddr.v |
// |
// Project: OpenArty, an entirely open SoC based upon the Arty platform |
// |
// Purpose: For the DDR3 SDRAM, this handles the Xilinx specific portions |
// of the output necessary to make this happen for one pin only. |
// For the QSPI, this helps to make certain that as much of the logic |
// delay as possible has been removed from the path--to get the full |
// 100MHz speed. |
// |
// 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 xoddr(i_clk, i_v, o_pin); |
input i_clk; |
input [1:0] i_v; |
output o_pin; |
|
wire w_internal; |
reg last; |
|
always @(posedge i_clk) |
last <= i_v[1]; |
|
ODDR #( |
.DDR_CLK_EDGE("SAME_EDGE"), |
.INIT(1'b0), |
.SRTYPE("SYNC") |
) ODDRi( |
.Q(o_pin), |
.C(i_clk), |
.CE(1'b1), |
.D1(last), // Negative clock edge (goes first) |
.D2(i_v[0]), // Positive clock edge |
.R(1'b0), |
.S(1'b0)); |
|
endmodule |
/fasttop.v
214,7 → 214,7
// |
// |
////// |
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; |
241,7 → 241,7
// 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, |
w_ddr_cs_n, w_ddr_ras_n, w_ddr_cas_n, w_ddr_we_n, |
278,7 → 278,7
// ?? Dual mode out (not yet) |
// |
// |
`define QSPI_OUT_VERSION_ONE |
// `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])); |
285,104 → 285,29
assign i_qspi_dat = io_qspi_dat; |
assign o_qspi_sck = w_qspi_sck; |
`else |
wire [3:0] i_qspi_ignore; |
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[0])||(~qspi_bmod[1]), |
xioddr xqspi_d0( i_clk, (qspi_bmod != 2'b11), |
{ qspi_dat[0], qspi_dat[0] }, |
{ i_qspi_ignore[0], i_qspi_dat[0] }, io_qspi_dat[0]); |
{ i_qspi_pedge[0], i_qspi_nedge[0] }, io_qspi_dat[0]); |
xioddr xqspi_d1( i_clk, (qspi_bmod==2'b10), |
{ qspi_dat[1], qspi_dat[1] }, |
{ i_qspi_ignore[1], i_qspi_dat[1] }, io_qspi_dat[1]); |
{ i_qspi_pedge[1], i_qspi_nedge[1] }, io_qspi_dat[1]); |
xioddr xqspi_d2( i_clk, (qspi_bmod!=2'b11), |
(qspi_bmod[1])?{ qspi_dat[2], qspi_dat[2] }:2'b11, |
{ i_qspi_ignore[2], i_qspi_dat[2] }, io_qspi_dat[2]); |
{ i_qspi_pedge[2], i_qspi_nedge[2] }, io_qspi_dat[2]); |
xioddr xqspi_d3( i_clk, (qspi_bmod!=2'b11), |
(qspi_bmod[1])?{ qspi_dat[3], qspi_dat[3] }:2'b11, |
{ i_qspi_ignore[3], i_qspi_dat[3] }, io_qspi_dat[3]); |
{ 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 |
// |
// |
// 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 on other boards in order to |
// gain access to the o_qspi_sck pin. On the Arty, however, there is |
// a clock PIN, so we don't need this primitive. |
// |
// |
/* |
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 |
// |
// |
/builddate.v
38,4 → 38,4
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
`define DATESTAMP 32'h20160810 |
`define DATESTAMP 32'h20160811 |
/wbscope.v
101,6 → 101,17
// 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)]; |
|
111,13 → 122,13
wire [19:0] bw_holdoff; |
initial br_config = ((1<<(LGMEM-1))-4); |
always @(posedge i_wb_clk) |
if ((i_wb_stb)&&(~i_wb_addr)) |
if ((r_wb_stb)&&(~r_wb_addr)) |
begin |
if (i_wb_we) |
br_config <= { i_wb_data[31], |
(i_wb_data[27]), |
i_wb_data[26], |
i_wb_data[19:0] }; |
if (r_wb_we) |
br_config <= { r_wb_data[31], |
(r_wb_data[27]), |
r_wb_data[26], |
r_wb_data[19:0] }; |
end else if (bw_reset_complete) |
br_config[22] <= 1'b1; |
assign bw_reset_request = (~br_config[22]); |
273,21 → 284,26
end endgenerate |
|
// Reads use the bus clock |
reg br_wb_ack, r_wb_ack; // takes one clock to read |
wire bw_cyc_stb, bus_read_fifo; |
assign bw_cyc_stb = (i_wb_stb); |
assign bus_read_fifo = (i_wb_stb)&&(i_wb_addr)&&(~i_wb_we); |
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); |
initial br_wb_ack = 1'b0; |
always @(posedge i_wb_clk) |
begin // CE depends upon 5 inputs, output on 7 (ignoring add&carries) |
if ((bw_reset_request) |
||((bw_cyc_stb)&&(i_wb_addr)&&(i_wb_we))) |
if ((bw_reset_request)||(bus_write_fifo)) |
raddr <= 0; |
else if ((bus_read_fifo)&&(bw_stopped)) |
raddr <= raddr + {{(LGMEM-1){1'b0}},1'b1}; // Data read, when stopped |
|
r_wb_ack <= i_wb_stb; |
br_wb_ack <= r_wb_ack; |
r_wb_ack <= r_wb_stb; |
s_wb_ack <= r_wb_ack; |
br_wb_ack <= s_wb_ack; |
end |
|
reg [(LGMEM-1):0] nxt_addr; |
303,14 → 319,15
always @(posedge i_wb_clk) |
nxt_mem <= mem[nxt_addr]; |
|
reg r_wb_addr; |
always @(posedge i_clk) |
r_wb_addr <= i_wb_addr; |
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 (~r_wb_addr) // Control register read |
if (~q_wb_addr) // Control register read |
o_wb_data <= { bw_reset_request, |
bw_stopped, |
bw_triggered, |
326,7 → 343,7
o_wb_data <= nxt_mem; // mem[raddr+waddr]; |
|
assign o_wb_stall = 1'b0; |
assign o_wb_ack = (br_wb_ack); |
assign o_wb_ack = (s_wb_ack); |
|
reg br_level_interrupt; |
initial br_level_interrupt = 1'b0; |
/wbicapetwo.v
95,7 → 95,7
`define MBOOT_DESYNC 5'h11 |
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_wb_ack, o_wb_stall, o_wb_data, o_dbg); |
input i_clk; |
// Wishbone inputs |
input i_wb_cyc, i_wb_stb, i_wb_we; |
104,6 → 104,8
// Wishbone outputs |
output reg o_wb_ack, o_wb_stall; |
output reg [31:0] o_wb_data; |
// Debugging output |
output wire [31:0] o_dbg; |
// ICAPE2 interface signals |
// These are kept internal to this block ... |
|
111,7 → 113,38
reg [31:0] r_data; |
reg [4:0] r_addr; |
|
reg slow_clk; |
`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) |
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 [31:0] cfg_in; |
reg cfg_cs_n, cfg_rdwrn; |
wire [31:0] cfg_out; |
120,13 → 153,19
initial cfg_cs_n = 1'b1; |
always @(posedge i_clk) |
begin |
// In general, o_wb_ack is always zero. The exceptions to this |
// will be handled individually below. |
o_wb_ack <= 1'b0; |
// We can simplify our logic a touch by always setting |
// o_wb_data. It will only be examined if o_wb_ack |
// is also true, so this is okay. |
o_wb_data <= cfg_out; |
|
// Turn any request "off", so that it will not be ack'd, if |
// the wb_cyc line is ever lowered. |
wb_req <= wb_req & i_wb_cyc; |
slow_clk <= slow_clk ^ 1'b1; |
o_wb_stall <= (state != `MBOOT_IDLE)&&(slow_clk); |
if (~slow_clk) |
o_wb_stall <= (state != `MBOOT_IDLE)||(clk_stall); |
if (clk_stb) |
begin |
state <= state + 5'h01; |
case(state) |
142,7 → 181,7
r_addr <= i_wb_addr; |
r_data <= i_wb_data; |
r_we <= i_wb_we; |
if(i_wb_stb) |
if(i_wb_stb) // &&(!o_wb_stall) |
begin |
state <= `MBOOT_START; |
wb_req <= 1'b1; |
149,21 → 188,40
// |
o_wb_ack <= 1'b0; |
end end |
`MBOOT_START: cfg_in <= 32'hffffffff; // NOOP |
`MBOOT_START: begin |
cfg_in <= 32'hffffffff; // NOOP |
cfg_cs_n <= 1'b1; |
end |
5'h02: begin |
cfg_cs_n <= 1'b0; // Activate interface |
cfg_rdwrn <= 1'b0; |
cfg_in <= 32'h20000000; // NOOP |
end |
5'h03: cfg_in <= 32'haa995566; // Sync word |
5'h04: cfg_in <= 32'h20000000; // NOOP |
5'h03: begin |
cfg_in <= 32'haa995566; // Sync word |
cfg_cs_n <= 1'b0; |
end |
5'h04: begin |
cfg_in <= 32'h20000000; // NOOP |
cfg_cs_n <= 1'b0; |
end |
5'h05: begin |
cfg_in <= 32'h20000000; // NOOP |
state <= (r_we) ? `MBOOT_WRITE : `MBOOT_READ; |
cfg_cs_n <= 1'b0; |
end |
`MBOOT_READ: cfg_in <= { 8'h28, 6'h0, r_addr, 13'h001 }; |
5'h07: cfg_in <= 32'h20000000; // NOOP |
5'h08: cfg_in <= 32'h20000000; // NOOP |
`MBOOT_READ: begin |
cfg_cs_n <= 1'b0; |
cfg_in <= { 8'h28, 6'h0, r_addr, 13'h001 }; |
end |
5'h07: begin |
cfg_cs_n <= 1'b0; |
cfg_in <= 32'h20000000; // NOOP |
end |
5'h08: begin |
cfg_cs_n <= 1'b0; |
cfg_in <= 32'h20000000; // NOOP |
end |
5'h09: begin // Idle the interface before the read cycle |
cfg_cs_n <= 1'b1; |
cfg_rdwrn <= 1'b1; |
174,12 → 232,18
cfg_rdwrn <= 1'b1; |
cfg_in <= 32'h20000000; // NOOP |
end |
5'h0b: // ... still waiting, cycle two |
5'h0b: begin // ... still waiting, cycle two |
cfg_in <= 32'h20000000; // NOOP |
5'h0c: // ... still waiting, cycle three |
cfg_cs_n <= 1'b0; |
end |
5'h0c: begin // ... still waiting, cycle three |
cfg_in <= 32'h20000000; // NOOP |
5'h0d: // ... still waiting, cycle four |
cfg_cs_n <= 1'b0; |
end |
5'h0d: begin // ... still waiting, cycle four |
cfg_in <= 32'h20000000; // NOOP |
cfg_cs_n <= 1'b0; |
end |
5'h0e: begin // and now our answer is there |
cfg_cs_n <= 1'b1; |
cfg_rdwrn <= 1'b1; |
187,24 → 251,45
// |
// Wishbone return |
o_wb_ack <= wb_req; |
o_wb_data <= cfg_out; |
// o_wb_data <= cfg_out; // Independent of state |
wb_req <= 1'b0; |
// |
state <= `MBOOT_DESYNC; |
end |
`MBOOT_WRITE: // Issue a write command to the given address |
`MBOOT_WRITE: begin |
// Issue a write command to the given address |
cfg_in <= { 8'h30, 6'h0, r_addr, 13'h001 }; |
5'h10: cfg_in <= r_data; // Write the value |
cfg_cs_n <= 1'b0; |
end |
5'h10: begin |
cfg_in <= r_data; // Write the value |
cfg_cs_n <= 1'b0; |
end |
`MBOOT_DESYNC: begin |
cfg_cs_n <= 1'b0; |
cfg_rdwrn <= 1'b0; |
cfg_in <= 32'h20000000; // 1st NOOP |
end |
5'h12: cfg_in <= 32'h20000000; // 2nd NOOP |
5'h13: cfg_in <= 32'h30008001; // Write to CMD register |
5'h14: cfg_in <= 32'h0000000d; // DESYNC command |
5'h15: cfg_in <= 32'h20000000; // NOOP |
5'h16: cfg_in <= 32'h20000000; // NOOP |
5'h12: begin |
cfg_cs_n <= 1'b0; |
cfg_in <= 32'h20000000; // 2nd NOOP |
end |
5'h13: begin |
cfg_cs_n <= 1'b0; |
cfg_in <= 32'h30008001; // Write to CMD register |
end |
5'h14: begin |
cfg_cs_n <= 1'b0; |
cfg_in <= 32'h0000000d; // DESYNC command |
end |
5'h15: begin |
cfg_cs_n <= 1'b0; |
cfg_in <= 32'h20000000; // NOOP |
end |
5'h16: begin |
cfg_cs_n <= 1'b0; |
cfg_in <= 32'h20000000; // NOOP |
end |
5'h17: begin |
// Acknowledge the bus transaction, it is now complete |
o_wb_ack <= wb_req; |
217,7 → 302,7
state <= `MBOOT_IDLE; |
end |
default: begin |
o_wb_ack <= 1'b0; |
wb_req <= 1'b0; |
cfg_cs_n <= 1'b1; |
cfg_rdwrn <= 1'b0; |
state <= `MBOOT_IDLE; |
224,8 → 309,6
cfg_in <= 32'hffffffff; // DUMMY WORD |
end |
endcase |
end else begin |
o_wb_ack <= 1'b0; |
end |
end |
|
259,4 → 342,16
ICAPE2 #(.ICAP_WIDTH("X32")) reconfig(.CLK(slow_clk), |
.CSIB(cfg_cs_n), .RDWRB(cfg_rdwrn), |
.I(bit_swapped_cfg_in), .O(bit_swapped_cfg_out)); |
|
assign o_dbg = { |
`ifdef DIVIDE_BY_FOUR |
slow_clk_counter, clk_stb, clk_stall, |
`else |
1'b0, slow_clk, clk_stb, clk_stall, |
`endif |
i_wb_stb, o_wb_ack, cfg_cs_n, cfg_rdwrn, |
o_wb_stall, state, 2'h0, |
cfg_in[7:0], |
cfg_out[7:0] }; |
|
endmodule |
/lleqspi.v
70,7 → 70,7
input i_dir; // 0 -> read, 1 -> write to SPI |
input i_recycle; // 0 = 20ns, 1 = 50ns |
output reg [31:0] o_word; |
output wire o_valid; |
output reg o_valid; |
output reg o_busy; |
// Interface with the QSPI lines |
output reg o_sck; |
298,38 → 298,42
end |
|
`define EXTRA_DELAY |
wire rd_input_N, rd_valid_N, r_spd_N; |
`ifdef EXTRA_DELAY |
reg rd_input_2, rd_valid_2, r_spd_2; |
reg [2:0] rd_input_p, rd_valid_p, r_spd_p; |
always @(posedge i_clk) |
rd_input_2 <= rd_input; |
rd_input_p <= { rd_input_p[1:0], rd_input }; |
always @(posedge i_clk) |
rd_valid_2 <= rd_valid; |
rd_valid_p <= { rd_valid_p[1:0], rd_valid }; |
always @(posedge i_clk) |
r_spd_2 <= r_spd; |
r_spd_p <= { r_spd_p[1:0], r_spd }; |
|
assign rd_input_N = rd_input_p[2]; |
assign rd_valid_N = rd_valid_p[2]; |
assign r_spd_N = r_spd_p[2]; |
`else |
wire rd_input_2, rd_valid_2, r_spd_2; |
assign rd_input_2 = rd_input; |
assign rd_valid_2 = rd_valid; |
assign r_spd_2 = rd_spd; |
assign rd_input_N = rd_input; |
assign rd_valid_N = rd_valid; |
assign r_spd_N = rd_spd; |
`endif |
|
|
always @(posedge i_clk) |
begin |
if ((state == `EQSPI_IDLE)||(rd_valid_2)) |
// if ((state == `EQSPI_IDLE)||(rd_valid_N)) |
if (o_valid) |
r_input <= 31'h00; |
else if ((rd_input_2)&&(r_spd_2)) |
if ((rd_input_N)&&(r_spd_N)) |
r_input <= { r_input[26:0], i_dat }; |
else if (rd_input_2) |
else if (rd_input_N) |
r_input <= { r_input[29:0], i_miso }; |
|
if ((rd_valid)&&(rd_spd)) |
if ((rd_valid_N)&&(r_spd_N)) |
o_word <= { r_input[27:0], i_dat }; |
else if (rd_valid) |
else if (rd_valid_N) |
o_word <= { r_input[30:0], i_miso }; |
o_valid <= rd_valid_N; |
end |
|
assign o_valid = rd_valid_2; |
|
endmodule |
|