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

Subversion Repositories ftdi_wb_bridge

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /ftdi_wb_bridge/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/testbench/simulation.svh
0,0 → 1,57
`timescale 1ns/1ps
 
//-----------------------------------------------------------------
// assert_task
//-----------------------------------------------------------------
task automatic assert_task(input v, string file, int line, input string s);
begin
if (!v)
begin
$display("ASSERT: %s:%0d - %s", file, line, s);
$finish(1);
end
end
endtask
 
//-----------------------------------------------------------------
// ASSERT
//-----------------------------------------------------------------
`define ASSERT(v) assert_task(v, `__FILE__, `__LINE__, `"v`")
 
//-----------------------------------------------------------------
// CLOCK_GEN
//-----------------------------------------------------------------
`define CLOCK_GEN(NAME, CYCLE) \
reg ``NAME; \
initial \
begin \
``NAME <= 0; \
forever # (``CYCLE / 2) ``NAME = ~``NAME; \
end
 
//-----------------------------------------------------------------
// RESET_GEN
//-----------------------------------------------------------------
`define RESET_GEN(NAME, DELAY) \
reg ``NAME; \
initial \
begin \
``NAME <= 1; \
# ``DELAY \
``NAME <= 0; \
end
 
//-----------------------------------------------------------------
// TB_VCD
//-----------------------------------------------------------------
`define TB_VCD(TOP, NAME) \
initial \
begin \
$dumpfile(``NAME); \
$dumpvars(0,``TOP); \
end
 
//-----------------------------------------------------------------
// TB_RUN_FOR
//-----------------------------------------------------------------
`define TB_RUN_FOR(TIME) initial #``TIME $finish;
/testbench/wb_slave.sv
0,0 → 1,231
//-----------------------------------------------------------------
// Module
//-----------------------------------------------------------------
module wb_slave
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
 
// Wishbone I/F
input [31:0] addr_i /*verilator public*/,
input [31:0] data_i /*verilator public*/,
output reg [31:0] data_o /*verilator public*/,
input [3:0] sel_i /*verilator public*/,
input cyc_i /*verilator public*/,
input stb_i /*verilator public*/,
input [2:0] cti_i /*verilator public*/,
input we_i /*verilator public*/,
output reg ack_o /*verilator public*/,
output reg stall_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter MAX_RESP_RATE = 0;
parameter RESP_DELAY_RATE = 3;
 
parameter RANDOM_STALLS = 1;
parameter STALL_RATE = 3;
 
`include "simulation.svh"
 
//-----------------------------------------------------------------
// Request Queue
//-----------------------------------------------------------------
typedef struct
{
reg [31:0] address;
reg [31:0] data;
reg [3:0] sel;
reg we;
} request_t;
 
request_t requests[$];
 
//-----------------------------------------------------------------
// Memory
//-----------------------------------------------------------------
reg [31:0] mem[*];
 
//-----------------------------------------------------------------
// write
//-----------------------------------------------------------------
task automatic write(input [31:0] addr, input [31:0] data);
begin
mem[addr[31:2]] = data;
end
endtask
 
//-----------------------------------------------------------------
// read
//-----------------------------------------------------------------
task automatic read(input [31:0] addr, output [31:0] data);
begin
if (mem.exists(addr[31:2]))
data = mem[addr[31:2]];
else
data = 32'bx;
end
endtask
//-----------------------------------------------------------------
// read8
//-----------------------------------------------------------------
task automatic read8(input [31:0] addr, output [7:0] data);
begin
if (mem.exists(addr[31:2]))
begin
reg [31:0] tmp_data;
tmp_data = mem[addr[31:2]];
 
case (addr[1:0])
0: data = tmp_data[7:0];
1: data = tmp_data[15:8];
2: data = tmp_data[23:16];
3: data = tmp_data[31:24];
endcase
end
else
data = 8'bx;
end
endtask
//-----------------------------------------------------------------
// write_bytes
//-----------------------------------------------------------------
task automatic write_bytes(input [31:0] addr, input [31:0] data, input [31:0] sel);
begin
reg [31:0] new_data;
 
read(addr, new_data);
 
if (sel[3])
new_data[31:24] = data[31:24];
if (sel[2])
new_data[23:16] = data[23:16];
if (sel[1])
new_data[15:8] = data[15:8];
if (sel[0])
new_data[7:0] = data[7:0];
 
write(addr, new_data);
end
endtask
 
//-----------------------------------------------------------------
// response
//-----------------------------------------------------------------
initial
begin
request_t req;
 
ack_o = 1'b0;
data_o = 32'bz;
 
forever
begin
@(posedge clk_i);
 
ack_o = 1'b0;
data_o = 32'bz;
 
if (!MAX_RESP_RATE)
begin
repeat ($urandom_range(RESP_DELAY_RATE,0)) @(posedge clk_i);
end
 
if (requests.size() > 0)
begin
req = requests.pop_front();
 
// Write
if (req.we)
begin
ack_o = 1'b1;
data_o = 32'bz;
write_bytes(req.address, req.data, req.sel);
end
// Read
else
begin
ack_o = 1'b1;
read(req.address, data_o);
end
end
end
end
 
//-----------------------------------------------------------------
// request
//-----------------------------------------------------------------
always @(posedge clk_i)
begin
// Request presented and accepted
if (stb_i && cyc_i && !stall_o)
begin
request_t req;
 
req.address = addr_i;
req.data = data_i;
req.sel = sel_i;
req.we = we_i;
 
requests.push_back(req);
end
end
 
always @(posedge rst_i or posedge clk_i)
if (rst_i)
stall_o <= 1'b0;
else
begin
if (RANDOM_STALLS)
stall_o <= ($urandom_range(STALL_RATE,0) == 0);
end
 
//-----------------------------------------------------------------
// CTI
//-----------------------------------------------------------------
initial
begin
reg burst;
reg [2:0] burst_cnt;
 
burst = 1'b0;
burst_cnt = 0;
 
forever
begin
@(posedge clk_i);
 
// Start of burst
if (stb_i && cyc_i && !stall_o && cti_i == 3'b010)
begin
burst_cnt = 7;
burst = 1;
 
while (burst_cnt != 0)
begin
@(posedge clk_i);
 
if (stb_i && cyc_i && !stall_o)
begin
if (burst_cnt == 1)
begin
`ASSERT(cti_i == 3'b111);
end
 
burst_cnt = burst_cnt - 1;
end
end
 
burst = 0;
end
else if (stb_i && cyc_i && !stall_o)
begin
`ASSERT(cti_i == 3'b111);
end
end
end
 
endmodule
/testbench/makefile
0,0 → 1,29
TRACE ?= 1
 
all: compile run view
# Testbench
SRC+= ./top_tb.sv wb_slave.sv
 
SRC+= ../rtl/ftdi_if.v ../rtl/ftdi_sync.v
 
ifeq ($(TRACE),1)
SRC_FLAGS += +define+TRACE=$(TRACE)
endif
 
INC_DIRS = -I.
 
compile :
vlib work
vlog $(SRC) $(SRC_FLAGS)
run : compile
vsim -c -do "run -all" top_tb
view : compile
ifeq ($(TRACE),1)
gtkwave waveform.vcd gtksettings.sav
endif
 
clean :
-rm -rf work waveform.vcd transcript
/testbench/gtksettings.sav
0,0 → 1,32
@28
top_tb.clk
top_tb.rst
@200
-
-WB
@22
#{top_tb.u_dut.mem_addr_o[31:0]} top_tb.u_dut.mem_addr_o[31] top_tb.u_dut.mem_addr_o[30] top_tb.u_dut.mem_addr_o[29] top_tb.u_dut.mem_addr_o[28] top_tb.u_dut.mem_addr_o[27] top_tb.u_dut.mem_addr_o[26] top_tb.u_dut.mem_addr_o[25] top_tb.u_dut.mem_addr_o[24] top_tb.u_dut.mem_addr_o[23] top_tb.u_dut.mem_addr_o[22] top_tb.u_dut.mem_addr_o[21] top_tb.u_dut.mem_addr_o[20] top_tb.u_dut.mem_addr_o[19] top_tb.u_dut.mem_addr_o[18] top_tb.u_dut.mem_addr_o[17] top_tb.u_dut.mem_addr_o[16] top_tb.u_dut.mem_addr_o[15] top_tb.u_dut.mem_addr_o[14] top_tb.u_dut.mem_addr_o[13] top_tb.u_dut.mem_addr_o[12] top_tb.u_dut.mem_addr_o[11] top_tb.u_dut.mem_addr_o[10] top_tb.u_dut.mem_addr_o[9] top_tb.u_dut.mem_addr_o[8] top_tb.u_dut.mem_addr_o[7] top_tb.u_dut.mem_addr_o[6] top_tb.u_dut.mem_addr_o[5] top_tb.u_dut.mem_addr_o[4] top_tb.u_dut.mem_addr_o[3] top_tb.u_dut.mem_addr_o[2] top_tb.u_dut.mem_addr_o[1] top_tb.u_dut.mem_addr_o[0]
#{top_tb.u_dut.mem_data_o[31:0]} top_tb.u_dut.mem_data_o[31] top_tb.u_dut.mem_data_o[30] top_tb.u_dut.mem_data_o[29] top_tb.u_dut.mem_data_o[28] top_tb.u_dut.mem_data_o[27] top_tb.u_dut.mem_data_o[26] top_tb.u_dut.mem_data_o[25] top_tb.u_dut.mem_data_o[24] top_tb.u_dut.mem_data_o[23] top_tb.u_dut.mem_data_o[22] top_tb.u_dut.mem_data_o[21] top_tb.u_dut.mem_data_o[20] top_tb.u_dut.mem_data_o[19] top_tb.u_dut.mem_data_o[18] top_tb.u_dut.mem_data_o[17] top_tb.u_dut.mem_data_o[16] top_tb.u_dut.mem_data_o[15] top_tb.u_dut.mem_data_o[14] top_tb.u_dut.mem_data_o[13] top_tb.u_dut.mem_data_o[12] top_tb.u_dut.mem_data_o[11] top_tb.u_dut.mem_data_o[10] top_tb.u_dut.mem_data_o[9] top_tb.u_dut.mem_data_o[8] top_tb.u_dut.mem_data_o[7] top_tb.u_dut.mem_data_o[6] top_tb.u_dut.mem_data_o[5] top_tb.u_dut.mem_data_o[4] top_tb.u_dut.mem_data_o[3] top_tb.u_dut.mem_data_o[2] top_tb.u_dut.mem_data_o[1] top_tb.u_dut.mem_data_o[0]
#{top_tb.u_dut.mem_data_i[31:0]} top_tb.u_dut.mem_data_i[31] top_tb.u_dut.mem_data_i[30] top_tb.u_dut.mem_data_i[29] top_tb.u_dut.mem_data_i[28] top_tb.u_dut.mem_data_i[27] top_tb.u_dut.mem_data_i[26] top_tb.u_dut.mem_data_i[25] top_tb.u_dut.mem_data_i[24] top_tb.u_dut.mem_data_i[23] top_tb.u_dut.mem_data_i[22] top_tb.u_dut.mem_data_i[21] top_tb.u_dut.mem_data_i[20] top_tb.u_dut.mem_data_i[19] top_tb.u_dut.mem_data_i[18] top_tb.u_dut.mem_data_i[17] top_tb.u_dut.mem_data_i[16] top_tb.u_dut.mem_data_i[15] top_tb.u_dut.mem_data_i[14] top_tb.u_dut.mem_data_i[13] top_tb.u_dut.mem_data_i[12] top_tb.u_dut.mem_data_i[11] top_tb.u_dut.mem_data_i[10] top_tb.u_dut.mem_data_i[9] top_tb.u_dut.mem_data_i[8] top_tb.u_dut.mem_data_i[7] top_tb.u_dut.mem_data_i[6] top_tb.u_dut.mem_data_i[5] top_tb.u_dut.mem_data_i[4] top_tb.u_dut.mem_data_i[3] top_tb.u_dut.mem_data_i[2] top_tb.u_dut.mem_data_i[1] top_tb.u_dut.mem_data_i[0]
#{top_tb.u_dut.mem_sel_o[3:0]} top_tb.u_dut.mem_sel_o[3] top_tb.u_dut.mem_sel_o[2] top_tb.u_dut.mem_sel_o[1] top_tb.u_dut.mem_sel_o[0]
@28
top_tb.u_dut.mem_we_o
top_tb.u_dut.mem_cyc_o
top_tb.u_dut.mem_stb_o
top_tb.u_dut.mem_stall_i
top_tb.u_dut.mem_ack_i
@200
-
-FTDI
@28
top_tb.u_dut.ftdi_rxf_i
@22
#{top_tb.u_dut.ftdi_d_io[7:0]} top_tb.u_dut.ftdi_d_io[7] top_tb.u_dut.ftdi_d_io[6] top_tb.u_dut.ftdi_d_io[5] top_tb.u_dut.ftdi_d_io[4] top_tb.u_dut.ftdi_d_io[3] top_tb.u_dut.ftdi_d_io[2] top_tb.u_dut.ftdi_d_io[1] top_tb.u_dut.ftdi_d_io[0]
@28
top_tb.u_dut.ftdi_rd_o
top_tb.u_dut.u_sync.ftdi_txe_i
top_tb.u_dut.u_sync.ftdi_wr_o
@200
-
[pattern_trace] 1
[pattern_trace] 0
/testbench/top_tb.sv
0,0 → 1,405
`timescale 100ps/100ps
 
//-----------------------------------------------------------------
// Module
//-----------------------------------------------------------------
module top_tb ;
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter MAX_DELAY = 0;
 
//-----------------------------------------------------------------
// Simulation
//-----------------------------------------------------------------
`include "simulation.svh"
 
`CLOCK_GEN(clk, 100)
`RESET_GEN(rst, 100)
 
`ifdef TRACE
`TB_VCD(top_tb, "waveform.vcd")
`endif
 
`TB_RUN_FOR(10ms)
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
wire [31:0] mem_addr;
wire [31:0] mem_data_w;
wire [31:0] mem_data_r;
wire [3:0] mem_sel;
wire mem_stb;
wire mem_cyc;
wire mem_we;
wire mem_stall;
wire mem_ack;
 
reg ftdi_rxf;
reg ftdi_txe;
wire ftdi_rd;
wire ftdi_wr;
reg [7:0] ftdi_data;
 
wire [7:0] ftdi_data_io_w;
 
reg [7:0] mem[*];
 
reg [7:0] gpio_in;
wire [7:0] gpio_out;
 
//-----------------------------------------------------------------
// mem_write
//-----------------------------------------------------------------
task automatic mem_write(input [31:0] addr, input [7:0] data);
begin
mem[addr] = data;
end
endtask
 
//-----------------------------------------------------------------
// mem_read
//-----------------------------------------------------------------
task automatic mem_read(input [31:0] addr, output [7:0] data);
begin
if (mem.exists(addr))
data = mem[addr];
else
data = 8'bx;
end
endtask
//-----------------------------------------------------------------
// write_to_ftdi
//-----------------------------------------------------------------
task automatic write_to_ftdi(input [31:0] addr, input [11:0] len);
begin
integer i;
reg [7:0] data;
reg [31:0] addr_tmp;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
ftdi_rxf <= 1'b0;
ftdi_data <= {len[11:8], 4'h1}; // WRITE
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
ftdi_rxf <= 1'b0;
ftdi_data <= len[7:0]; // LEN
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
// ADDR
addr_tmp = addr;
for (i=0;i<4;i=i+1)
begin
ftdi_rxf <= 1'b0;
 
data = addr_tmp[31:24];
addr_tmp = {addr_tmp[23:0], 8'b0};
 
$display("ADDR%d: %x", i, data);
ftdi_data <= data; // DATA
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
end
 
// DATA
addr_tmp = addr;
for (i=0;i<len;i=i+1)
begin
ftdi_rxf <= 1'b0;
 
data = $urandom;
 
$display("BYTE%d: %x", i, data);
ftdi_data <= data; // DATA
 
mem_write(addr_tmp, data);
addr_tmp += 1;
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
end
end
endtask
//-----------------------------------------------------------------
// write_gp
//-----------------------------------------------------------------
task automatic write_gp(input [7:0] gp);
begin
integer i;
reg [7:0] data;
reg [31:0] addr_tmp;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
ftdi_rxf <= 1'b0;
ftdi_data <= {4'b0, 4'h3}; // GP_WR
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
ftdi_rxf <= 1'b0;
 
data = $urandom;
 
ftdi_data <= data; // DATA
 
mem_write(addr_tmp, data);
addr_tmp += 1;
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
repeat (2) @(posedge clk);
`ASSERT(gpio_out == data);
end
endtask
//-----------------------------------------------------------------
// read_gp
//-----------------------------------------------------------------
task automatic read_gp(output [7:0] gp);
begin
integer i;
reg [7:0] data;
reg [31:0] addr_tmp;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
ftdi_rxf <= 1'b0;
ftdi_data <= {4'b0, 4'h4}; // GP_RD
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
ftdi_txe <= 1'b0;
 
@(posedge ftdi_wr);
 
$display("GPIO_IN: %x", u_dut.u_sync.tx_data_q);
ftdi_txe <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
end
endtask
//-----------------------------------------------------------------
// check_mem
//-----------------------------------------------------------------
task automatic check_mem(input [31:0] addr, input [31:0] len);
begin
integer i;
reg [7:0] data;
reg [7:0] actual_data;
 
// Compare
for (i=0;i<len;i=i+1)
begin
 
mem_read(addr, data);
u_wbs.read8(addr, actual_data);
 
if (data !== actual_data)
begin
$display("Error @ %x: %x != %x", addr, data, actual_data);
$finish;
end
 
addr += 1;
 
end
end
endtask
//-----------------------------------------------------------------
// read_from_ftdi
//-----------------------------------------------------------------
task automatic read_from_ftdi(input [31:0] addr, input [11:0] len);
begin
integer i;
reg [7:0] data;
reg [31:0] addr_tmp;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
ftdi_rxf <= 1'b0;
ftdi_data <= {len[11:8], 4'h2}; // READ
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
ftdi_rxf <= 1'b0;
ftdi_data <= len[7:0]; // LEN
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
 
// ADDR
addr_tmp = addr;
for (i=0;i<4;i=i+1)
begin
ftdi_rxf <= 1'b0;
 
data = addr_tmp[31:24];
addr_tmp = {addr_tmp[23:0], 8'b0};
 
$display("ADDR%d: %x", i, data);
ftdi_data <= data; // DATA
 
@(posedge ftdi_rd);
ftdi_rxf <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
end
 
// DATA
addr_tmp = addr;
for (i=0;i<len;i=i+1)
begin
ftdi_txe <= 1'b0;
 
@(posedge ftdi_wr);
 
data = $urandom;
 
$display("READ%d: %x", i, u_dut.u_sync.tx_data_q);
// TODO: COMP
mem_write(addr_tmp, u_dut.u_sync.tx_data_q);
addr_tmp += 1;
ftdi_txe <= 1'b1;
 
repeat ($urandom_range(MAX_DELAY,0)) @(posedge clk);
end
end
endtask
 
//-----------------------------------------------------------------
// Testbench
//-----------------------------------------------------------------
initial
begin
reg [7:0] tmp;
 
ftdi_rxf = 1'b1;
ftdi_data = 8'bz;
ftdi_txe = 1'b1;
 
gpio_in = 8'h55;
 
forever
begin
repeat (10) @(posedge clk);
 
write_to_ftdi(32'h00000000, 16);
write_gp(4'ha);
write_to_ftdi(32'h00000010, 16);
 
read_gp(tmp);
`ASSERT(tmp == 8'h55);
 
repeat (100) @(posedge clk);
check_mem(32'h00000000, 32);
 
read_from_ftdi(32'h00000000, 16);
 
repeat (100) @(posedge clk);
check_mem(32'h00000000, 16);
 
write_to_ftdi(32'h00000100, 15);
repeat (100) @(posedge clk);
check_mem(32'h00000100, 15);
 
write_to_ftdi(32'h00000201, 14);
repeat (100) @(posedge clk);
check_mem(32'h00000201, 14);
 
write_to_ftdi(32'h00000001, 1);
repeat (100) @(posedge clk);
check_mem(32'h00000001, 1);
 
$finish;
end
end
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
assign ftdi_data_io_w = !ftdi_rd ? ftdi_data : 8'bz;
 
ftdi_if
u_dut
(
.clk_i(clk),
.rst_i(rst),
 
// FTDI (async FIFO interface)
.ftdi_rxf_i(ftdi_rxf),
.ftdi_txe_i(ftdi_txe),
.ftdi_siwua_o(),
.ftdi_wr_o(ftdi_wr),
.ftdi_rd_o(ftdi_rd),
.ftdi_d_io(ftdi_data_io_w),
 
// General Purpose
.gp_o(gpio_out),
.gp_i(gpio_in),
 
// Wishbone Interface
.mem_addr_o(mem_addr),
.mem_data_o(mem_data_w),
.mem_data_i(mem_data_r),
.mem_sel_o(mem_sel),
.mem_we_o(mem_we),
.mem_cyc_o(mem_cyc),
.mem_stb_o(mem_stb),
.mem_stall_i(mem_stall),
.mem_ack_i(mem_ack)
);
 
wb_slave
#(
.RANDOM_STALLS(1),
.MAX_RESP_RATE(0)
)
u_wbs
(
.clk_i(clk),
.rst_i(rst),
.addr_i(mem_addr),
.data_i(mem_data_w),
.data_o(mem_data_r),
.sel_i(mem_sel),
.cyc_i(mem_cyc),
.stb_i(mem_stb),
.cti_i(3'b111),
.we_i(mem_we),
.stall_o(mem_stall),
.ack_o(mem_ack)
);
 
endmodule
/rtl/ftdi_sync.v
0,0 → 1,277
//-----------------------------------------------------------------
// FTDI Asynchronous FIFO Interface
// V0.1
// Ultra-Embedded.com
// Copyright 2015
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for
// use in closed source commercial applications please contact me
// for details.
//-----------------------------------------------------------------
//
// This file is open source HDL; 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 2 of
// the License, or (at your option) any later version.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY 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 file; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module: ftdi_sync - Async FT245 FIFO interface
//-----------------------------------------------------------------
module ftdi_sync
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
parameter CLK_DIV = 0 // 0 - X
)
 
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
input clk_i,
input rst_i,
 
// FTDI (async FIFO interface)
input ftdi_rxf_i,
input ftdi_txe_i,
output ftdi_siwua_o,
output reg ftdi_wr_o,
output reg ftdi_rd_o,
inout [7:0] ftdi_d_io,
 
// Synchronous Interface
output [7:0] data_o,
input [7:0] data_i,
input wr_i,
input rd_i,
output wr_accept_o,
output reg rd_ready_o
);
 
//-----------------------------------------------------------------
// Defines / Local params
//-----------------------------------------------------------------
localparam STATE_W = 2;
localparam STATE_IDLE = 2'd0;
localparam STATE_TX_SETUP = 2'd1;
localparam STATE_TX = 2'd2;
localparam STATE_RX = 2'd3;
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
// Xilinx placement pragmas:
//synthesis attribute IOB of tx_data_q is "TRUE"
//synthesis attribute IOB of ftdi_rd_o is "TRUE"
//synthesis attribute IOB of ftdi_wr_o is "TRUE"
 
// Current state
reg [STATE_W-1:0] state_q;
 
reg tx_ready_q;
 
reg ftdi_rxf_ms_q;
reg ftdi_txe_ms_q;
reg ftdi_rxf_q;
reg ftdi_txe_q;
 
reg [7:0] rx_data_q;
reg [7:0] tx_data_q;
 
//-----------------------------------------------------------------
// Resample async signals
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
begin
ftdi_rxf_ms_q <= 1'b1;
ftdi_txe_ms_q <= 1'b1;
ftdi_rxf_q <= 1'b1;
ftdi_txe_q <= 1'b1;
end
else
begin
ftdi_rxf_q <= ftdi_rxf_ms_q;
ftdi_rxf_ms_q <= ftdi_rxf_i;
 
ftdi_txe_q <= ftdi_txe_ms_q;
ftdi_txe_ms_q <= ftdi_txe_i;
end
 
//-----------------------------------------------------------------
// Clock divider
//-----------------------------------------------------------------
reg [CLK_DIV:0] clk_div_q;
 
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
clk_div_q <= {1'b1, {(CLK_DIV){1'b0}}};
else if (CLK_DIV > 0)
clk_div_q <= {clk_div_q[0], clk_div_q[CLK_DIV:1]};
else
clk_div_q <= ~clk_div_q;
 
wire clk_en_w = clk_div_q[0];
 
//-----------------------------------------------------------------
// Sample flag
//-----------------------------------------------------------------
// Sample read data when both RD# and RXF# are low
wire rx_sample_w = (state_q == STATE_RX) & clk_en_w;
 
// Target accepts data when WR# and TXE# are low
wire tx_sent_w = (state_q == STATE_TX) & clk_en_w;
 
wire rx_ready_w = ~ftdi_rxf_q & clk_en_w;
wire tx_space_w = ~ftdi_txe_q & clk_en_w;
 
wire rx_start_w = (state_q == STATE_IDLE) & rx_ready_w & !rd_ready_o;
wire tx_start_w = (state_q == STATE_IDLE) & tx_space_w & tx_ready_q;
 
//-----------------------------------------------------------------
// Next State Logic
//-----------------------------------------------------------------
reg [STATE_W-1:0] next_state_r;
always @ *
begin
next_state_r = state_q;
 
case (state_q)
//-----------------------------------------
// STATE_IDLE
//-----------------------------------------
STATE_IDLE :
begin
if (rx_start_w)
next_state_r = STATE_RX;
else if (tx_start_w)
next_state_r = STATE_TX_SETUP;
end
//-----------------------------------------
// STATE_RX
//-----------------------------------------
STATE_RX :
begin
if (clk_en_w)
next_state_r = STATE_IDLE;
end
//-----------------------------------------
// STATE_TX_SETUP
//-----------------------------------------
STATE_TX_SETUP :
begin
if (clk_en_w)
next_state_r = STATE_TX;
end
//-----------------------------------------
// STATE_TX
//-----------------------------------------
STATE_TX :
begin
if (clk_en_w)
next_state_r = STATE_IDLE;
end
default:
;
endcase
end
 
// Update state
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
state_q <= STATE_IDLE;
else
state_q <= next_state_r;
 
//-----------------------------------------------------------------
// rd_ready_o
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
rd_ready_o <= 1'b0;
else if (rx_sample_w)
rd_ready_o <= 1'b1;
else if (rd_i)
rd_ready_o <= 1'b0;
 
//-----------------------------------------------------------------
// tx_ready_q
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
tx_ready_q <= 1'b0;
else if (tx_sent_w)
tx_ready_q <= 1'b0;
else if (wr_i)
tx_ready_q <= 1'b1;
 
assign wr_accept_o = !tx_ready_q;
 
//-----------------------------------------------------------------
// RD#
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
ftdi_rd_o <= 1'b1;
else if (rx_start_w)
ftdi_rd_o <= 1'b0;
else if (rx_sample_w)
ftdi_rd_o <= 1'b1;
 
//-----------------------------------------------------------------
// WR#
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
ftdi_wr_o <= 1'b1;
else if ((state_q == STATE_TX_SETUP) && clk_en_w)
ftdi_wr_o <= 1'b0;
else if (tx_sent_w)
ftdi_wr_o <= 1'b1;
 
//-----------------------------------------------------------------
// Rx Data
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
rx_data_q <= 8'b0;
else if (rx_sample_w)
rx_data_q <= ftdi_d_io;
 
//-----------------------------------------------------------------
// Tx Data
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
tx_data_q <= 8'b0;
else if (wr_i && wr_accept_o)
tx_data_q <= data_i;
 
//-----------------------------------------------------------------
// Outputs
//-----------------------------------------------------------------
 
// Tristate output
assign ftdi_d_io = (state_q == STATE_TX_SETUP || state_q == STATE_TX) ? tx_data_q : 8'hzz;
assign ftdi_siwua_o = 1'b1;
 
assign data_o = rx_data_q;
 
endmodule
/rtl/ftdi_if.v
0,0 → 1,529
//-----------------------------------------------------------------
// FTDI Asynchronous FIFO Interface
// V0.1
// Ultra-Embedded.com
// Copyright 2015
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for
// use in closed source commercial applications please contact me
// for details.
//-----------------------------------------------------------------
//
// This file is open source HDL; 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 2 of
// the License, or (at your option) any later version.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY 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 file; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module: ftdi_if - Async FT245 FIFO interface
//-----------------------------------------------------------------
module ftdi_if
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
parameter CLK_DIV = 2, // 2 - X
parameter LITTLE_ENDIAN = 1, // 0 or 1
parameter ADDR_W = 32,
parameter GP_OUTPUTS = 8, // 1 - 8
parameter GP_INPUTS = 8, // 1 - 8
parameter GP_IN_EVENT_MASK = 8'h00
)
 
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
input clk_i,
input rst_i,
 
// FTDI (async FIFO interface)
input ftdi_rxf_i,
input ftdi_txe_i,
output ftdi_siwua_o,
output ftdi_wr_o,
output ftdi_rd_o,
inout [7:0] ftdi_d_io,
 
// General Purpose IO
output [GP_OUTPUTS-1:0] gp_o,
input [GP_INPUTS-1:0] gp_i,
 
// Wishbone Interface (Master)
output [ADDR_W-1:0] mem_addr_o,
output [31:0] mem_data_o,
input [31:0] mem_data_i,
output [3:0] mem_sel_o,
output reg mem_we_o,
output reg mem_stb_o,
output mem_cyc_o,
input mem_ack_i,
input mem_stall_i
);
 
//-----------------------------------------------------------------
// Defines / Local params
//-----------------------------------------------------------------
localparam CMD_NOP = 4'd0;
localparam CMD_WR = 4'd1;
localparam CMD_RD = 4'd2;
localparam CMD_GP_WR = 4'd3;
localparam CMD_GP_RD = 4'd4;
localparam CMD_GP_RD_CLR = 4'd5;
 
`define CMD_R 3:0
`define LEN_UPPER_R 7:4
`define LEN_LOWER_R 7:0
 
localparam LEN_W = 12;
 
localparam DATA_W = 8;
 
localparam STATE_W = 4;
localparam STATE_IDLE = 4'd0;
localparam STATE_CMD = 4'd1;
localparam STATE_LEN = 4'd2;
localparam STATE_ADDR0 = 4'd3;
localparam STATE_ADDR1 = 4'd4;
localparam STATE_ADDR2 = 4'd5;
localparam STATE_ADDR3 = 4'd6;
localparam STATE_WRITE = 4'd7;
localparam STATE_READ = 4'd8;
localparam STATE_DATA0 = 4'd9;
localparam STATE_DATA1 = 4'd10;
localparam STATE_DATA2 = 4'd11;
localparam STATE_DATA3 = 4'd12;
localparam STATE_GP_WR = 4'd13;
localparam STATE_GP_RD = 4'd14;
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
// Async I/F <-> sync I/F
wire [DATA_W-1:0] data_tx_w;
wire [DATA_W-1:0] data_rx_w;
wire wr_w;
wire rd_w;
wire wr_accept_w;
wire rx_ready_w;
 
// Current state
reg [STATE_W-1:0] state_q;
 
// Transfer length (for WB read / writes)
reg [LEN_W-1:0] len_q;
 
// Mem address (some bits might be unused if ADDR_W < 32)
reg [31:0] mem_addr_q;
reg mem_cyc_q;
 
// Byte Index
reg [1:0] data_idx_q;
 
// Word storage
reg [31:0] data_q;
 
// GPIO Output Flops
reg [GP_OUTPUTS-1:0] gp_out_q;
 
// GPIO Input Flops
reg [GP_INPUTS-1:0] gp_in_q;
 
//-----------------------------------------------------------------
// Next State Logic
//-----------------------------------------------------------------
reg [STATE_W-1:0] next_state_r;
always @ *
begin
next_state_r = state_q;
 
case (state_q)
//-----------------------------------------
// STATE_IDLE
//-----------------------------------------
STATE_IDLE :
begin
if (rx_ready_w)
next_state_r = STATE_CMD;
end
//-----------------------------------------
// STATE_CMD
//-----------------------------------------
STATE_CMD :
begin
if (data_rx_w[`CMD_R] == CMD_NOP)
next_state_r = STATE_IDLE;
else if (data_rx_w[`CMD_R] == CMD_WR || data_rx_w[`CMD_R] == CMD_RD)
next_state_r = STATE_LEN;
else if (data_rx_w[`CMD_R] == CMD_GP_WR)
next_state_r = STATE_GP_WR;
else if (data_rx_w[`CMD_R] == CMD_GP_RD)
next_state_r = STATE_GP_RD;
else
next_state_r = STATE_IDLE;
end
//-----------------------------------------
// STATE_LEN
//-----------------------------------------
STATE_LEN :
begin
if (rx_ready_w)
next_state_r = STATE_ADDR0;
end
//-----------------------------------------
// STATE_ADDR
//-----------------------------------------
STATE_ADDR0 : if (rx_ready_w) next_state_r = STATE_ADDR1;
STATE_ADDR1 : if (rx_ready_w) next_state_r = STATE_ADDR2;
STATE_ADDR2 : if (rx_ready_w) next_state_r = STATE_ADDR3;
STATE_ADDR3 :
begin
if (rx_ready_w && mem_we_o)
next_state_r = STATE_WRITE;
else if (rx_ready_w)
next_state_r = STATE_READ;
end
//-----------------------------------------
// STATE_WRITE
//-----------------------------------------
STATE_WRITE :
begin
if (len_q == {LEN_W{1'b0}} && mem_ack_i)
next_state_r = STATE_IDLE;
else
next_state_r = STATE_WRITE;
end
//-----------------------------------------
// STATE_READ
//-----------------------------------------
STATE_READ :
begin
// Data ready
if (mem_ack_i)
next_state_r = STATE_DATA0;
end
//-----------------------------------------
// STATE_DATA
//-----------------------------------------
STATE_DATA0 :
begin
if (wr_accept_w)
next_state_r = STATE_DATA1;
end
STATE_DATA1 :
begin
if (wr_accept_w)
next_state_r = STATE_DATA2;
end
STATE_DATA2 :
begin
if (wr_accept_w)
next_state_r = STATE_DATA3;
end
STATE_DATA3 :
begin
if (wr_accept_w && (len_q != {LEN_W{1'b0}}))
next_state_r = STATE_READ;
else if (wr_accept_w)
next_state_r = STATE_IDLE;
end
//-----------------------------------------
// STATE_GP_WR
//-----------------------------------------
STATE_GP_WR :
begin
if (rx_ready_w)
next_state_r = STATE_IDLE;
end
//-----------------------------------------
// STATE_GP_RD
//-----------------------------------------
STATE_GP_RD :
begin
if (wr_accept_w)
next_state_r = STATE_IDLE;
end
default:
;
endcase
end
 
// Update state
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
state_q <= STATE_IDLE;
else
state_q <= next_state_r;
 
//-----------------------------------------------------------------
// Async -> Sync I/O
//-----------------------------------------------------------------
ftdi_sync
#( .CLK_DIV(CLK_DIV) )
u_sync
(
.clk_i(clk_i),
.rst_i(rst_i),
 
// FTDI (async FIFO interface)
.ftdi_rxf_i(ftdi_rxf_i),
.ftdi_txe_i(ftdi_txe_i),
.ftdi_siwua_o(ftdi_siwua_o),
.ftdi_wr_o(ftdi_wr_o),
.ftdi_rd_o(ftdi_rd_o),
.ftdi_d_io(ftdi_d_io),
 
// Synchronous Interface
.data_o(data_rx_w),
.data_i(data_tx_w),
.wr_i(wr_w),
.rd_i(rd_w),
.wr_accept_o(wr_accept_w),
.rd_ready_o(rx_ready_w)
);
 
//-----------------------------------------------------------------
// RD/WR to and from async FTDI I/F
//-----------------------------------------------------------------
 
// Write to FTDI interface in the following states
assign wr_w = (state_q == STATE_DATA0) |
(state_q == STATE_DATA1) |
(state_q == STATE_DATA2) |
(state_q == STATE_DATA3) |
(state_q == STATE_GP_RD);
 
// Accept data in the following states
assign rd_w = (state_q == STATE_CMD) |
(state_q == STATE_LEN) |
(state_q == STATE_ADDR0) |
(state_q == STATE_ADDR1) |
(state_q == STATE_ADDR2) |
(state_q == STATE_ADDR3) |
(state_q == STATE_WRITE && !mem_cyc_o) |
(state_q == STATE_GP_WR);
 
//-----------------------------------------------------------------
// Capture length
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
len_q <= {LEN_W{1'b0}};
else if (state_q == STATE_CMD && rx_ready_w)
len_q[11:8] <= data_rx_w[`LEN_UPPER_R];
else if (state_q == STATE_LEN && rx_ready_w)
len_q[7:0] <= data_rx_w[`LEN_LOWER_R];
else if (state_q == STATE_WRITE && rx_ready_w && !mem_cyc_o)
len_q <= len_q - {{(LEN_W-1){1'b0}}, 1'b1};
else if (state_q == STATE_READ && (mem_cyc_o && mem_ack_i))
len_q <= len_q - {{(LEN_W-1){1'b0}}, 1'b1};
else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && wr_accept_w)
len_q <= len_q - {{(LEN_W-1){1'b0}}, 1'b1};
 
//-----------------------------------------------------------------
// Capture addr
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
mem_addr_q <= 'd0;
else if (state_q == STATE_ADDR0 && rx_ready_w)
mem_addr_q[31:24] <= data_rx_w;
else if (state_q == STATE_ADDR1 && rx_ready_w)
mem_addr_q[23:16] <= data_rx_w;
else if (state_q == STATE_ADDR2 && rx_ready_w)
mem_addr_q[15:8] <= data_rx_w;
else if (state_q == STATE_ADDR3 && rx_ready_w)
mem_addr_q[7:0] <= data_rx_w;
// Address increment on every access issued
else if (state_q == STATE_WRITE && (mem_cyc_o && mem_ack_i))
mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4;
else if (state_q == STATE_READ && (mem_cyc_o && mem_ack_i))
mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4;
 
assign mem_addr_o = {mem_addr_q[ADDR_W-1:2], 2'b0};
 
//-----------------------------------------------------------------
// Data Index
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
data_idx_q <= 2'b0;
else if (state_q == STATE_ADDR3)
data_idx_q <= data_rx_w[1:0];
else if (state_q == STATE_WRITE && rx_ready_w && !mem_cyc_o)
data_idx_q <= data_idx_q + 2'd1;
 
//-----------------------------------------------------------------
// Data Sample
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
data_q <= 32'b0;
// In idle state, just sample GPIO inputs flops in-case of reads
else if (state_q == STATE_IDLE)
data_q <= {{(32-GP_INPUTS){1'b0}}, gp_in_q};
// Write to memory
else if (state_q == STATE_WRITE && rx_ready_w && !mem_cyc_o)
begin
if (LITTLE_ENDIAN)
begin
case (data_idx_q)
2'd0: data_q[7:0] <= data_rx_w;
2'd1: data_q[15:8] <= data_rx_w;
2'd2: data_q[23:16] <= data_rx_w;
2'd3: data_q[31:24] <= data_rx_w;
endcase
end
else
begin
case (data_idx_q)
2'd3: data_q[7:0] <= data_rx_w;
2'd2: data_q[15:8] <= data_rx_w;
2'd1: data_q[23:16] <= data_rx_w;
2'd0: data_q[31:24] <= data_rx_w;
endcase
end
end
// Read from memory
else if (state_q == STATE_READ && mem_ack_i)
begin
if (LITTLE_ENDIAN)
data_q <= mem_data_i;
else
data_q <= {mem_data_i[7:0], mem_data_i[15:8], mem_data_i[23:16], mem_data_i[31:24]};
end
// Shift data out (read response -> FTDI)
else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && wr_accept_w)
begin
data_q <= {8'b0, data_q[31:8]};
end
 
assign data_tx_w = data_q[7:0];
 
assign mem_data_o = data_q;
 
//-----------------------------------------------------------------
// Wishbone: STB
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
mem_stb_o <= 1'b0;
else if (mem_stb_o)
begin
if (!mem_stall_i)
mem_stb_o <= 1'b0;
end
// Every 4th byte, issue bus access
else if (state_q == STATE_WRITE && rx_ready_w && (data_idx_q == 2'd3 || len_q == 1))
mem_stb_o <= 1'b1;
// Read request
else if (state_q == STATE_READ && !mem_cyc_o)
mem_stb_o <= 1'b1;
 
//-----------------------------------------------------------------
// Wishbone: SEL
//-----------------------------------------------------------------
reg [3:0] mem_sel_q;
reg [3:0] mem_sel_r;
 
always @ *
begin
mem_sel_r = 4'b1111;
 
case (data_idx_q)
2'd0: mem_sel_r = 4'b0001;
2'd1: mem_sel_r = 4'b0011;
2'd2: mem_sel_r = 4'b0111;
2'd3: mem_sel_r = 4'b1111;
endcase
 
case (mem_addr_q[1:0])
2'd0: mem_sel_r = mem_sel_r & 4'b1111;
2'd1: mem_sel_r = mem_sel_r & 4'b1110;
2'd2: mem_sel_r = mem_sel_r & 4'b1100;
2'd3: mem_sel_r = mem_sel_r & 4'b1000;
endcase
end
 
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
mem_sel_q <= 4'b0;
// Idle - reset for read requests
else if (state_q == STATE_IDLE)
mem_sel_q <= 4'b1111;
// Every 4th byte, issue bus access
else if (state_q == STATE_WRITE && rx_ready_w && (data_idx_q == 2'd3 || len_q == 1))
mem_sel_q <= mem_sel_r;
 
assign mem_sel_o = LITTLE_ENDIAN ? mem_sel_q : {mem_sel_q[0], mem_sel_q[1], mem_sel_q[2], mem_sel_q[3]};
 
//-----------------------------------------------------------------
// Wishbone: WE
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
mem_we_o <= 1'b0;
else if (state_q == STATE_CMD && rx_ready_w)
mem_we_o <= (data_rx_w[`CMD_R] == CMD_WR);
 
//-----------------------------------------------------------------
// Wishbone: CYC
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i == 1'b1)
mem_cyc_q <= 1'b0;
else if (mem_stb_o)
mem_cyc_q <= 1'b1;
else if (mem_ack_i)
mem_cyc_q <= 1'b0;
 
assign mem_cyc_o = mem_stb_o | mem_cyc_q;
 
//-----------------------------------------------------------------
// General Purpose Outputs
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
gp_out_q <= {(GP_OUTPUTS){1'b0}};
else if (state_q == STATE_GP_WR && rx_ready_w)
gp_out_q <= data_rx_w[GP_OUTPUTS-1:0];
 
assign gp_o = gp_out_q;
 
//-----------------------------------------------------------------
// General Purpose Inputs
//-----------------------------------------------------------------
reg [GP_INPUTS-1:0] gp_in_r;
always @ *
begin
// GPIO inputs can be normal or pulse capture with clear on read.
// GP_IN_EVENT_MASK indicates which are 'pulse capture' ones.
if ((state_q == STATE_GP_RD) && wr_accept_w)
gp_in_r = gp_i;
else
gp_in_r = (gp_in_q & GP_IN_EVENT_MASK) | gp_i;
end
 
always @ (posedge rst_i or posedge clk_i)
if (rst_i)
gp_in_q <= {(GP_INPUTS){1'b0}};
else
gp_in_q <= gp_in_r;
 
endmodule
/sw/poke.c
0,0 → 1,77
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define DEFAULT_FTDI_IFACE 1
 
//-----------------------------------------------------------------
// main:
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
int err = 0;
int c;
int help = 0;
int ftdi_iface = DEFAULT_FTDI_IFACE;
uint32_t addr = 0xFFFFFFFF;
uint32_t value = 0;
int quiet = 0;
 
while ((c = getopt (argc, argv, "a:v:i:q")) != -1)
{
switch(c)
{
case 'a':
addr = (uint32_t)strtoul(optarg, NULL, 0);
break;
case 'v':
value = (uint32_t)strtoul(optarg, NULL, 0);
break;
case 'i':
ftdi_iface = (int)strtol(optarg, NULL, 0);
break;
case 'q':
quiet = 1;
break;
default:
help = 1;
break;
}
}
 
if (help || addr == 0xFFFFFFFF)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-a 0xNNNNNNNN = Address to write\n");
fprintf (stderr,"-v 0xNNNNNNNN = Data to write\n");
fprintf (stderr,"-i id = FTDI interface ID (0 = A, 1 = B)\n");
fprintf (stderr,"-q = Quiet mode\n");
exit(-1);
}
 
// Try and communicate with FTDI interface
if (ftdi_hw_init(ftdi_iface) != 0)
{
fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing / check connection\n");
exit(-2);
}
 
if (!quiet)
printf("Write 0x%x to 0x%x\n", value, addr);
 
if (ftdi_hw_mem_write_word(addr, value) != sizeof(value))
{
fprintf(stderr, "ERROR: Could not write to device\n");
err = 1;
}
 
ftdi_hw_close();
 
return err;
}
/sw/load.c
0,0 → 1,170
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define CHUNK_SIZE 256
#define DEFAULT_FTDI_IFACE 1
 
//-----------------------------------------------------------------
// load_file_to_mem
//-----------------------------------------------------------------
static uint8_t* load_file_to_mem(const char *filename, long size_override, int *pSize)
{
uint8_t *buf = NULL;
FILE *f = fopen(filename, "rb");
 
*pSize = 0;
 
if (f)
{
long size;
 
// Get size of file
fseek(f, 0, SEEK_END);
size = ftell(f);
rewind(f);
 
// User overriden file size
if (size_override >= 0)
{
if (size > size_override)
size = size_override;
}
 
buf = (uint8_t*)malloc(size);
if (buf)
{
// Read file data into allocated memory
int len = fread(buf, 1, size, f);
if (len != size)
{
free(buf);
buf = NULL;
}
else
*pSize = size;
}
fclose(f);
}
 
return buf;
}
//-----------------------------------------------------------------
// upload
//-----------------------------------------------------------------
static int upload(uint32_t addr, uint8_t *buf, int length)
{
int err = 0;
int i;
int size;
for (i=0;i<length;i+=CHUNK_SIZE)
{
size = (length - i);
if (size > CHUNK_SIZE)
size = CHUNK_SIZE;
 
if (ftdi_hw_mem_write(addr, buf, size) != size)
{
fprintf(stderr, "Upload: Error uploading file\n");
err = 1;
break;
}
 
addr += CHUNK_SIZE;
buf += CHUNK_SIZE;
 
printf("\r%d%%", (i * 100) / length);
fflush(stdout);
}
 
return err;
}
//-----------------------------------------------------------------
// main
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
int c;
long size_override = -1;
char *filename = NULL;
int help = 0;
int err = 1;
int size;
uint32_t address = 0x0;
uint8_t *buf;
int ftdi_iface = DEFAULT_FTDI_IFACE;
 
while ((c = getopt (argc, argv, "f:s:a:i:")) != -1)
{
switch(c)
{
case 'f':
filename = optarg;
break;
case 's':
size_override = strtol(optarg, NULL, 0);
break;
case 'a':
address = strtoul(optarg, NULL, 0);
break;
case 'i':
ftdi_iface = (int)strtol(optarg, NULL, 0);
break;
default:
help = 1;
break;
}
}
 
if (help || filename == NULL)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-f filename.bin = Executable to load (binary)\n");
fprintf (stderr,"-a 0xnnnn = Address to load to (default to 0x0)\n");
fprintf (stderr,"-i id = FTDI interface ID (0 = A, 1 = B)\n");
fprintf (stderr,"-s 0xnnnn = Size override\n");
exit(-1);
}
 
// Try and communicate with FTDI interface
if (ftdi_hw_init(ftdi_iface) != 0)
{
fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing / check connection\n");
exit(-2);
}
 
// Read file into memory
buf = load_file_to_mem(filename, size_override, &size);
if (buf)
{
printf("Loading %s (%dKB) to 0x%x:\n", filename, (size + 1023) / 1024, address);
 
// Upload file to target
err = upload(address, buf, size);
 
// Free file memory
free(buf);
buf = NULL;
 
if (!err)
printf("\rDone!\n");
else
printf("\rFailed!\n");
}
else
{
fprintf (stderr,"Error: Could not open image\n");
err = 1;
}
 
ftdi_hw_close();
 
return err;
}
/sw/makefile.mk
0,0 → 1,31
###############################################################################
## Makefile
###############################################################################
 
# Target
TARGET ?= test
 
# Options
CFLAGS = -g
LDFLAGS =
LIBS = -lftdi
 
# Source Files
OBJ = ftdi_hw.o $(TARGET).o
 
###############################################################################
# Rules
###############################################################################
all: $(TARGET)
clean:
-rm *.o $(TARGET)
 
%.o : %.c
gcc -c $(CFLAGS) $< -o $@
 
%.o : %.cpp
g++ -c $(CFLAGS) $< -o $@
 
$(TARGET): $(OBJ)
g++ $(LDFLAGS) $(OBJ) $(LIBS) -o $@
/sw/peek.c
0,0 → 1,76
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define DEFAULT_FTDI_IFACE 1
 
//-----------------------------------------------------------------
// main:
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
int err = 0;
int c;
int help = 0;
int ftdi_iface = DEFAULT_FTDI_IFACE;
uint32_t addr = 0xFFFFFFFF;
uint32_t value = 0;
int quiet = 0;
 
while ((c = getopt (argc, argv, "a:i:q")) != -1)
{
switch(c)
{
case 'a':
addr = (uint32_t)strtoul(optarg, NULL, 0);
break;
case 'i':
ftdi_iface = (int)strtol(optarg, NULL, 0);
break;
case 'q':
quiet = 1;
break;
default:
help = 1;
break;
}
}
 
if (help || addr == 0xFFFFFFFF)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-a 0xNNNNNNNN = Address to read\n");
fprintf (stderr,"-i id = FTDI interface ID (0 = A, 1 = B)\n");
fprintf (stderr,"-q = Quiet mode (data returned via return value)\n");
exit(-1);
}
 
// Try and communicate with FTDI interface
if (ftdi_hw_init(ftdi_iface) != 0)
{
fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing / check connection\n");
exit(-2);
}
 
if (ftdi_hw_mem_read_word(addr, &value) != sizeof(value))
{
fprintf(stderr, "ERROR: Could not read from device\n");
err = 1;
}
 
if (!quiet)
{
printf("Read 0x%x from 0x%x\n", value, addr);
value = 0;
}
 
ftdi_hw_close();
 
return err ? -1 : value;
}
/sw/ftdi_hw.c
0,0 → 1,275
#include <stdio.h>
#include <ftdi.h>
 
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define CMD_NOP 0x0
#define CMD_WR 0x1
#define CMD_RD 0x2
#define CMD_GP_WR 0x3
#define CMD_GP_RD 0x4
 
#define MAX_TX_SIZE 2048
#define HDR_SIZE 6
 
#define FTDI_PID 0x0403
#define FTDI_VID 0x6010
 
//-----------------------------------------------------------------
// Locals:
//-----------------------------------------------------------------
static struct ftdi_context *_handle;
 
//-----------------------------------------------------------------
// ftdi_hw_init:
//-----------------------------------------------------------------
int ftdi_hw_init(int interface)
{
int status;
 
_handle = ftdi_new();
if (!_handle)
return -1;
 
// Open channel
ftdi_set_interface(_handle, interface ? INTERFACE_B : INTERFACE_A);
status = ftdi_usb_open(_handle, FTDI_PID, FTDI_VID);
if (status != 0)
{
ftdi_free(_handle);
_handle = NULL;
return -1;
}
 
// Reset FTDI
status = ftdi_usb_reset(_handle);
if (status != 0)
{
ftdi_usb_close(_handle);
ftdi_free(_handle);
_handle = NULL;
return -1;
}
 
// Flush buffers
status = ftdi_usb_purge_buffers(_handle);
if (status != 0)
{
ftdi_usb_close(_handle);
ftdi_free(_handle);
_handle = NULL;
return -1;
}
 
// Set transfer mode
status = ftdi_set_bitmode(_handle, 0xFF, BITMODE_RESET);
if (status != 0)
{
ftdi_usb_close(_handle);
ftdi_free(_handle);
_handle = NULL;
return -1;
}
 
return 0;
}
//-----------------------------------------------------------------
// ftdi_hw_close:
//-----------------------------------------------------------------
int ftdi_hw_close(void)
{
if (_handle)
{
ftdi_usb_close(_handle);
ftdi_free(_handle);
_handle = NULL;
}
 
return 0;
}
//-----------------------------------------------------------------
// ftdi_hw_mem_write:
//-----------------------------------------------------------------
int ftdi_hw_mem_write(uint32_t addr, uint8_t *data, int length)
{
int i;
int sent = 0;
int size = length;
int res;
uint8_t buffer[MAX_TX_SIZE + HDR_SIZE];
uint8_t *p;
 
while (sent < length)
{
size = (length - sent);
if (size > MAX_TX_SIZE)
size = MAX_TX_SIZE;
 
// Build packet header
p = buffer;
*p++ = (((size >> 8) & 0xF) << 4) | CMD_WR;
*p++ = (size & 0xFF);
 
*p++ = (addr >> 24);
*p++ = (addr >> 16);
*p++ = (addr >> 8);
*p++ = (addr >> 0);
 
// Fill packet payload
for (i=0;i<size;i++)
*p++ = *data++;
 
// Write request + data to FTDI device
res = ftdi_write_data(_handle, buffer, (size + HDR_SIZE));
if (res != (size + HDR_SIZE))
{
fprintf(stderr, "ftdi_hw_mem_write: Failed to send\n");
return -1;
}
 
sent += size;
addr += size;
}
 
return sent;
}
//-----------------------------------------------------------------
// ftdi_hw_mem_read:
//-----------------------------------------------------------------
int ftdi_hw_mem_read(uint32_t addr, uint8_t *data, int length)
{
int i;
int received = 0;
int size = length;
int remain;
int res;
uint8_t buffer[HDR_SIZE];
uint8_t *p;
 
while (received < length)
{
size = (length - received);
if (size > MAX_TX_SIZE)
size = MAX_TX_SIZE;
 
// Round up to nearest 4 byte multiple
size = (size + 3) & ~3;
 
// Build packet header
p = buffer;
*p++ = (((size >> 8) & 0xF) << 4) | CMD_RD;
*p++ = (size & 0xFF);
 
*p++ = (addr >> 24);
*p++ = (addr >> 16);
*p++ = (addr >> 8);
*p++ = (addr >> 0);
 
// Write request to FTDI device
res = ftdi_write_data(_handle, buffer, HDR_SIZE);
if (res != HDR_SIZE)
{
fprintf(stderr, "ftdi_hw_mem_read: Failed to send request\n");
return -1;
}
 
remain = size;
do
{
res = ftdi_read_data(_handle, data, remain);
if (res < 0)
{
fprintf(stderr, "ftdi_hw_mem_read: Failed to read data\n");
return -1;
}
 
remain -= res;
data += res;
}
while (remain > 0);
 
received += size;
addr += size;
}
 
return received;
}
//-----------------------------------------------------------------
// ftdi_hw_mem_write_word:
//-----------------------------------------------------------------
int ftdi_hw_mem_write_word(uint32_t addr, uint32_t data)
{
uint8_t buffer[4];
 
buffer[3] = (data >> 24);
buffer[2] = (data >> 16);
buffer[1] = (data >> 8);
buffer[0] = (data >> 0);
 
return ftdi_hw_mem_write(addr, buffer, 4);
}
//-----------------------------------------------------------------
// ftdi_hw_mem_read_word:
//-----------------------------------------------------------------
int ftdi_hw_mem_read_word(uint32_t addr, uint32_t *data)
{
uint8_t buffer[4];
 
int res = ftdi_hw_mem_read(addr, buffer, 4);
if (res > 0)
{
(*data) = ((uint32_t)buffer[3]) << 24;
(*data)|= ((uint32_t)buffer[2]) << 16;
(*data)|= ((uint32_t)buffer[1]) << 8;
(*data)|= ((uint32_t)buffer[0]) << 0;
}
return res;
}
//-----------------------------------------------------------------
// ftdi_hw_gpio_write:
//-----------------------------------------------------------------
int ftdi_hw_gpio_write(uint8_t value)
{
uint8_t buffer[2] = { CMD_GP_WR, value };
 
// Write request to FTDI device
int res = ftdi_write_data(_handle, buffer, sizeof(buffer));
if (res != sizeof(buffer))
{
fprintf(stderr, "ftdi_hw_mem_write: Failed to send\n");
return -1;
}
 
return 0;
}
//-----------------------------------------------------------------
// ftdi_hw_gpio_read:
//-----------------------------------------------------------------
int ftdi_hw_gpio_read(uint8_t *value)
{
// Write request to FTDI device
uint8_t request = CMD_GP_RD;
int res = ftdi_write_data(_handle, &request, 1);
if (res != 1)
{
fprintf(stderr, "ftdi_hw_mem_write: Failed to send\n");
return -1;
}
 
// Poll for response
do
{
res = ftdi_read_data(_handle, value, 1);
if (res < 0)
{
fprintf(stderr, "ftdi_hw_mem_read: Failed to read data\n");
return -1;
}
}
while (res != 1);
 
return 0;
}
/sw/verify.c
0,0 → 1,184
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define CHUNK_SIZE 256
#define DEFAULT_FTDI_IFACE 1
 
//-----------------------------------------------------------------
// load_file_to_mem
//-----------------------------------------------------------------
static uint8_t* load_file_to_mem(const char *filename, long size_override, int *pSize)
{
uint8_t *buf = NULL;
FILE *f = fopen(filename, "rb");
 
*pSize = 0;
 
if (f)
{
long size;
 
// Get size of file
fseek(f, 0, SEEK_END);
size = ftell(f);
rewind(f);
 
// User overriden file size
if (size_override >= 0)
{
if (size > size_override)
size = size_override;
}
 
buf = (uint8_t*)malloc(size);
if (buf)
{
// Read file data into allocated memory
int len = fread(buf, 1, size, f);
if (len != size)
{
free(buf);
buf = NULL;
}
else
*pSize = size;
}
fclose(f);
}
 
return buf;
}
//-----------------------------------------------------------------
// compare
//-----------------------------------------------------------------
static int compare(uint32_t addr, uint8_t *data, int length)
{
uint8_t buf[CHUNK_SIZE];
int res = 1;
int i;
int size;
for (i=0;i<length;i+=CHUNK_SIZE)
{
size = (length - i);
if (size > CHUNK_SIZE)
size = CHUNK_SIZE;
 
if (ftdi_hw_mem_read(addr, buf, size) != size)
{
fprintf(stderr, "Compare: Error downloading file\n");
res = -1;
break;
}
 
// Check for differences
if (memcmp(data, buf, size) != 0)
{
res = 0;
break;
}
 
addr += CHUNK_SIZE;
data += CHUNK_SIZE;
 
printf("\r%d%%", (i * 100) / length);
fflush(stdout);
}
 
return res;
}
//-----------------------------------------------------------------
// main
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
int c;
long size_override = -1;
char *filename = NULL;
int help = 0;
int err = 1;
int res;
int size;
uint32_t address = 0x0;
uint8_t *buf;
int ftdi_iface = DEFAULT_FTDI_IFACE;
 
while ((c = getopt (argc, argv, "f:s:a:i:")) != -1)
{
switch(c)
{
case 'f':
filename = optarg;
break;
case 's':
size_override = strtol(optarg, NULL, 0);
break;
case 'a':
address = strtoul(optarg, NULL, 0);
break;
case 'i':
ftdi_iface = (int)strtol(optarg, NULL, 0);
break;
default:
help = 1;
break;
}
}
 
if (help || filename == NULL)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-f filename.bin = Executable to compare (binary)\n");
fprintf (stderr,"-a 0xnnnn = Address to compare to (default to 0x0)\n");
fprintf (stderr,"-i id = FTDI interface ID (0 = A, 1 = B)\n");
fprintf (stderr,"-s 0xnnnn = Size override\n");
exit(-1);
}
 
// Try and communicate with FTDI interface
if (ftdi_hw_init(ftdi_iface) != 0)
{
fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing / check connection\n");
exit(-2);
}
 
// Read file into memory
buf = load_file_to_mem(filename, size_override, &size);
if (buf)
{
printf("Comparing %s (%dKB) to 0x%x:\n", filename, (size + 1023) / 1024, address);
 
// Upload file to target
res = compare(address, buf, size);
 
// Free file memory
free(buf);
buf = NULL;
 
if (res == 1)
printf("\nMatches!\n");
else if (res == 0)
printf("\nDiffers!\n");
else
{
printf("\n");
err = 1;
}
}
else
{
fprintf (stderr,"Error: Could not open image\n");
err = 1;
}
 
ftdi_hw_close();
 
return err;
}
/sw/sdram_test.c
0,0 → 1,147
#include <stdio.h>
#include <sys/time.h>
 
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define DEFAULT_FTDI_IFACE 1
#define BLOCK_SIZE 2048
 
#define MEM_SIZE ((32 * 1024) / 4)
 
static uint32_t mem[MEM_SIZE];
 
//-----------------------------------------------------------------
// main
//-----------------------------------------------------------------
int main(void)
{
uint32_t buffer[BLOCK_SIZE/4];
uint32_t req;
uint32_t resp;
uint32_t addr;
uint8_t gpio;
struct timeval t1, t2;
double elapsedTime;
int res;
int i;
 
if (ftdi_hw_init(DEFAULT_FTDI_IFACE) != 0)
{
fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing\n");
return 0;
}
 
addr = 0x00000000;
req = 0x12345678;
ftdi_hw_mem_write_word(addr, req);
ftdi_hw_mem_read_word(addr, &resp);
 
if (req != resp)
{
printf("ERR0: %x != %x\n", req, resp);
}
 
addr = 0x00000004;
req = 0xcafebabe;
ftdi_hw_mem_write_word(addr, req);
ftdi_hw_mem_read_word(addr, &resp);
 
if (req != resp)
{
printf("ERR1: %x != %x\n", req, resp);
}
 
addr = 0x00000000;
req = 0x12345678;
ftdi_hw_mem_read_word(addr, &resp);
 
if (req != resp)
{
printf("ERR2: %x != %x\n", req, resp);
}
 
for (i=0;i<MEM_SIZE;i++)
mem[i] = 0;
 
printf("Erasing memory\n");
ftdi_hw_mem_write(0, (uint8_t*)mem, MEM_SIZE);
printf("Erasing memory - done\n");
 
// Start timer
gettimeofday(&t1, NULL);
 
int sent = 0;
while (1)
{
// SINGLE
if (rand() & 1)
{
addr = rand() & ((MEM_SIZE * 4) - 1);
addr &= ~3;
 
req = rand();
 
ftdi_hw_mem_write(addr, (uint8_t*)&req, 4);
ftdi_hw_mem_read(addr, (uint8_t*)&resp, 4);
sent += 4;
 
if (req != resp)
{
printf("ERR (RB): %x - %x != %x\n", addr, req, resp);
}
 
mem[addr/4] = req;
addr = rand() & (MEM_SIZE - 1);
addr &= ~3;
 
ftdi_hw_mem_read(addr, (uint8_t*)&resp, 4);
sent += (4 * 3);
 
if (mem[addr/4] != resp)
{
printf("ERR (MEM): %x - %x != %x\n", addr, mem[addr/4], resp);
}
}
// BLOCK
else
{
addr = rand() & ((MEM_SIZE * 4) - 1);
addr &= ~3;
 
// Stop block from overflowing RAM
if (addr > ((MEM_SIZE * 4) - BLOCK_SIZE))
addr = ((MEM_SIZE * 4) - BLOCK_SIZE);
 
for (i=0;i<BLOCK_SIZE / 4;i++)
{
buffer[i] = rand();
mem[(addr/4)+i] = buffer[i];
}
 
// Write block
ftdi_hw_mem_write(addr, (uint8_t*)&buffer, BLOCK_SIZE);
sent += BLOCK_SIZE;
}
 
// Stop timer
gettimeofday(&t2, NULL);
 
elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms
elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms
 
if (((int)elapsedTime) >= 1000)
{
printf("%dKB/s\n", sent / 1024);
 
gettimeofday(&t1, NULL);
sent = 0;
}
}
 
ftdi_hw_close();
return 0;
}
/sw/dump.c
0,0 → 1,130
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define CHUNK_SIZE 256
#define DEFAULT_FTDI_IFACE 1
 
//-----------------------------------------------------------------
// download
//-----------------------------------------------------------------
static int download(FILE *f, uint32_t addr, int length)
{
uint8_t buf[CHUNK_SIZE];
int err = 0;
int i;
int size;
for (i=0;i<length;i+=CHUNK_SIZE)
{
size = (length - i);
if (size > CHUNK_SIZE)
size = CHUNK_SIZE;
 
if (ftdi_hw_mem_read(addr, buf, size) != size)
{
fprintf(stderr, "Download: Error downloading file\n");
err = 1;
break;
}
 
if (fwrite(buf, 1, size, f) != size)
{
fprintf(stderr, "Download: Error writing file\n");
err = 1;
break;
}
 
addr += CHUNK_SIZE;
 
printf("\r%d%%", (i * 100) / length);
fflush(stdout);
}
 
return err;
}
//-----------------------------------------------------------------
// main
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
int c;
int size = -1;
char *filename = NULL;
int help = 0;
int err = 1;
uint32_t address = 0x0;
int ftdi_iface = DEFAULT_FTDI_IFACE;
FILE *f = NULL;
 
while ((c = getopt (argc, argv, "o:s:a:i:")) != -1)
{
switch(c)
{
case 'o':
filename = optarg;
break;
case 's':
size = (int)strtol(optarg, NULL, 0);
break;
case 'a':
address = strtoul(optarg, NULL, 0);
break;
case 'i':
ftdi_iface = (int)strtol(optarg, NULL, 0);
break;
default:
help = 1;
break;
}
}
 
if (help || filename == NULL || size < 0)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-o filename.bin = Output filename\n");
fprintf (stderr,"-s n = Size to dump\n");
fprintf (stderr,"-a 0xnnnn = Address to dump from (default to 0x0)\n");
fprintf (stderr,"-i id = FTDI interface ID (0 = A, 1 = B)\n");
exit(-1);
}
 
// Try and communicate with FTDI interface
if (ftdi_hw_init(ftdi_iface) != 0)
{
fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing / check connection\n");
exit(-2);
}
 
// Try and create new file
f = fopen(filename, "wb");
if (f)
{
printf("Downloading %s (%dKB) from 0x%x:\n", filename, (size + 1023) / 1024, address);
 
err = download(f, address, size);
 
if (!err)
printf("\rDone!\n");
else
printf("\rFailed!\n");
 
fclose(f);
f = NULL;
}
else
{
fprintf (stderr,"Error: Could not create file\n");
err = 1;
}
 
ftdi_hw_close();
 
return err;
}
/sw/gpio_write.c
0,0 → 1,72
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define DEFAULT_FTDI_IFACE 1
 
//-----------------------------------------------------------------
// main:
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
int err = 0;
int c;
int help = 0;
int ftdi_iface = DEFAULT_FTDI_IFACE;
uint8_t value = 0;
int quiet = 0;
 
while ((c = getopt (argc, argv, "v:i:q")) != -1)
{
switch(c)
{
case 'v':
value = (uint8_t)strtoul(optarg, NULL, 0);
break;
case 'i':
ftdi_iface = (int)strtol(optarg, NULL, 0);
break;
case 'q':
quiet = 1;
break;
default:
help = 1;
break;
}
}
 
if (help)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-v 0xNN = Data to write\n");
fprintf (stderr,"-i id = FTDI interface ID (0 = A, 1 = B)\n");
fprintf (stderr,"-q = Quiet mode\n");
exit(-1);
}
 
// Try and communicate with FTDI interface
if (ftdi_hw_init(ftdi_iface) != 0)
{
fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing / check connection\n");
exit(-2);
}
 
if (!quiet)
printf("Write 0x%x to GPIO\n", value);
 
if (ftdi_hw_gpio_write(value) != 0)
{
fprintf(stderr, "ERROR: Could not write to device\n");
err = 1;
}
 
ftdi_hw_close();
 
return err;
}
/sw/gpio_read.c
0,0 → 1,72
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ftdi_hw.h"
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
#define DEFAULT_FTDI_IFACE 1
 
//-----------------------------------------------------------------
// main:
//-----------------------------------------------------------------
int main(int argc, char *argv[])
{
int err = 0;
int c;
int help = 0;
int ftdi_iface = DEFAULT_FTDI_IFACE;
uint8_t value = 0;
int quiet = 0;
 
while ((c = getopt (argc, argv, "i:q")) != -1)
{
switch(c)
{
case 'i':
ftdi_iface = (int)strtol(optarg, NULL, 0);
break;
case 'q':
quiet = 1;
break;
default:
help = 1;
break;
}
}
 
if (help)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-v 0xNN = Data to write\n");
fprintf (stderr,"-i id = FTDI interface ID (0 = A, 1 = B)\n");
fprintf (stderr,"-q = Quiet mode (data returned via return value)\n");
exit(-1);
}
 
// Try and communicate with FTDI interface
if (ftdi_hw_init(ftdi_iface) != 0)
{
fprintf(stderr, "ERROR: Could not open FTDI interface, try SUDOing / check connection\n");
exit(-2);
}
 
if (ftdi_hw_gpio_read(&value) != 0)
{
fprintf(stderr, "ERROR: Could not read from device\n");
err = 1;
}
 
if (!quiet)
{
printf("Read 0x%x from GPIO\n", value);
value = 0;
}
 
ftdi_hw_close();
 
return err ? -1 : value;
}
/sw/ftdi_hw.h
0,0 → 1,26
#ifndef _FTDI_HW_H_
#define _FTDI_HW_H_
 
#include <stdint.h>
 
//-----------------------------------------------------------------
// Defines:
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Prototypes:
//-----------------------------------------------------------------
int ftdi_hw_init(int interface);
int ftdi_hw_close(void);
 
// Memory Access
int ftdi_hw_mem_write(uint32_t addr, uint8_t *data, int length);
int ftdi_hw_mem_read(uint32_t addr, uint8_t *data, int length);
int ftdi_hw_mem_write_word(uint32_t addr, uint32_t data);
int ftdi_hw_mem_read_word(uint32_t addr, uint32_t *data);
 
// GPIO
int ftdi_hw_gpio_write(uint8_t value);
int ftdi_hw_gpio_read(uint8_t *value);
 
#endif
/sw/makefile
0,0 → 1,23
###############################################################################
# Rules
###############################################################################
all:
make -f makefile.mk TARGET=load
make -f makefile.mk TARGET=peek
make -f makefile.mk TARGET=poke
make -f makefile.mk TARGET=dump
make -f makefile.mk TARGET=verify
make -f makefile.mk TARGET=gpio_read
make -f makefile.mk TARGET=gpio_write
make -f makefile.mk TARGET=sdram_test
 
clean:
make -f makefile.mk TARGET=load clean
make -f makefile.mk TARGET=peek clean
make -f makefile.mk TARGET=poke clean
make -f makefile.mk TARGET=dump clean
make -f makefile.mk TARGET=verify clean
make -f makefile.mk TARGET=gpio_read clean
make -f makefile.mk TARGET=gpio_write clean
make -f makefile.mk TARGET=sdram_test clean
 

powered by: WebSVN 2.1.0

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