24c2ca0010ba3988a37ef6510bf55ef56b6fda4a
[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 [fml_depth-1-1:0] fml_adr_base,
27         output start_of_frame,
28         output reg next_burst,
29         input last_burst,
30
31         /* From video input module. */
32         input v_stb,
33         output reg v_ack,
34         input v_field,
35         input [31:0] v_rgb565,
36
37         /* FML interface. fml_we=1 is assumed. */
38         output [fml_depth-1:0] fml_adr,
39         output reg fml_stb,
40         input fml_ack,
41         output [63:0] fml_do
42 );
43
44 /* Data buffer */
45 reg data_en;
46 reg [2:0] v_bcount;
47 reg burst_7;
48 always @(posedge sys_clk) begin
49         if(sys_rst)
50                 v_bcount <= 3'd0;
51         else if(v_stb & v_ack & data_en) begin
52                 v_bcount <= v_bcount + 3'd1;
53                 burst_7 <= v_bcount == 3'd6;
54         end
55 end
56
57 reg [1:0] f_bcount;
58
59 bt656cap_burstmem burstmem(
60         .sys_clk(sys_clk),
61
62         .we(v_stb & v_ack & data_en),
63         .wa(v_bcount),
64         .wd(v_rgb565),
65
66         .ra(f_bcount),
67         .rd(fml_do)
68 );
69
70 /* FML address generator */
71 reg [fml_adr-1-5:0] fml_adr_b;
72
73 always @(posedge sys_clk) begin
74         if(start_of_frame)
75                 fml_adr_b <= fml_adr_base;
76         else if(next_burst)
77                 fml_adr_b <= fml_adr_b + 1'd1;
78 end
79
80 assign fml_adr = {fml_adr_b, 5'd0};
81
82 /* Detect start of frames and filter fields */
83 reg previous_field;
84 always @(posedge sys_clk) begin
85         if(v_stb & v_ack)
86                 previous_field <= v_field;
87 end
88
89 assign start_of_frame = (v_stb & v_ack) &
90         ((field_filter[0] & previous_field & ~v_field)
91         |(field_filter[1] & ~previous_field & v_field));
92
93 /* Controller */
94 reg [2:0] state;
95 reg [2:0] next_state;
96
97 parameter WAIT_SOF = 3'd0;
98 parameter WAIT_EOB = 3'd1;
99 parameter TRANSFER1 = 3'd2;
100 parameter TRANSFER2 = 3'd3;
101 parameter TRANSFER3 = 3'd4;
102 parameter TRANSFER4 = 3'd6;
103
104 always @(posedge sys_clk) begin
105         if(sys_rst)
106                 state <= WAIT_SOF;
107         else
108                 stats <= next_state;
109 end
110
111 always @(*) begin
112         v_ack = 1'b0;
113         fml_stb = 1'b0;
114         next_burst = 1'b0;
115
116         data_en = 1'b0;
117
118         f_bcount = 2'bx;
119
120         next_state = state;
121
122         case(state)
123                 WAIT_SOF: begin
124                         v_ack = 1'b1;
125                         data_en = start_of_frame;
126                         if(start_of_frame)
127                                 next_state = WAIT_EOB;
128                 end
129                 WAIT_EOB: begin
130                         v_ack = 1'b1;
131                         data_en = 1'b1;
132                         f_bcount = 2'd0;
133                         if(burst_7 & v_stb)
134                                 next_state = TRANSFER1;
135                 end
136                 TRANSFER1: begin
137                         fml_stb = 1'b1;
138                         f_bcount = 2'd0;
139                         if(fml_ack) begin
140                                 f_bcount = 2'd1;
141                                 next_state = TRANSFER2;
142                         end
143                 end
144                 TRANSFER2: begin
145                         f_bcount = 2'd2;
146                         next_burst = 1'b1;
147                         next_state = TRANSFER3;
148                 end
149                 TRANSFER3: begin
150                         f_bcount = 2'd3;
151                         next_state = TRANSFER4;
152                 end
153                 TRANSFER4: begin
154                         if(last_burst)
155                                 next_state = WAIT_SOF;
156                         else
157                                 next_state = WAIT_EOB;
158                 end
159         endcase
160
161 end
162
163 endmodule