1 |
2 |
ZTEX |
/*%
|
2 |
|
|
Common communication interface of default firmwares
|
3 |
|
|
Copyright (C) 2009-2017 ZTEX GmbH.
|
4 |
|
|
http://www.ztex.de
|
5 |
|
|
|
6 |
|
|
Copyright and related rights are licensed under the Solderpad Hardware
|
7 |
|
|
License, Version 0.51 (the "License"); you may not use this file except
|
8 |
|
|
in compliance with the License. You may obtain a copy of the License at
|
9 |
|
|
|
10 |
|
|
http://solderpad.org/licenses/SHL-0.51.
|
11 |
|
|
|
12 |
|
|
Unless required by applicable law or agreed to in writing, software, hardware
|
13 |
|
|
and materials distributed under this License is distributed on an "AS IS"
|
14 |
|
|
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
15 |
|
|
implied. See the License for the specific language governing permissions
|
16 |
|
|
and limitations under the License.
|
17 |
|
|
%*/
|
18 |
|
|
/*
|
19 |
|
|
Implements the low speed interface of default firmwares.
|
20 |
|
|
|
21 |
|
|
It allows easy-to-use low speed communication with a SRAM-like
|
22 |
|
|
interface (32 bit width, 8 bit address). For example it can be used
|
23 |
|
|
to transfer things like settings and debug data.
|
24 |
|
|
*/
|
25 |
|
|
|
26 |
|
|
module ezusb_lsi (
|
27 |
|
|
// control signals
|
28 |
|
|
input clk, // at least 20MHz
|
29 |
|
|
input reset_in, // high-active asynchronous reset
|
30 |
|
|
output reg reset = 1'b1, // synchronous reset output
|
31 |
|
|
// hardware pins
|
32 |
|
|
input data_clk, // all action happens if this signal changes (both edges)
|
33 |
|
|
inout data, // data in and out, LSB transmitted first
|
34 |
|
|
input stop, // defines how data is processed at data_clk change:
|
35 |
|
|
// * if low: data is read and shifted into a read buffer
|
36 |
|
|
// * if high while data is low: data is written to the user application (on FPGA): last 8 bits are the address, preceding 32bit are the data
|
37 |
|
|
// * if high while data is high: write-to-host sequence is started and remains active until stop goes low, last 8 bits are the address:
|
38 |
|
|
// 1. continuously read out_data (user data, see below) and write first bit to host until data_clk changes
|
39 |
|
|
// 2..n. shift next bit to host and wait until data_clk changes, repeated this until stop goes low
|
40 |
|
|
// user interface
|
41 |
|
|
output reg [7:0] in_addr, // input address
|
42 |
|
|
output reg [31:0] in_data, // input data
|
43 |
|
|
output reg in_strobe = 1'b0, // 1 indicates new data received (1 for one cycle)
|
44 |
|
|
output reg in_valid = 1'b0, // 1 if date is valid
|
45 |
|
|
output reg [7:0] out_addr, // output address
|
46 |
|
|
input [31:0] out_data, // output data
|
47 |
|
|
output reg out_strobe = 1'b0 // 1 indicates new data request (1 for one cycle)
|
48 |
|
|
);
|
49 |
|
|
|
50 |
|
|
reg [39:0] read_reg;
|
51 |
|
|
reg [31:0] write_reg;
|
52 |
|
|
reg [2:0] data_clk_buf;
|
53 |
|
|
reg dir = 0; // 0 : read
|
54 |
|
|
reg do_write = 0;
|
55 |
|
|
|
56 |
|
|
assign data = dir && (!write_reg[0]) ? 1'b0 : 1'bz;
|
57 |
|
|
|
58 |
|
|
// wire data_clk_edge = ( (data_clk==data_clk_buf[0]) && (data_clk==data_clk_buf[1]) && (data_clk!=data_clk_buf[2]) );
|
59 |
|
|
wire data_clk_edge = ( (data_clk_buf[0]!=data_clk_buf[1]) && (data_clk_buf[1]==data_clk_buf[2]) );
|
60 |
|
|
|
61 |
|
|
|
62 |
|
|
always @ (posedge clk)
|
63 |
|
|
begin
|
64 |
|
|
reset <= reset_in;
|
65 |
|
|
data_clk_buf <= { data_clk_buf[1:0], data_clk };
|
66 |
|
|
in_strobe <= (!reset) && data_clk_edge && (!dir) && stop && (!data);
|
67 |
|
|
out_strobe <= (!reset) && data_clk_edge && (!dir) && stop && data;
|
68 |
|
|
dir <= (!reset) && stop && ((data_clk_edge && data) || dir);
|
69 |
|
|
if ( reset )
|
70 |
|
|
begin
|
71 |
|
|
in_valid <= 1'b0;
|
72 |
|
|
do_write <= 1'b0;
|
73 |
|
|
end else if ( data_clk_edge )
|
74 |
|
|
begin
|
75 |
|
|
if ( !dir ) // read from fx3
|
76 |
|
|
begin
|
77 |
|
|
if ( stop )
|
78 |
|
|
begin
|
79 |
|
|
if ( data ) // last 8 bit contain write address
|
80 |
|
|
begin
|
81 |
|
|
// dir <= 1'b1;
|
82 |
|
|
out_addr <= read_reg[39:32];
|
83 |
|
|
do_write <= 1'b1;
|
84 |
|
|
end else
|
85 |
|
|
begin
|
86 |
|
|
in_valid <= 1'b1;
|
87 |
|
|
in_addr <= read_reg[39:32];
|
88 |
|
|
in_data <= read_reg[31:0];
|
89 |
|
|
end
|
90 |
|
|
end else
|
91 |
|
|
begin
|
92 |
|
|
read_reg <= { data, read_reg[39:1] };
|
93 |
|
|
end
|
94 |
|
|
end else // write to fx3
|
95 |
|
|
begin
|
96 |
|
|
write_reg[30:0] <= write_reg[31:1]; // shift next bit to host
|
97 |
|
|
do_write <= 1'b0;
|
98 |
|
|
// dir <= stop;
|
99 |
|
|
end
|
100 |
|
|
end else if ( dir && do_write ) // write the first bit to host
|
101 |
|
|
begin
|
102 |
|
|
write_reg <= out_data;
|
103 |
|
|
end
|
104 |
|
|
end
|
105 |
|
|
endmodule
|