Commit 69b1d30b authored by Andrey Filippov's avatar Andrey Filippov

Ready to start with the real serial sensor, all done so far can be used with parallel ones too

parents 0a729a6a 9c457ded
......@@ -10,9 +10,11 @@ x393.prj
*DEBUG_VDT*
*.kate-swp
*.old
*.new
*.bad
*.pyc
*.pickle
py393/dbg
py393/dbg*
includes/x393_cur_params_sim.vh
includes/x393_cur_params_target_*.vh
......
......@@ -62,42 +62,42 @@
<link>
<name>vivado_logs/VivadoBitstream.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoBitstream-20151009231737365.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoBitstream-20151103114104932.log</location>
</link>
<link>
<name>vivado_logs/VivadoOpt.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOpt-20151009231737365.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoOpt-20151103114104932.log</location>
</link>
<link>
<name>vivado_logs/VivadoOptPhys.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPhys-20151009231737365.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPhys-20151103114104932.log</location>
</link>
<link>
<name>vivado_logs/VivadoOptPower.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPower-20151009231737365.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPower-20151103114104932.log</location>
</link>
<link>
<name>vivado_logs/VivadoPlace.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoPlace-20151009231737365.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoPlace-20151103114104932.log</location>
</link>
<link>
<name>vivado_logs/VivadoRoute.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoRoute-20151009231737365.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoRoute-20151103114104932.log</location>
</link>
<link>
<name>vivado_logs/VivadoSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoSynthesis-20151009231255456.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoSynthesis-20151103114104932.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20151009231737365.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20151103114104932.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportSynthesis.log</name>
......@@ -107,7 +107,7 @@
<link>
<name>vivado_logs/VivadoTimingReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-20150904164653967.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-20151101221627109.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimingReportSynthesis.log</name>
......
VivadoRoute_122_SkipSnapshotRoute=true
VivadoRoute_123_SkipSnapshotRoute=true
com.elphel.store.context.VivadoRoute=VivadoRoute_122_SkipSnapshotRoute<-@\#\#@->VivadoRoute_123_SkipSnapshotRoute<-@\#\#@->
VivadoRoute_125_directive_route=MoreGlobalIterations
com.elphel.store.context.VivadoRoute=VivadoRoute_122_SkipSnapshotRoute<-@\#\#@->VivadoRoute_123_SkipSnapshotRoute<-@\#\#@->VivadoRoute_125_directive_route<-@\#\#@->
eclipse.preferences.version=1
......@@ -2,7 +2,7 @@ VivadoSynthesis_101_MaxMsg=10000
VivadoSynthesis_102_ConstraintsFiles=x393.xdc<-@\#\#@->x393_timing.xdc<-@\#\#@->
VivadoSynthesis_115_flatten_hierarchy=none
VivadoSynthesis_121_ConstraintsFiles=x393.xdc<-@\#\#@->x393_timing.xdc<-@\#\#@->
VivadoSynthesis_122_ConstraintsFiles=x393.xdc<-@\#\#@->x393_timing.xdc<-@\#\#@->
VivadoSynthesis_122_ConstraintsFiles=x393.xdc<-@\#\#@->x393_nox2_timing.xdc<-@\#\#@->
VivadoSynthesis_122_SkipSnapshotSynth=true
VivadoSynthesis_123_ResetProject=true
VivadoSynthesis_123_SkipSnapshotSynth=true
......
/*******************************************************************************
* Module: bit_stuffer_27_32
* Date:2015-10-23
* Author: andrey
* Description: Aggregate MSB aligned variable-length (1..27) data to 32-bit words
*
* Copyright (c) 2015 Elphel, Inc .
* bit_stuffer_27_32.v 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, either version 3 of the License, or
* (at your option) any later version.
*
* bit_stuffer_27_32.v 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/> .
*******************************************************************************/
`timescale 1ns/1ps
module bit_stuffer_27_32#(
parameter DIN_LEN = 27
)(
input xclk, // pixel clock, sync to incoming data
input rst, // @xclk
input [DIN_LEN-1:0] din, // input data, MSB aligned
input [4:0] dlen, // input data width
input ds, // input data valid
input flush_in, // flush remaining data - should be after last ds. Also prepares for the next block
output [31:0] d_out, // outpt 32-bit data
output reg [1:0] bytes_out, // (0 means 4) valid with dv
output reg dv, // output data valid
output reg flush_out // delayed flush in matching the data latency
);
localparam DATA1_LEN = DIN_LEN + 32 - 8;
localparam DATA2_LEN = DIN_LEN + 32 - 2;
localparam DATA3_LEN = DIN_LEN + 32 - 1;
reg [DATA1_LEN-1:0] data1; // first stage of the barrel shifter
reg [DATA2_LEN-1:0] data2; // second stage of the barrel shifter
reg [DATA3_LEN-1:0] data3; // second stage of the barrel shifter/ output register
reg [5:0] early_length; // number of bits in the last word (mod 32)
reg [5:0] dlen1; // use for the stage 2, MSB - carry out
reg [5:0] dlen2; // use for the stege 3
reg [31:0] dmask2_rom; // data mask (sync with data2) - 1 use new data, 0 - use old data. Use small ROM?
reg [1:0] stage; // delayed ds or flush
reg [1:0] ds_stage;
reg [2:0] flush_stage;
wire [4:0] pre_bits_out_w = dlen2[4:0] + 5'h7;
assign d_out = data3[DATA3_LEN-1 -: 32];
always @ (posedge xclk) begin
if (rst) stage <= 0;
else stage <= {stage[0], ds | flush_in};
if (rst) ds_stage <= 0;
else ds_stage <= {ds_stage[0], ds};
if (rst) flush_stage <= 0;
else flush_stage <= {flush_stage[1:0], flush_in};
if (rst || flush_in) early_length <= 0;
else if (ds) early_length <= early_length[4:0] + dlen; // early_length[5] is not used in calculations, it is just carry out
if (rst) dlen1 <= 0;
else if (ds) dlen1 <= early_length; // previous value
if (rst) dlen2 <= 0;
else if (stage[0]) dlen2 <= dlen1; // previous value (position)
// barrel shifter stage 1 (0/8/16/24)
if (rst) data1 <= 'bx;
else if (ds) case (early_length[4:3])
2'h0: data1 <= { din, 24'b0};
2'h1: data1 <= { 8'b0,din, 16'b0};
2'h2: data1 <= {16'b0,din, 8'b0};
2'h3: data1 <= {24'b0,din };
endcase
// barrel shifter stage 2 (0/2/4/6)
if (rst) data2 <= 'bx;
else if (stage[0]) case (dlen1[2:1])
2'h0: data2 <= { data1, 6'b0};
2'h1: data2 <= { 2'b0,data1, 4'b0};
2'h2: data2 <= { 4'b0,data1, 2'b0};
2'h3: data2 <= { 6'b0,data1 };
endcase
if (rst) dmask2_rom <= 'bx;
else if (stage[0]) case (dlen1[4:0])
5'h00: dmask2_rom <= 32'hffffffff;
5'h01: dmask2_rom <= 32'h7fffffff;
5'h02: dmask2_rom <= 32'h3fffffff;
5'h03: dmask2_rom <= 32'h1fffffff;
5'h04: dmask2_rom <= 32'h0fffffff;
5'h05: dmask2_rom <= 32'h07ffffff;
5'h06: dmask2_rom <= 32'h03ffffff;
5'h07: dmask2_rom <= 32'h01ffffff;
5'h08: dmask2_rom <= 32'h00ffffff;
5'h09: dmask2_rom <= 32'h007fffff;
5'h0a: dmask2_rom <= 32'h003fffff;
5'h0b: dmask2_rom <= 32'h001fffff;
5'h0c: dmask2_rom <= 32'h000fffff;
5'h0d: dmask2_rom <= 32'h0007ffff;
5'h0e: dmask2_rom <= 32'h0003ffff;
5'h0f: dmask2_rom <= 32'h0001ffff;
5'h10: dmask2_rom <= 32'h0000ffff;
5'h11: dmask2_rom <= 32'h00007fff;
5'h12: dmask2_rom <= 32'h00003fff;
5'h13: dmask2_rom <= 32'h00001fff;
5'h14: dmask2_rom <= 32'h00000fff;
5'h15: dmask2_rom <= 32'h000007ff;
5'h16: dmask2_rom <= 32'h000003ff;
5'h17: dmask2_rom <= 32'h000001ff;
5'h18: dmask2_rom <= 32'h000000ff;
5'h19: dmask2_rom <= 32'h0000007f;
5'h1a: dmask2_rom <= 32'h0000003f;
5'h1b: dmask2_rom <= 32'h0000001f;
5'h1c: dmask2_rom <= 32'h0000000f;
5'h1d: dmask2_rom <= 32'h00000007;
5'h1e: dmask2_rom <= 32'h00000003;
5'h1f: dmask2_rom <= 32'h00000001;
endcase
// barrel shifter stage 3 (0/1), combined with output/hold register
if (rst) data3 <= 'bx;
else if (ds_stage[1]) begin
data3[DATA3_LEN-1 -: 32] <= (~dmask2_rom & (dlen2[5] ? {data3[DATA3_LEN-1-32 : 0],6'b0}: data3[DATA3_LEN-1 -: 32])) |
( dmask2_rom & (dlen2[0] ? {1'b0,data2[DATA2_LEN-1 -: 31]} : data2[DATA2_LEN-1 -: 32]));
data3[DATA3_LEN-1-32: 0] <= dlen2[0] ? data2[DATA2_LEN-31-1 : 0] : {data2[DATA2_LEN-32-1 : 0], 1'b0};
end
// dv <= (ds_stage[1] && dlen2[5]) || (flush_stage[1] && !(|data3[DATA3_LEN-1 -: 32]));
// dv <= (ds_stage[1] && dlen1[5]) || (flush_stage[1] && !(|data3[DATA3_LEN-1 -: 32]));
// dv <= (ds_stage[0] && dlen1[5]) || (flush_stage[1] && !(|data3[DATA3_LEN-1 -: 32]));
dv <= (ds_stage[0] && dlen1[5]) || (flush_stage[1] && (|data3[DATA3_LEN-1 -: 32]));
// no difference in number of cells
// if (rst ) bytes_out <= 0; // if the dv was caused by 32 bits full - output 4 bytes
// else if (ds_stage[1]) bytes_out <= 0; // if the dv was caused by 32 bits full - output 4 bytes
if (rst || ds_stage[1]) bytes_out <= 0; // if the dv was caused by 32 bits full - output 4 bytes
else if (flush_stage[1]) bytes_out <= pre_bits_out_w[4:3];
flush_out <= flush_stage[2];
end
endmodule
This diff is collapsed.
/*******************************************************************************
* Module: bit_stuffer_metadata
* Date:2015-10-25
* Author: andrey
* Description:
*
* Copyright (c) 2015 Elphel, Inc .
* bit_stuffer_metadata.v 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, either version 3 of the License, or
* (at your option) any later version.
*
* bit_stuffer_metadata.v 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/> .
*******************************************************************************/
`timescale 1ns/1ps
module bit_stuffer_metadata(
input mclk,
input mrst, // @posedge mclk, sync reset
input xclk,
input xrst, // @posedge xclk, sync reset
input last_block, // use it to copy timestamp from fifo
// time stamping - will copy time at the end of color_first (later than the first hact after vact in the current frame, but before the next one
// and before the data is needed for output
input ts_pre_stb, // @mclk - 1 cycle before receiving 8 bytes of timestamp data
input [7:0] ts_data, // timestamp data (s0,s1,s2,s3,us0,us1,us2,us3==0)
input color_first, // @fradv_clk only used for timestamp
input [31:0] din, // input data, MSB aligned
input [1:0] bytes_in, // number of bytes, valid @ ds (0 means 4)
input in_stb, // input data/bytes_in strobe
input flush, // end of input data
input abort, // @ any, extracts 0->1 and flushes
// outputs @ negedge clk
output reg [31:0] data_out, // [31:0] output data
output reg data_out_valid,// output data valid
output reg done, // reset by !en, goes high after some delay after flushing
output reg running // from registering timestamp until done
`ifdef DEBUG_RING
, output reg [3:0] dbg_etrax_dma
,output dbg_ts_rstb
,output [7:0] dbg_ts_dout
`endif
);
reg [7:0] time_ram0[0:3]; // 0 - seconds, 1 - microseconds MSB in the output 32-bit word, byt LSB of the sec/usec
reg [7:0] time_ram1[0:3];
reg [7:0] time_ram2[0:3];
reg [7:0] time_ram3[0:3];
reg [3:0] ts_in=8;
reg last_block_d; // last_block delayed by one clock
reg color_first_r;
reg [2:0] abort_r;
reg force_flush;
// reg color_first_r; // registered with the same clock as color_first to extract leading edge
// stb_time[2] - single-cycle pulse after color_first goes low
// reg [19:0] imgsz32; // current image size in multiples of 32-bytes
reg [21:0] imgsz4; // current image size in multiples of 4-bytes
reg last_stb_4; // last stb_in was 4 bytes
reg trailer;
reg meta_out;
reg [1:0] meta_word;
reg zeros_out; // output of 32 bytes (8 words) of zeros
wire trailer_done = (imgsz4[2:0] == 7) && zeros_out;
wire meta_last = (imgsz4[2:0] == 7) && meta_out;
// re-clock enable to this clock
wire ts_rstb= last_block && !last_block_d; // enough time to have timestamp data; // one cycle before getting timestamp data from FIFO
wire [7:0] ts_dout; // timestamp data, byte at a time
wire write_size = (in_stb && (bytes_in != 0)) || (flush && last_stb_4);
wire stb_start = !color_first && color_first_r;
wire stb = in_stb & !trailer && !force_flush;
always @ (posedge xclk) begin
if (xrst ||trailer_done) imgsz4 <= 0;
else if (stb || trailer) imgsz4 <= imgsz4 + 1;
if (stb) last_stb_4 <= (bytes_in == 0);
last_block_d <= last_block;
color_first_r <= color_first;
if (xrst) ts_in <= 8;
else if (ts_rstb) ts_in <= 0;
else if (!ts_in[3]) ts_in <= ts_in + 1;
if ((!ts_in[3] && (ts_in[1:0] == 0)) || write_size) time_ram0[ts_in[3:2]] <= ts_in[3]? ({imgsz4[5:0],flush?2'b0:bytes_in}):ts_dout; //ts_in[3:2] == 2'b10 when write_size
if ((!ts_in[3] && (ts_in[1:0] == 1)) || write_size) time_ram1[ts_in[3:2]] <= ts_in[3]? (imgsz4[13:6]):ts_dout;
if ((!ts_in[3] && (ts_in[1:0] == 2)) || write_size) time_ram2[ts_in[3:2]] <= ts_in[3]? (imgsz4[21:14]):ts_dout;
if ((!ts_in[3] && (ts_in[1:0] == 3)) || write_size) time_ram3[ts_in[3:2]] <= ts_in[3]? (8'hff):ts_dout;
if (xrst) trailer <= 0;
else if (flush || force_flush) trailer <= 1;
else if (trailer_done) trailer <= 0;
if (xrst) meta_out <= 0;
else if (trailer && (imgsz4[2:0] == 4) &&!zeros_out) meta_out <= 1;
else if (meta_last) meta_out <= 0;
if (!meta_out) meta_word <= 0;
else meta_word <= meta_word + 1;
if (xrst) zeros_out <= 0;
else if (meta_last) zeros_out <= 1;
else if (trailer_done) zeros_out <= 0;
data_out <= ({32{stb}} & din) | ({32{meta_out}} & {time_ram0[meta_word],time_ram1[meta_word],time_ram2[meta_word],time_ram3[meta_word]});
data_out_valid <= stb || trailer;
if (xrst || trailer) running <= 0;
else if (stb_start) running <= 1;
done <= trailer_done;
// re-clock abort, extract leading edge
abort_r <= {abort_r[0] & ~abort_r[1], abort_r[0], abort & ~trailer};
if (xrst || trailer) force_flush <= 0;
else if (abort_r) force_flush <= 1;
end
// just for testing
`ifdef DEBUG_RING
assign dbg_ = ts_rstb;
assign dbg_ts_dout = ts_dout;
always @ (posedge xclk) begin
dbg_etrax_dma <= imgsz4[3:0];
end
`endif
//color_first && color_first_r
timestamp_fifo timestamp_fifo_i (
.sclk (mclk), // input
.srst (mrst), // input
.pre_stb (ts_pre_stb), // input
.din (ts_data), // input[7:0]
.aclk (xclk), //fradv_clk), // input
.arst (xrst), //fradv_clk), // input
.advance (stb_start), // triggers at the 0->1
.rclk (xclk), // input
.rrst (xrst), //fradv_clk), // input
.rstb (ts_rstb), // input
.dout (ts_dout) // output[7:0] reg
);
endmodule
/*******************************************************************************
* Module: cmprs_out_fifo32
* Date:2015-06-25
* Author: Andrey Filippov
* Description: Compressor output FIFO, modified to use 32-bit input and xclk
*
* Copyright (c) 2015 Elphel, Inc.
* cmprs_out_fifo32.v 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, either version 3 of the License, or
* (at your option) any later version.
*
* cmprs_out_fifo32.v 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/> .
*******************************************************************************/
`timescale 1ns/1ps
module cmprs_out_fifo32(
// input rst, // mostly for simulation
// wclk domain
input wclk, // source clock (1x pixel clock)
input wrst, // @posedge wclk, sync reset
input we,
input [31:0] wdata,
input wa_rst, // reset low address bits when stuffer is disabled (to make sure it is multiple of 32 bytes
input wlast, // written last 32 bytes of a frame (flush FIFO) - stuffer_done (has to be later than we)
output eof_written_wclk, // eof_written - reclocked to wclk
// rclk domain
input rclk,
input rrst, // @posedge rclk, sync reset
input rst_fifo, // reset FIFO (set read address to write, reset count)
input ren,
output [63:0] rdata,
output eof, // single rclk pulse signalling EOF
input eof_written, // confirm frame written ofer AFI to the system memory (single rclk pulse)
output flush_fifo, // EOF, need to output all what is in FIFO (Stays active until enough data chunks are read)
output [7:0] fifo_count // number of 32-byte chunks in FIFO
);
reg regen;
reg [ 8:0] raddr;
reg [ 7:0] count32;
reg [ 7:0] lcount32; // counting chunks left in the same frame
reg [ 9:0] waddr;
wire written32b; // written 32 bytes, re-clocked to read clock domain (single-cycle)
wire wlast_rclk;
reg flush_fifo_r;
assign flush_fifo = flush_fifo_r;
assign fifo_count = count32;
assign eof = wlast_rclk;
always @ (posedge wclk) begin
if (wrst) waddr <= 0;
else if (wa_rst) waddr <= waddr & 10'h3f8; // reset 3 LSBs only
else if (we) waddr <= waddr + 1;
end
always @ (posedge rclk) begin
regen <= ren;
if (rst_fifo) raddr <= {waddr[9:3],2'b0};
else if (ren) raddr <= raddr + 1;
if (rst_fifo) count32 <= 0;
else if ( written32b && !(ren && (&raddr[1:0]))) count32 <= count32 + 1;
else if (!written32b && (ren && (&raddr[1:0]))) count32 <= count32 - 1;
if (rst_fifo) lcount32 <= 0;
else if (wlast_rclk) lcount32 <= count32;
else if ((lcount32 !=0) && ren && (&raddr[1:0])) lcount32 <= lcount32 - 1;
if (rst_fifo) flush_fifo_r <= 0;
else if (wlast_rclk) flush_fifo_r <= 1;
else if ((count32[7:1] == 0) && ( !count32[0] || ren)) flush_fifo_r <= 0;
end
// wclk -> rclk
pulse_cross_clock written32b_i (.rst(wrst), .src_clk(wclk), .dst_clk(rclk), .in_pulse(we && (&waddr[2:0])), .out_pulse(written32b),.busy());
pulse_cross_clock wlast_rclk_i (.rst(wrst), .src_clk(wclk), .dst_clk(rclk), .in_pulse(wlast), .out_pulse(wlast_rclk),.busy());
// rclk -> wclk
pulse_cross_clock eof_written_wclk_i (.rst(rrst), .src_clk(rclk), .dst_clk(wclk), .in_pulse(eof_written), .out_pulse(eof_written_wclk),.busy());
ram_var_w_var_r #(
.REGISTERS(1),
.LOG2WIDTH_WR(5),
.LOG2WIDTH_RD(6)
) fifo_i (
.rclk (rclk), // input
.raddr (raddr), // input[8:0]
.ren (ren), // input
.regen (regen), // input
.data_out (rdata), // output[63:0]
.wclk (wclk), // input - OK, negedge mclk
.waddr (waddr), // input[10:0]
.we (we), // input
.web (8'hff), // input[7:0]
.data_in (wdata) // input[15:0]
);
endmodule
......@@ -119,9 +119,10 @@ module compressor393 # (
`endif
)(
// input rst, // global reset
input xclk, // global clock input, compressor single clock rate
`ifdef USE_XCLK2X
input xclk2x, // global clock input, compressor double clock rate, nominally rising edge aligned
`endif
input mrst, // @posedge mclk, sync reset
input xrst, // @posedge xclk, sync reset
input hrst, // @posedge hclk, sync reset
......@@ -388,7 +389,9 @@ module compressor393 # (
) jp_channel_i (
// .rst (rst), // input
.xclk (xclk), // input
`ifdef USE_XCLK2X
.xclk2x (xclk2x), // input
`endif
.mrst (mrst), // input
.xrst (xrst), // input
.hrst (hrst), // input
......
......@@ -249,7 +249,7 @@ module csconvert18a(
wire ystrt,nxtline;
reg [7:0] yaddr_r; // address for the external buffer memory to write 16x16x8bit Y data
reg ywe_r; // wrire enable of Y data
reg ywe_r; // write enable of Y data
reg [6:0] caddr_r; // address for the external buffer memory 2x8x8x8bit Cb+Cr data (MSB=0 - Cb, 1 - Cr)
reg cwe_r; // write enable for CbCr data
reg odd_pix; // odd pixel (assumes even number of pixels in a line
......@@ -267,10 +267,10 @@ module csconvert18a(
assign n000 = n000_r;
assign n255 = n255_r;
assign signed_y = signed_y_r; // - now signed char, -128(black) to +127 (white)
assign yaddr = yaddr_r;
assign ywe = ywe_r;
assign caddr = caddr_r;
assign cwe = cwe_r;
assign yaddr = yaddr_r2;
assign ywe = ywe_r2;
assign caddr = caddr_r2;
assign cwe = cwe_r2;
dly_16 #(.WIDTH(1)) i_strt_dly0 (.clk(CLK),.rst(1'b0), .dly(4'd15), .din(pre_first_in), .dout(strt_dly[0]));
dly_16 #(.WIDTH(1)) i_strt_dly1 (.clk(CLK),.rst(1'b0), .dly(4'd15), .din(strt_dly[0]), .dout(strt_dly[1]));
......@@ -532,20 +532,29 @@ Y[1,1]=(0x96*P[1,1]+ 0x1d*((P[1,0]+P[1,2])/2 + 0x4d*((P[0,1] +
reg [7:0] y;
// reg [7:0] y0; // bypass in monochrome mode
wire [7:0] y0 = pdc;
// wire [7:0] y0 = pdc;
reg [7:0] y0_r;
// wire [7:0] y0; // bypass in monochrome mode
reg [15:0] y1,y2,y3;
wire [15:0] y_sum =y1+y2+y3;
reg [15:0] y1,y2,y3;
// TODO: insert register to ease mm1..3 -> y (OK to delay all outputs).
// TODO: reduce width of y1,y2,y3 and correctly round
// wire [15:0] y_sum =y1+y2+y3;
reg [15:0] y_sum_r;
// always @ (posedge CLK) y0 <= pd1_dly; // m1; // equivalent
always @ (posedge CLK) y1 <= mm1;
always @ (posedge CLK) y2 <= mm2;
always @ (posedge CLK) y3 <= mm3;
// wire [7:0] pre_y= mono ? y0 : (y_sum[15:8]+y_sum[7]);
wire [7:0] pre_y= mono ? y0_r : (y_sum_r[15:8]+y_sum_r[7]);
// making y output signed -128..+127
wire [7:0] pre_y= mono ? y0 : (y_sum[15:8]+y_sum[7]);
always @ (posedge CLK) y[7:0] <= pre_y[7:0];
always @ (posedge CLK) signed_y_r[7:0] <= {~pre_y[7], pre_y[6:0]};
always @ (posedge CLK) begin
y1 <= mm1;
y2 <= mm2;
y3 <= mm3;
y0_r <= pdc;
y_sum_r <= y1+y2+y3;
y[7:0] <= pre_y[7:0];
signed_y_r[7:0] <= {~pre_y[7], pre_y[6:0]};
end
// Try easier and hope better algorithm of color extractions that should perform better on gradients.
......@@ -574,19 +583,31 @@ reg use_cr; // in this line cr is calculated. Valid during ywe_r
reg sub_y; // output accumulator/subtractor. 0 - load new data, 1 - subtract. Walid 2 cycles after ywe_r
wire cwe0; // preliminary cwe_r (to be modulated by odd/even pixels)
reg cstrt; //ystrt dealyed by 1
reg cnxt; // nxtline delayed by 1
reg cnxt; // nxtline delayed by 1
reg pre_sel_cbcrmult1;
// delaying, for now uing "old" ywe,cwe, yaddr,caddr - registering them on the output
always @ (posedge CLK) begin
if (~(ywe_r || ystrt || nxtline)) sel_cbcrmult1 <= ~(bayer_phase[1] ^ bayer_phase[0] ^ odd_line);
else sel_cbcrmult1 <= ~sel_cbcrmult1;
// if (~(ywe_r || ystrt || nxtline)) sel_cbcrmult1 <= ~(bayer_phase[1] ^ bayer_phase[0] ^ odd_line);
// else sel_cbcrmult1 <= ~sel_cbcrmult1;
if (~(ywe_r || ystrt || nxtline)) pre_sel_cbcrmult1 <= ~(bayer_phase[1] ^ bayer_phase[0] ^ odd_line);
else pre_sel_cbcrmult1 <= ~pre_sel_cbcrmult1;
sel_cbcrmult1 <=pre_sel_cbcrmult1;
sub_y <= ~sel_cbcrmult1;
cbcrmult1 <= sel_cbcrmult1?y[7:0]:pdc[7:0];
cbcrmult1 <= sel_cbcrmult1?y[7:0]:pdc[7:0];
// cbcrmult1 <= sel_cbcrmult1?y[7:0]:pdc[7:0];
cbcrmult1 <= sel_cbcrmult1?y[7:0]:y0_r[7:0]; // delayed by 1 clock
if (~ywe_r) use_cr <= ~(bayer_phase[1] ^ odd_line);
end
assign cbcrmult2=use_cr?m_cr:m_cb; // maybe will need a register? (use_cr will still be good as it is valid early)
assign cbcrmulto=cbcrmult1*cbcrmult2;
assign cbcrmult2 = use_cr?m_cr:m_cb; // maybe will need a register? (use_cr will still be good as it is valid early)
//assign cbcrmulto = cbcrmult1*cbcrmult2;
assign cbcrmulto = cbcrmult1*cbcrmult2_r;
reg [9:0] cbcrmult2_r; // will be one cycle later than cbcrmult2, but is still OK. Will be absorbed into the DSP block
// will preserve extra bit, but do not need to add half of the truncated MSB - on average there will be no shift after subtraction
always @ (posedge CLK) begin
cbcrmult2_r <= cbcrmult2;
cbcrmultr[10:0] <= cbcrmulto[17:7];
cbcr[10:0] <= sub_y? (cbcr[10:0]-cbcrmultr[10:0]+ 1'b1):cbcrmultr[10:0];
end
......@@ -598,23 +619,38 @@ end
dly_16 #(.WIDTH(1)) i_cwe0 (.clk(CLK),.rst(1'b0), .dly(4'd1), .din(ywe_r), .dout(cwe0));
//SRL16 i_cwe0 (.D(ywe_r ), .Q(cwe0), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0), .CLK(CLK)); // dly=2=1+1
always @ (posedge CLK) begin
cstrt <= ystrt;
cnxt <= nxtline;
cwe_r <= cwe0 && sub_y;
caddr_r[2:0]<= cwe0?(caddr_r[2:0]+cwe_r):3'b0;
if (cstrt) caddr_r[6] <= ~bayer_phase[1];
else if (cnxt) caddr_r[6] <= ~caddr_r[6];
if (cstrt) caddr_r[5:3] <=3'b0;
else if (cnxt) caddr_r[5:3] <=(bayer_phase[1]^caddr_r[6])? caddr_r[5:3]:(caddr_r[5:3]+1);
end
always @ (posedge CLK) begin
cstrt <= ystrt;
cnxt <= nxtline;
// cwe_r <= cwe0 && sub_y;
cwe_r <= cwe0 && !sel_cbcrmult1;
caddr_r[2:0]<= cwe0?(caddr_r[2:0]+cwe_r):3'b0;
if (cstrt) caddr_r[6] <= ~bayer_phase[1];
else if (cnxt) caddr_r[6] <= ~caddr_r[6];
if (cstrt) caddr_r[5:3] <=3'b0;
else if (cnxt) caddr_r[5:3] <=(bayer_phase[1]^caddr_r[6])? caddr_r[5:3]:(caddr_r[5:3]+1);
end
// extra signals delayed by 1 clock
reg ywe_r2, cwe_r2;
reg [6:0] caddr_r2;