Video capture complete, untested
authorlekernel <sebastien.bourdeauducq@lekernel.net>
Mon, 28 Jun 2010 19:03:10 +0000 (21:03 +0200)
committerlekernel <sebastien.bourdeauducq@lekernel.net>
Mon, 28 Jun 2010 19:03:10 +0000 (21:03 +0200)
cores/bt656cap/rtl/bt656cap.v [new file with mode: 0644]
cores/bt656cap/rtl/bt656cap_ctlif.v [new file with mode: 0644]
cores/bt656cap/rtl/bt656cap_dma.v

diff --git a/cores/bt656cap/rtl/bt656cap.v b/cores/bt656cap/rtl/bt656cap.v
new file mode 100644 (file)
index 0000000..5aee21a
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Milkymist VJ SoC
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+module bt656cap #(
+       parameter csr_addr = 4'h0,
+       parameter fml_depth = 27
+) (
+       input sys_clk,
+       input sys_rst,
+
+       input [13:0] csr_a,
+       input csr_we,
+       input [31:0] csr_di,
+       output [31:0] csr_do,
+
+       output irq,
+
+       output [fml_depth-1:0] fml_adr,
+       output reg fml_stb,
+       input fml_ack,
+       output [63:0] fml_do
+
+       input vid_clk,
+       input [7:0] p,
+       inout sda,
+       output sdc
+);
+
+wire v_stb;
+wire v_ack;
+wire v_field;
+wire [31:0] v_rgb565;
+bt656cap_input in(
+       .sys_clk(sys_clk),
+       .vid_clk(vid_clk),
+
+       .p(p),
+
+       .stb(v_stb),
+       .ack(v_ack),
+       .field(v_field),
+       .rgb565(v_rgb565)
+);
+
+wire [1:0] field_filter;
+wire in_frame;
+wire [fml_depth-1-5:0] fml_adr_base;
+wire start_of_frame;
+wire next_burst;
+wire last_burst;
+bt656cap_dma #(
+       .fml_depth(fml_depth)
+) dma (
+       .sys_clk(sys_clk),
+       .sys_rst(sys_rst),
+
+       .field_filter(field_filter),
+       .in_frame(in_frame),
+       .fml_adr_base(fml_adr_base),
+       .start_of_frame(start_of_frame),
+       .next_burst(next_burst),
+       .last_burst(last_burst),
+
+       .v_stb(v_stb),
+       .v_ack(v_ack),
+       .v_field(v_field),
+       .v_rgb565(v_rgb565),
+
+       .fml_adr(fml_adr),
+       .fml_stb(fml_stb),
+       .fml_ack(fml_ack),
+       .fml_do(fml_do)
+);
+
+bt656cap_ctlif #(
+       .fml_depth(fml_depth),
+       .csr_addr(csr_addr)
+) ctlif (
+       .sys_clk(sys_clk),
+       .sys_rst(sys_rst),
+
+       .csr_a(csr_a),
+       .csr_we(csr_we),
+       .csr_di(csr_di),
+       .csr_do(csr_do),
+
+       .irq(irq),
+
+       .field_filter(field_filter),
+       .in_frame(in_frame),
+       .fml_adr_base(fml_adr_base),
+       .start_of_frame(start_of_frame),
+       .next_burst(next_burst),
+       .last_burst(last_burst),
+
+       .sda(sda),
+       .sdc(sdc)
+);
+
+endmodule
diff --git a/cores/bt656cap/rtl/bt656cap_ctlif.v b/cores/bt656cap/rtl/bt656cap_ctlif.v
new file mode 100644 (file)
index 0000000..ae2f4f3
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Milkymist VJ SoC
+ * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+module bt656cap_ctlif #(
+       parameter csr_addr = 4'h0,
+       parameter fml_depth = 27
+) (
+       input sys_clk,
+       input sys_rst,
+
+       input [13:0] csr_a,
+       input csr_we,
+       input [31:0] csr_di,
+       output reg [31:0] csr_do,
+
+       output reg irq,
+
+       output reg [1:0] field_filter,
+       input in_frame,
+       output reg [fml_depth-1-5:0] fml_adr_base,
+       input start_of_frame,
+       input next_burst,
+       output reg last_burst,
+
+       inout sda,
+       output sdc
+);
+
+/* I2C */
+reg sda_1;
+reg sda_2;
+reg sda_oe;
+reg sda_o;
+
+always @(posedge sys_clk) begin
+       sda_1 <= sda;
+       sda_2 <= sda_1;
+end
+
+assign sda = sda_oe ? sda_o : 1'bz;
+
+/* CSR IF */
+
+wire csr_selected = csr_a[13:10] == csr_addr;
+
+reg [14:0] max_bursts;
+reg [14:0] done_bursts;
+
+always @(posedge sys_clk) begin
+       if(sys_rst) begin
+               csr_do <= 32'd0;
+
+               sda_oe <= 1'b0;
+               sda_o <= 1'b0;
+       end else begin
+               csr_do <= 32'd0;
+
+               if(csr_selected) begin
+                       if(csr_we) begin
+                               case(csr_a[2:0])
+                                       3'd0: begin
+                                               sda_o <= csr_di[1];
+                                               sda_oe <= csr_di[2];
+                                       end
+                                       3'd1: field_filter <= csr_di[1:0];
+                                       3'd2: fml_adr_base <= csr_di[fml_depth-1:5];
+                                       3'd3: max_bursts <= csr_di[14:0];
+                               endcase
+                       end
+
+                       case(csr_a[2:0])
+                               3'd0: csr_do <= {sda_oe, sda_o, sda_2};
+                               3'd1: csr_do <= {in_frame, field_filter};
+                               3'd2: csr_do <= {fml_adr_base, 5'd0};
+                               3'd3: csr_do <= max_bursts;
+                               3'd4: csr_do <= done_bursts;
+                       endcase
+               end
+       end
+end
+
+always @(posedge sys_clk) begin
+       if(sys_rst)
+               irq <= 1'b0;
+       else
+               irq <= start_of_frame;
+end
+
+reg [14:0] burst_counter;
+always @(posedge sys_clk) begin
+       if(sys_rst) begin
+               last_burst <= 1'b0;
+               burst_counter <= 15'd0;
+       end else begin
+               if(start_of_frame) begin
+                       last_burst <= 1'b0;
+                       burst_counter <= 15'd0;
+                       done_bursts <= burst_counter;
+               end
+               if(next_burst) begin
+                       burst_counter <= burst_counter + 15'd1;
+                       last_burst <= (burst_counter + 15'd1) == max_bursts;
+               end
+       end
+end
+
+endmodule
index 24c2ca0..cc0ba8e 100644 (file)
@@ -23,7 +23,8 @@ module bt656cap_dma #(
 
        /* To/from control interface */
        input [1:0] field_filter,
-       output [fml_depth-1-1:0] fml_adr_base,
+       output reg in_frame,
+       input [fml_depth-1-5:0] fml_adr_base,
        output start_of_frame,
        output reg next_burst,
        input last_burst,
@@ -111,6 +112,7 @@ end
 always @(*) begin
        v_ack = 1'b0;
        fml_stb = 1'b0;
+       in_frame = 1'b1;
        next_burst = 1'b0;
 
        data_en = 1'b0;
@@ -121,6 +123,7 @@ always @(*) begin
 
        case(state)
                WAIT_SOF: begin
+                       in_frame = 1'b0;
                        v_ack = 1'b1;
                        data_en = start_of_frame;
                        if(start_of_frame)