cc0ba8ed7ca1bbbfd3186477f343320470581061
[mw/milkymist.git] / cores / bt656cap / rtl / bt656cap_dma.v
1 /*
2  * Milkymist VJ SoC
3  * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 module bt656cap_dma #(
19         input fml_depth = 27
20 ) (
21         input sys_clk,
22         input sys_rst,
23
24         /* To/from control interface */
25         input [1:0] field_filter,
26         output reg in_frame,
27         input [fml_depth-1-5:0] fml_adr_base,
28         output start_of_frame,
29         output reg next_burst,
30         input last_burst,
31
32         /* From video input module. */
33         input v_stb,
34         output reg v_ack,
35         input v_field,
36         input [31:0] v_rgb565,
37
38         /* FML interface. fml_we=1 is assumed. */
39         output [fml_depth-1:0] fml_adr,
40         output reg fml_stb,
41         input fml_ack,
42         output [63:0] fml_do
43 );
44
45 /* Data buffer */
46 reg data_en;
47 reg [2:0] v_bcount;
48 reg burst_7;
49 always @(posedge sys_clk) begin
50         if(sys_rst)
51                 v_bcount <= 3'd0;
52         else if(v_stb & v_ack & data_en) begin
53                 v_bcount <= v_bcount + 3'd1;
54                 burst_7 <= v_bcount == 3'd6;
55         end
56 end
57
58 reg [1:0] f_bcount;
59
60 bt656cap_burstmem burstmem(
61         .sys_clk(sys_clk),
62
63         .we(v_stb & v_ack & data_en),
64         .wa(v_bcount),
65         .wd(v_rgb565),
66
67         .ra(f_bcount),
68         .rd(fml_do)
69 );
70
71 /* FML address generator */
72 reg [fml_adr-1-5:0] fml_adr_b;
73
74 always @(posedge sys_clk) begin
75         if(start_of_frame)
76                 fml_adr_b <= fml_adr_base;
77         else if(next_burst)
78                 fml_adr_b <= fml_adr_b + 1'd1;
79 end
80
81 assign fml_adr = {fml_adr_b, 5'd0};
82
83 /* Detect start of frames and filter fields */
84 reg previous_field;
85 always @(posedge sys_clk) begin
86         if(v_stb & v_ack)
87                 previous_field <= v_field;
88 end
89
90 assign start_of_frame = (v_stb & v_ack) &
91         ((field_filter[0] & previous_field & ~v_field)
92         |(field_filter[1] & ~previous_field & v_field));
93
94 /* Controller */
95 reg [2:0] state;
96 reg [2:0] next_state;
97
98 parameter WAIT_SOF = 3'd0;
99 parameter WAIT_EOB = 3'd1;
100 parameter TRANSFER1 = 3'd2;
101 parameter TRANSFER2 = 3'd3;
102 parameter TRANSFER3 = 3'd4;
103 parameter TRANSFER4 = 3'd6;
104
105 always @(posedge sys_clk) begin
106         if(sys_rst)
107                 state <= WAIT_SOF;
108         else
109                 stats <= next_state;
110 end
111
112 always @(*) begin
113         v_ack = 1'b0;
114         fml_stb = 1'b0;
115         in_frame = 1'b1;
116         next_burst = 1'b0;
117
118         data_en = 1'b0;
119
120         f_bcount = 2'bx;
121
122         next_state = state;
123
124         case(state)
125                 WAIT_SOF: begin
126                         in_frame = 1'b0;
127                         v_ack = 1'b1;
128                         data_en = start_of_frame;
129                         if(start_of_frame)
130                                 next_state = WAIT_EOB;
131                 end
132                 WAIT_EOB: begin
133                         v_ack = 1'b1;
134                         data_en = 1'b1;
135                         f_bcount = 2'd0;
136                         if(burst_7 & v_stb)
137                                 next_state = TRANSFER1;
138                 end
139                 TRANSFER1: begin
140                         fml_stb = 1'b1;
141                         f_bcount = 2'd0;
142                         if(fml_ack) begin
143                                 f_bcount = 2'd1;
144                                 next_state = TRANSFER2;
145                         end
146                 end
147                 TRANSFER2: begin
148                         f_bcount = 2'd2;
149                         next_burst = 1'b1;
150                         next_state = TRANSFER3;
151                 end
152                 TRANSFER3: begin
153                         f_bcount = 2'd3;
154                         next_state = TRANSFER4;
155                 end
156                 TRANSFER4: begin
157                         if(last_burst)
158                                 next_state = WAIT_SOF;
159                         else
160                                 next_state = WAIT_EOB;
161                 end
162         endcase
163
164 end
165
166 endmodule