/*!
* Module:simul_sensor12bits
* @file simul_sensor12bits.v
* @date 2015-07-29
* @author Andrey Filippov
*
* @brief Generate sensor data
*
* @copyright Copyright (c) 2002-2015 Elphel, Inc.
*
* License:
*
* simul_sensor12bits.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.
*
* simul_sensor12bits.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 .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*/
module simul_sensor12bits # (
parameter SENSOR_IMAGE_TYPE = "NORM", // "RUN1",
parameter lline = 192, // 1664;// line duration in clocks
parameter ncols = 66, //58; //56; // 129; //128; //1288;
parameter nrows = 18, // 16; // 1032;
parameter nrowb = 1, // number of "blank rows" from vact to 1-st hact
parameter nrowa = 1, // number of "blank rows" from last hact to end of vact
// parameter nAV = 24, //240; // clocks from ARO to VACT (actually from en_dclkd)
parameter nbpf = 20, //16; // bpf length
parameter ngp1 = 8, // bpf to hact
parameter nVLO = 1, // VACT=0 in video mode (clocks)
//parameter tMD = 14; //
//parameter tDDO = 10; // some confusion here - let's assume that it is from DCLK to Data out
parameter tMD = 4, //
parameter tDDO = 2, // some confusion here - let's assume that it is from DCLK to Data out
parameter tDDO1 = 5, //
parameter trigdly = 8, // delay between trigger input and start of output (VACT) in lines
parameter ramp = 1, // 1 - ramp, 0 - random (now - sensor.dat)
parameter new_bayer = 0 // 0 - old (16x16), 1 - new (18x18)
) (
input MCLK, // Master clock
input MRST, // Master Reset - active low
input ARO, // Array read Out.
input ARST, // Array Reset. Active low
input OE, // output Elphel, Inc.ock
input SCL, // I2C data // SuppressThisWarning VEditor - not used
inout SDA, // I2C data// SuppressThisWarning VEditor - not used/assigned
input OFST, // I2C address ofset by 2: for simulation 0 - still mode, 1 - video mode.
output [11:0] D, // [11:0] data output
output DCLK, // Data output clock
output BPF, // Black Pixel Flag
output HACT, // Horizontal Active
output VACT, // Vertical Active
output VACT1);
localparam s_stop= 0;
localparam s_preVACT= 1;
localparam s_firstline= 2;
localparam s_BPF= 3;
localparam s_preHACT= 4;
localparam s_HACT= 5;
localparam s_afterHACT= 6;
localparam s_lastline= 7;
localparam s_frame_done=8;
localparam t_preVACT= lline* trigdly;
localparam t_firstline=nrowb*lline+1; // 1664
localparam t_BPF= nbpf; // 16
localparam t_preHACT= ngp1; // 8
localparam t_HACT= ncols; // 1288
localparam t_afterHACT=lline-nbpf-ngp1-ncols; // 352
localparam t_lastline= nrowa*lline+1; // 1664
reg [15:0] sensor_data[0:4095]; // up to 64 x 64 pixels // SuppressThisWarning VEditor - Will be assigned by $readmem
// $readmemh("sensor.dat",sensor_data);
reg c; // internal data out clock
//reg [9:0] id; // internal pixel data (sync do DCLK)
//wire [9:0] nxt_d; // will be calculated later - next pixel data
reg stopped;
wire #1 stoppedd=stopped;
reg ibpf, ihact, ivact, ivact1;
reg arst1; //
reg [11:0] col; // current row
reg [11:0] row; // current column;
reg [3:0] state;
reg [15:0] cntr;
wire [11:0] cold;
wire [11:0] rowd;
wire [3:0] stated;
wire [15:0] cntrd;
wire NMRST=!MRST;
wire [5:0] row_index=row[5:0]-new_bayer;
wire [5:0] col_index=col[5:0]-new_bayer;
// random
integer seed;
integer r;
reg c_rand;
reg [11:0] d_rand;
assign #1 cold= col;
assign #1 rowd= row;
assign #1 stated= state;
assign #1 cntrd= cntr;
//assign #tDDO D = OE? {10{1'bz}}: ((ihact || ibpf)? ((ramp)?(col[9:0] + row[9:0]):(d_rand)): 10'b0); // just test pattern
//assign #tDDO D = OE? {10{1'bz}}: ((ihact || ibpf)? ((ramp)?(col[9:0] + row[9:0]):(sensor_data[{row_index[5:0],col_index[5:0]}])): 10'b0); // just test pattern
//assign #tDDO D = OE? {12{1'bz}}: ((ihact || ibpf)? ((ramp)?(col[11:0] + row[11:0]):(sensor_data[{row_index[5:0],col_index[5:0]}])): 12'b0); // just test pattern
assign #tDDO D = OE? {12{1'bz}}: ((ihact || ibpf)? ((ramp)?({row[11:8],8'h0} + col[11:0]):(sensor_data[{row_index[5:0],col_index[5:0]}])): 12'b0); // just test pattern
//assign #tDDO BPF = ibpf;
//assign #tDDO HACT= ihact;
//assign #tDDO VACT= ivact;
assign #tDDO1 BPF = ibpf;
assign #tDDO1 HACT= ihact;
assign #tDDO1 VACT= ivact;
assign #tDDO1 VACT1= ivact && !ivact1;
assign DCLK= c;
initial begin
//parameter ramp = 1; // 0 - ramp, 1 - random
//parameter lline = 192; // 1664;// line duration in clocks
//parameter ncols = 58; //56; // 129; //128; //1288;
//parameter nrows = 16; // 1032;
$display ("sensor parameters");
$display (" -- image type = %s",SENSOR_IMAGE_TYPE);
$display (" -- ramp = %d (0 - random, 1 - ramp)",ramp);
$display (" -- lline = %d (line duration in clocks)",lline);
$display (" -- ncols = %d (numer of clocks in HACT)",ncols);
$display (" -- nrows = %d (number of rows)",nrows);
$display (" -- t_afterHACT = %d ",t_afterHACT);
$display (" -- t_preHACT = %d ",t_preHACT);
$display (" -- new_bayer = %d ",new_bayer);
// reg [15:0] sensor_data[0:4095]; // up to 64 x 64 pixels
if (SENSOR_IMAGE_TYPE == "NORM") $readmemh("input_data/sensor.dat",sensor_data);
else if (SENSOR_IMAGE_TYPE == "RUN1") $readmemh("input_data/sensor_run1.dat",sensor_data);
else begin
$display ("WARNING: Unrecognized sensor image :'%s', using default 'NORM': input_data/sensor.dat",SENSOR_IMAGE_TYPE);
$readmemh("input_data/sensor.dat",sensor_data);
end
c=0;
// {ibpf,ihact,ivact}=0;
stopped=1;
arst1= 0;
seed= 1;
d_rand= 0;
// row=0;
// col=0;
end
always @ (NMRST) begin
c=0;
// {ibpf,ihact,ivact}=0;
stopped=1;
arst1=0;
// row=0;
// col=0;
end
always begin
@ (posedge MCLK) begin
#tMD c = !stoppedd;
end
@ (negedge MCLK) begin
#tMD c = 1'b0;
end
end
always @ (posedge MCLK) begin
// #1 stopped= !arst1 || (stoppedd && !ARO) ;
#1 stopped= !arst1 || ((stoppedd || (state== s_frame_done)) && ARO) ; /// ARO tow TRIGGER, active low
#1 arst1=ARST;
end
always @ (posedge c) ivact1 = ivact;
always @ (posedge stoppedd or posedge c) begin
if (stoppedd) begin
{ibpf,ihact,ivact}=0;
row=0;
col=0;
// id=0;
state=0;
cntr=0;
end else if (|cntrd != 0) begin
#1 cntr=cntrd-1;
if (BPF || HACT) col=cold+1;
end else begin
case (stated)
s_stop: begin
cntr= t_preVACT-1;
state= s_preVACT;
end
s_preVACT: begin
ivact= 1'b1;
cntr= t_firstline-1;
state= s_firstline;
end
s_firstline: begin
col= 0;
row= 0;
if (t_BPF>=1) begin
ibpf= 1'b1;
cntr= t_BPF-1;
state= s_BPF;
end else begin
ihact= 1'b1;
cntr= t_HACT-1;
state= s_HACT;
end
end
s_BPF: begin
ibpf= 1'b0;
cntr= t_preHACT-1;
state= s_preHACT;
end
s_preHACT: begin
ihact= 1'b1;
col= 0;
cntr= t_HACT-1;
state= s_HACT;
end
s_HACT: begin
ihact= 1'b0;
row= rowd+1;
cntr= t_afterHACT-1;
state= s_afterHACT;
end
s_afterHACT:
if (rowd == nrows) begin
cntr= t_lastline-1;
state= s_lastline;
end else begin
col= 0;
if (t_BPF>=1) begin
ibpf= 1'b1;
cntr= t_BPF-1;
state= s_BPF;
end else begin
ihact= 1'b1;
cntr= t_HACT-1;
state= s_HACT;
end
end
s_lastline: begin
ivact= 1'b0;
state= s_frame_done;
cntr=nVLO;
end
s_frame_done: if (OFST) begin
ivact= 1'b1;
cntr= t_firstline-1;
state= s_firstline;
end
endcase
end
// random data
seed = $random(seed);
r = (seed & 'h7fff);
r= (r * r) >> 20; // 10 bits
c_rand = seed[16]; // >>16; // sign
d_rand=c_rand?(D+(((1023-d_rand)*r)>>10)):(d_rand-((d_rand*r)>>10));
end
endmodule