Commit ac0bb574 authored by Andrey Filippov's avatar Andrey Filippov

Initial commit of the x353 files as they were in the NC353 camera codebase

parent fb97a428
/** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
`timescale 1ns/1ps
module three_motor_driver ( clk, // system clock, negedge
xclk, // half frequency (80 MHz nominal)
we, // write enable (lower 16 bits, high - next cycle)
wa, // write address(1)/data(0)
di, // 16-bit data in (32 multiplexed)
do, // 16-bit data output
encod1, // 2-bit encoder data input, motor1
encod2, // 2-bit encoder data input, motor2
encod3, // 2-bit encoder data input, motor3
mot1, // 2 bits motor1 control output (11 - shorted, 00 - stop)
mot2, // 2 bits motor1 control output (11 - shorted, 00 - stop)
mot3 // 2 bits motor1 control output (11 - shorted, 00 - stop)
);
parameter DATA_WIDTH=24;
input clk; // system clock, negedge
input xclk; // half frequency (80 MHz nominal)
input we; // write enable (lower 16 bits, high - next cycle)
input wa; // write address(1)/data(0)
input [15:0] di; // 16-bit data in (32 multiplexed)
output [31:0] do; // 16-bit data output
input [1:0] encod1; // 2-bit encoder data input, motor1
input [1:0] encod2; // 2-bit encoder data input, motor2
input [1:0] encod3; // 2-bit encoder data input, motor3
output [1:0] mot1; // 2 bits motor1 control output (11 - shorted, 00 - stop)
output [1:0] mot2; // 2 bits motor1 control output (11 - shorted, 00 - stop)
output [1:0] mot3; // 2 bits motor1 control output (11 - shorted, 00 - stop)
reg [10:0] addr; // 11-th bit only for table readback
reg we_d; // only if wa was 0
reg we_pos;
reg we_ctl;
reg we_timing;
reg we_timing1;
reg we_decrement_on_pulse;
reg [7:0] pwm_cycle; // nominal 67 (0x43)
reg [2:0] pwm_delay; // nominal 2 - 0.3 usec
reg [3:0] deglitch_div; // nominal 7 ~=1 MHz
// for metastability reduction on the clock domain boarder
reg [7:0] pre_pwm_cycle; // nominal 67 (0x43)
reg [2:0] pre_pwm_delay; // nominal 2 - 0.3 usec
reg [3:0] pre_deglitch_div; // nominal 7 ~=1 MHz
reg [11:0] enc_period_cycle; // 1111 (0x457 ) so period measurement counter increments 6 times per millisecond (full speed encoder period)
// adjust to actual speed - period is floating point, maximal precision for 0..8 counts
reg [11:0] pre_enc_period_cycle;
reg [ 4:0] dec_on_pulse;
reg [ 4:0] pre_dec_on_pulse;
reg [15:0] di_d;
reg en_lut; // just to save energy
wire [3:0] pwm_code; //code to PWM module.0x20 - stop, else pwm_code[3] - direction, pwm_code[2:0] - PWM duty factor (0 - 0%, 1 - 25%, 2 - 27.5%, ..,7 - 100%)
wire [3:0] reg_addr; //={addr[1], addr[0] ^ (~addr[1]), addr[2],addr[3]}; // 0..3 - current positions, next - debug data (deglitch, period, pwm. 0 - control, 1..3 - motors
wire [DATA_WIDTH-1:0] state_next;
wire [DATA_WIDTH-1:0] state_current;
wire [3:0] sequence;
wire [3:0] sequence_next;
wire [DATA_WIDTH-1:0] target_pos;
wire reset_positions_clk;
wire enable_mot_clk;
reg pre_enable_mot, enable_mot;
reg pre_reset_positions, reset_positions;
reg pre_first;
wire [1:0] encoder;
assign encoder[1:0]=sequence[3]?(sequence[2]? encod3[1:0]:encod2[1:0]):encod1[1:0];
// wire [3:0] reg_addr={addr[1], addr[0] ^ (~addr[1]), addr[2],addr[3]}; // 0..3 - current positions, next - debug data (deglitch, period, pwm. 0 - control, 1..3 - motors
// assign read_addr[3:0]={reg_addr[1:0],reg_addr[3], ~reg_addr[2]}; //reg_addr[3:0]
assign reg_addr[3:0]={addr[1:0],addr[3], ~addr[2]};
always @ (negedge clk) begin
we_d <= ~wa & we;
we_pos <= we && (!wa) && (addr[9:2]==0);
we_ctl <= we && (!wa) && (addr[9:0]==4);
we_timing <= we && (!wa) && (addr[9:0]==5);
we_timing1 <= we && (!wa) && (addr[9:0]==6);
we_decrement_on_pulse <= we && (!wa) && (addr[9:0]==7);
if (we_timing) begin
pre_pwm_cycle[7:0] <= di_d[ 7: 0];
pre_pwm_delay[2:0] <= di_d[10: 8];
pre_deglitch_div[3:0] <= di_d[15:12];
end
if (we_timing1) begin
pre_enc_period_cycle[11:0] <= di_d[11:0];
end
if (we_decrement_on_pulse) begin
pre_dec_on_pulse[4:0] <= di_d[4:0];
end
end
always @ (negedge clk) begin
if (we) di_d[15:0] <= di[15:0];
if (we & wa) addr[10:9] <= di[10:9] ;
if (we & wa) addr[8:0] <= di[8:0] ;
else if (we_d ) addr[8:0] <= addr[8:0]+1 ; // autoincrement, but in the same device only
end
FDCE_1 i_reset_positions_clk(.C(clk),.CE(we_ctl && di_d[2]),.CLR(reset_positions),.D(1'b1), .Q(reset_positions_clk));
FDCE_1 i_enable_mot_clk (.C(clk),.CE(we_ctl && di_d[1]),.CLR(1'b0), .D(di_d[0]), .Q(enable_mot_clk));
always @ (posedge xclk) begin
pwm_cycle[7:0] <= pre_pwm_cycle[7:0];
pwm_delay[2:0] <= pre_pwm_delay[2:0];
deglitch_div[3:0] <= pre_deglitch_div[3:0];
enc_period_cycle[11:0] <= pre_enc_period_cycle[11:0];
dec_on_pulse[4:0] <= pre_dec_on_pulse[4:0];
pre_reset_positions <= reset_positions_clk;
if (pre_first) reset_positions <= pre_reset_positions; // single sequence period;
pre_enable_mot <= enable_mot_clk;
if (pre_first) enable_mot <= pre_enable_mot;
end
// reset at simulation
assign sequence_next[1:0]=sequence[1:0]+1;
assign sequence_next[3:2]=(sequence[1:0]==3'b11)?((sequence[3:2]==3'b11)?2'b01:(sequence[3:2]+1)):sequence[3:2];
FD i_sequence_0(.C(xclk),.D(sequence_next[0]), .Q(sequence[0]));
FD i_sequence_1(.C(xclk),.D(sequence_next[1]), .Q(sequence[1]));
FD i_sequence_2(.C(xclk),.D(sequence_next[2]), .Q(sequence[2]));
FD i_sequence_3(.C(xclk),.D(sequence_next[3]), .Q(sequence[3]));
always @ (posedge xclk) begin
pre_first <=(sequence[3:0]==4'b1110);
end
/// First cycle: deglitching
//synthesis translate_off
defparam i_deglitch_encoder.IGNORE_EN = 1'b0;
//synthesis translate_on
wire [8:0] period_cur=state_current[15:7] ;
wire [8:0] period_new; // multiplex to state_next[15:7]
wire [4:0] deglitch_cur=state_current[6:2] ;
wire [4:0] deglitch_new; // multiplex to state_next[6:2]
wire [1:0] encoder_used=state_current[1:0] ;
wire [1:0] encoder_new; // multiplex to state_next[1:0]
wire pre_incdec; // not registered
wire inc, dec, inc_dec; // registered inside deglitch_encoder
wire [4:0] encoded_period;
wire [DATA_WIDTH-1:0] rdo; // position/register file read data
wire [15:0] tdo; // table readback output
wire [31:0] do; // multiplexed readback
assign do[31:0]=addr[9]?{16'h0,tdo[15:0]}:{{(32-DATA_WIDTH){rdo[DATA_WIDTH-1]}},rdo[DATA_WIDTH-1:0]};
deglitch_encoder i_deglitch_encoder
(.clk(xclk), // posedge, 80 MHz
.en_in(!reset_positions), // enable (just for simulation), for real - let it on even when motors are off
.process(sequence[1:0]==2'h0), // process data this cycle (store inc, dec)
.pre_first(pre_first), // next whill be the first motor in a cycle (may use just spread bits)
.cycle_div(deglitch_div[3:0]), // [3:0] clock divisor - nominally 1/7 (80/4/3/7~=1MHz)
.deglitch_cur(deglitch_cur[4:0]), // [4:0] current value of deglitch counter for this channel , read from RAM
.deglitch_new(deglitch_new[4:0]), // [4:0] next value of deglitch counter for this channel, to write to RAM
.encoder(encoder[1:0]), // [1:0] current encoder data
.encoder_used(encoder_used[1:0]), // [1:0] encoder data from RAM (deglitched)
.encoder_new(encoder_new[1:0]), // encoder data to RAM (deglitched)
.pre_incdec(pre_incdec), // combinatorial output, valid same cucle
.inc(inc), // increment position counter, registered. On top level apply inc/dec to the next cycle, not to the current
.dec(dec), // decrement position counter, registered
.inc_dec(inc_dec) // increment or decrement position counter, registered
);
//synthesis translate_off
defparam i_period_encoder.IGNORE_EN = 1'b0;
//synthesis translate_on
period_encoder i_period_encoder(
.clk(xclk), // posedge, 80 MHz
.en_in(!reset_positions), // enable (just for simulation), for real - let it on even when motors are off
.pre_first(pre_first), // next will be the first motor in a cycle (may use just spread bits)
.process(sequence[1:0]==2'h0), // increment (with limit) period
.inc_dec(pre_incdec), // encoder pulse detected
.cycle_div(enc_period_cycle[11:0]), // [11:0] clock divisor - nominally 1111 (0x457 ), 6KHz (6 cycles per encoder phase, full speed)
.decr_on_pulse(dec_on_pulse[4:0]), // [4:0] decrease calculated period code by this amount after the encoder pulse. Normally - just 1?
.period_cur(period_cur[8:0]), // [8:0] current period from register file,
.period_new(period_new[8:0]), // [8:0] updated period to be stored back to register file
.encoded_period(encoded_period[4:0]) //4:0] encoded period (registered, valid 2 cycles after process
);
/// Second cycle: updating position, calculating position error
wire [DATA_WIDTH-1:0] position_next; // multiplex to state_next[15:0]
wire [DATA_WIDTH:0] position_diff;
wire [ 5:0] minus_diff;
reg [ 5:0] position_err; // saturated and registered position_diff
// assign position_next[15:0]= (reset_positions || (sequence[1:0]!=2'h1))? 16'h0:(inc?(state_current[15:0]+1):(dec?(state_current[15:0]-1):(state_current[15:0]) ) );
assign position_next[DATA_WIDTH-1:0]= reset_positions? target_pos[DATA_WIDTH-1:0]:
(inc?(state_current[DATA_WIDTH-1:0]+1):
(dec?(state_current[DATA_WIDTH-1:0]-1):(state_current[DATA_WIDTH-1:0]) ) );
// assign position_diff={target_pos[15],target_pos[15:0]}-{state_current[15],state_current[15:0]};
// assign minus_diff[4:0]= state_current[4:0] - target_pos[4:0];
assign position_diff={state_current[DATA_WIDTH-1],state_current[DATA_WIDTH-1:0]}-{target_pos[DATA_WIDTH-1],target_pos[DATA_WIDTH-1:0]};
assign minus_diff[5:0]= target_pos[5:0]-state_current[5:0];
always @ (posedge xclk) if (sequence[1:0]==2'h1) begin
position_err[5:0] <= (position_diff[DATA_WIDTH:5]=={(DATA_WIDTH-4){1'b0}}) ? position_diff[5:0]:
((position_diff[DATA_WIDTH:5]=={(DATA_WIDTH-4){1'b1}})? {1'b1,minus_diff[4:0]|{5{minus_diff[5]}}}:{position_diff[DATA_WIDTH],5'h1f});
end
/// third cycle: calculating speed, using RAM table to calculate pwm code
/// Combine old (freom register file) /new encoded periods, inc/dec pulses to prepare a 6-bit (partial) index for a RAM table.
/// Together with the position error (another 6 bits) the full 12-bit undex provides 1 4-bit PWM code from the RAM table
/// Updates direction immediately, period - if inc_dec or when new period > saved period (so it will be updated even if the motor is stopped)
wire dir_last= state_current[5]; // last stored direction (from register file)
wire [4:0] enc_period_last=state_current[4:0]; // [4:0] last encoded period (from register file)
wire dir_this; // new value of direction to be stored in the register file and used in the index, multiplex to state_next[5]
wire [4:0] enc_period_this; // [4:0] encoded period for the register file/ table index, multiplex to state_next[4:0]
//synthesis translate_off
defparam i_calc_speed.IGNORE_EN = 1'b0;
//synthesis translate_on
calc_speed i_calc_speed(
.clk(xclk), // posedge, 80 MHz
.en_in(!reset_positions), // enable (just for simulation), for real - let it on even when motors are off
.process(sequence[1:0]==2'h2), // increment (with limit) period
.inc_dec(inc_dec), // encoder pulse detected
.inc(inc), // encoder position increment
.dec(dec), // encoder position decrement
.enc_period_curr(encoded_period[4:0]), // encoded current period (still running if !inc_dec)
.dir_last(dir_last), // last stored direction (from register file)
.enc_period_last(enc_period_last[4:0]), // [4:0] last encoded period (from register file)
.dir_this(dir_this), // new value of direction to be stored in the register file and used in the index
.enc_period_this(enc_period_this[4:0]) // [4:0] encoded period for the register file/ table index
);
/// fourth cycle: processing PWM
wire [2:0] cur_pwm=state_current[2:0];
wire [2:0] new_pwm; // multiplex to state_next[2:0]
wire [1:0] next_mot;
reg set_mot;
reg [1:0] mot1; // 2 bits motor1 control output (11 - shorted, 00 - stop)
reg [1:0] mot2; // 2 bits motor1 control output (11 - shorted, 00 - stop)
reg [1:0] mot3; // 2 bits motor1 control output (11 - shorted, 00 - stop)
motor_pwm i_motor_pwm(
.clk(xclk), // posedge, 80 MHz
.en(enable_mot), // enable, 0 turns off motors and resets counterts
.pre_first(pre_first), // next whill be the first motor in a cycle (may use just spread bits)
.pwm_delay(pwm_delay[2:0]), // [2:0] - turns off bridge during transition (i.e. 10->00->11->00->10 ..). Nominal 0.3usec - 2 (0x18) cycles (80/4/3=6.66MHz)
.pwm_cycle(pwm_cycle[7:0]), // [7:0] - pwm cycle duration Nominal 10usec or 67 (0x43) 6.66MHz cycles. Total PWM period will be 8 of these cycles
.spread({sequence[3:2],1'b0}), // [2:0] shift on phase between motors, adds this number to the current phase (use just 2 MSBs for 3 motors)
.cur_pwm(cur_pwm[2:0]), // [2:0] - PWM data stored in per-motor memory. [1] - 'on', [0] direction, [2] - enable. That bit is used to turn off motor during PWM transitions
.pwm_code(pwm_code[3:0]), // [3:0] - code from the RAM. 0x8 - stop, , otherwise [3] - direction, [2:0]/8 - duty cycle (8 - 100% on), 0 - 0%, 1 - 25%, 3 - 37.5%...
.new_pwm(new_pwm[2:0]), // [2:0]
.mot(next_mot[1:0]) // [1:0] - data to be copied to the motor outputs
);
always @ (posedge xclk) begin
set_mot <= (sequence[1:0]==2'h2); // active during last (fourth) cycle
if (set_mot && !sequence[3]) mot1[1:0] <=next_mot[1:0];
if (set_mot && sequence[3] && !sequence[2]) mot2[1:0] <=next_mot[1:0];
if (set_mot && sequence[3] && sequence[2]) mot3[1:0] <=next_mot[1:0];
end
/// Multiplex register file input from multiple bit fields, depending on the sequence state
/*
0: wire [8:0] period_new; // multiplex to state_next[15:7]
wire [4:0] deglitch_new; // multiplex to state_next[6:2]
wire [1:0] encoder_new; // multiplex to state_next[1:0]
1: wire [15:0] position_next; // multiplex to state_next[15:0]
2: wire dir_this; // new value of direction to be stored in the register file and used in the index, multiplex to state_next[5]
wire [4:0] enc_period_this; // [4:0] encoded period for the register file/ table index, multiplex to state_next[4:0]
3: wire [2:0] new_pwm; // multiplex to state_next[2:0]
*/
always @ (posedge xclk) begin
en_lut <= (sequence[1:0]==2'h1); // valid at sequence[1:0]==2'h2
end
assign state_next[DATA_WIDTH-1:0]=sequence[1]?
(sequence[0]?{{(DATA_WIDTH-3){1'b0}},new_pwm[2:0]}:
{{(DATA_WIDTH-6){1'b0}},dir_this,enc_period_this[4:0]}):
(sequence[0]?position_next[DATA_WIDTH-1:0]:
{{(DATA_WIDTH-16){1'b0}},period_new[8:0],deglitch_new[4:0],encoder_new[1:0]}); // {0{1'b0}} OK
//Instance of motor table RAM, defines behaviour of the motor depending on current position and speed
// May add data initialization to theis memory
RAMB16_S4_S18 i_motor_ram (
.CLKA(xclk), // Port A Clock
.ENA(en_lut), // Port A RAM Enable Input
.WEA(1'b0), // Port A Write Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.ADDRA({position_err[5:0],dir_this,enc_period_this[4:0]}), // Port A 12-bit Address Input
.DIA(4'b0), // Port A 4-bit Data Input
.DOA(pwm_code[3:0]), // Port A 4-bit Data Output registered?
.CLKB(!clk), // Port B Clock
// .ENB(addr[9] && ((~wa && we) || we_d)), // Port B RAM Enable Input
// .WEB(1'b1), // Port B Write Enable Input
.ENB(1'b1), // Port B RAM Enable Input
.WEB(addr[9] && ((~wa && we) || we_d)), // Port B Write Enable Input
// .ADDRB({addr[8:0],we_d}), // Port B 10-bit Address Input
.ADDRB({addr[8:0],(we | we_d)?we_d:addr[10]}), // Port B 10-bit Address Input
.DIB(di[15:0]), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.DOB(tdo[15:0]), // Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.SSRB(1'b0) // Port B Synchronous Set/Reset Input
);
myRAM_WxD_D_1 #( .DATA_WIDTH(DATA_WIDTH),.DATA_DEPTH(2))
i_target_pos (.D((DATA_WIDTH>16)?{di[DATA_WIDTH-17:0],di_d[15:0]}:di_d[15:0]),
.WE(we_pos),
.clk(clk),
.AW(addr[1:0]),
.AR(sequence[3:2]),
.QW(),
.QR(target_pos[DATA_WIDTH-1:0]));
// wire [3:0] read_addr; // reorder addresses, so loc 1..3 will read current positions of the motors
// assign read_addr[3:0]={reg_addr[1:0],reg_addr[3], ~reg_addr[2]}; //reg_addr[3:0]
myRAM_WxD_D #( .DATA_WIDTH(DATA_WIDTH),.DATA_DEPTH(4))
i_current_state (.D(state_next[DATA_WIDTH-1:0]),
.WE(1'b1),
.clk(xclk),
.AW(sequence[3:0]),
// .AR(read_addr[3:0]),
.AR(reg_addr[3:0]),
.QW(state_current[DATA_WIDTH-1:0]),
.QR(rdo[DATA_WIDTH-1:0]));
endmodule
/// Combine old (freom register file) /new encoded periods, inc/dec pulses to prepare a 6-bit (partial) index for a RAM table.
/// Together with the position error (another 6 bits) the full 12-bit undex provides 1 4-bit PWM code from the RAM table
/// Updates direction immediately, period - if inc_dec or when new period > saved period (so it will be updated even if the motor is stopped)
module calc_speed (clk, // posedge, 80 MHz
en_in, // enable (just for simulation), for real - let it on even when motors are off
process, // increment (with limit) period
inc_dec, // encoder pulse detected
inc, // encoder position increment
dec, // encoder position decrement
enc_period_curr, // encoded current period (still running if !inc_dec)
dir_last, // last stored direction (from register file)
enc_period_last, // [4:0] last encoded period (from register file)
dir_this, // new value of direction to be stored in the register file and used in the index
enc_period_this // [4:0] encoded period for the register file/ table index
);
parameter IGNORE_EN=1;
input clk; // posedge, 80MHz
input en_in; // enable, 0 resets period counter - simulation only
input process; // increment (with limit) period
input inc_dec; // encoder pulse detected
input inc; // encoder position increment
input dec; // encoder position decrement
input [4:0] enc_period_curr; // encoded current period (still running if !inc_dec)
input dir_last; // last stored direction (from register file)
input [4:0] enc_period_last; // [4:0] last encoded period (from register file)
output dir_this; // new value of direction to be stored in the register file and used in the index
output [4:0] enc_period_this; // [4:0] encoded period for the register file/ table index
wire en=(IGNORE_EN)?1'b1:en_in; // will be overwritten, so en will be used in simulation only, ignored in synthesis
wire dir_this;
wire [4:0] enc_period_this;
wire [5:0] diff;
assign dir_this= en & (inc_dec?dec:dir_last);
assign diff[5:0]= {1'b0,enc_period_curr}-{1'b0,enc_period_last};
assign enc_period_this[4:0]= en ? ((diff[5] && !inc_dec)?enc_period_last[4:0]:enc_period_curr[4:0]):5'b0;
endmodule
module period_encoder (clk, // posedge, 80 MHz
en_in, // enable (just for simulation), for real - let it on even when motors are off
pre_first, // next whill be the first motor in a cycle (may use just spread bits)
process, // increment (with limit) period
inc_dec, // encoder pulse detected
cycle_div, // [11:0] clock divisor - nominally 1111 (0x457 ), 6KHz (6 cycles per encoder phase, full speed)
decr_on_pulse, // [4:0] decrease calculated period code by this amount after the encoder pulse. Normally - just 1?
period_cur, // [8:0] current period from register file,
period_new, // [8:0] updated period to be stored back to register file
encoded_period //4:0] encoded period (registered, valid 2 cycles after process
);
parameter IGNORE_EN=1;
input clk; // posedge, 80MHz
input en_in; // enable, 0 resets period counter - simulation only
input process; // increment (with limit) period
input pre_first; // next whill be the first motor in a cycle (may use just spread bits)
input inc_dec; // encoder pulse detected
input [11:0] cycle_div; // [11:0] clock divisor - nominally 1111 (0x457 ), 6KHz (6 cycles per encoder phase, full speed)
input [4:0] decr_on_pulse; // decrease calculated period code by this amount after the encoder pulse. Normally - just 1?
input [8:0] period_cur; // [8:0] current period from register file,
output [8:0] period_new; // [8:0] updated period to be stored back to register file
output [4:0] encoded_period; //4:0] encoded period (registered, valid 2 cycles after process
wire en=(IGNORE_EN)?1'b1:en_in; // will be overwritten, so en will be used in simulation only, ignored in synthesis
reg [11:0] prescaler;
reg inc_period;
wire [8:0] period_new;
wire [6:0] pri_enc;
reg [4:0] pre_enc_per; // valid next cycle, not decremented after the pulse
reg inc_dec_d; // next cycle after inc_dec
reg [4:0] encoded_period;
wire [5:0] decreased_pre_enc_per;
reg process_d;
// prescaler counter, inc_period should have frequency ~6 times (<8) higher than maximal encoder phase chnge frequency
always @ (posedge clk) if (pre_first) begin // change these registers once per cycle of all motors
prescaler= (!en || (prescaler==0))?cycle_div:(prescaler-1);
inc_period= en && (prescaler==0);
end
// assign period_new[8:0]=(inc_dec || !en)?9'h0:
assign period_new[8:0]=(inc_dec || !en)?{9{~en}}: /// reset to longest period (lowest speed)
((!inc_period || (period_cur[8:6]==3'h7))? period_cur[8:0]:(period_cur[8:0]+1));
assign pri_enc={period_cur[8],
(period_cur[8:7]==2'h1),
(period_cur[8:6]==3'h1),
(period_cur[8:5]==4'h1),
(period_cur[8:4]==5'h1),
(period_cur[8:3]==6'h1),
(period_cur[8:3]==6'h0)};
always @ (posedge clk) if (process) begin
pre_enc_per[4:0] <= {|pri_enc[6:3],
|pri_enc[6:5] | |pri_enc[2:1],
pri_enc[6] | pri_enc[4] | pri_enc[2] | (pri_enc[0] & period_cur[2]),
(pri_enc[6] & period_cur[7]) |
(pri_enc[5] & period_cur[6]) |
(pri_enc[4] & period_cur[5]) |
(pri_enc[3] & period_cur[4]) |
(pri_enc[2] & period_cur[3]) |
(pri_enc[1] & period_cur[2]) |
(pri_enc[0] & period_cur[1]),
(pri_enc[6] & period_cur[6]) |
(pri_enc[5] & period_cur[5]) |
(pri_enc[4] & period_cur[4]) |
(pri_enc[3] & period_cur[3]) |
(pri_enc[2] & period_cur[2]) |
(pri_enc[1] & period_cur[1]) |
(pri_enc[0] & period_cur[0]) };
inc_dec_d <= inc_dec;
end
assign decreased_pre_enc_per[5:0] = {1'b0,pre_enc_per[4:0]}-{1'b0,decr_on_pulse};
always @ (posedge clk) process_d <= process;
always @ (posedge clk) if (process_d) begin
encoded_period[4:0] <= inc_dec_d? (decreased_pre_enc_per[5]? 5'h0:decreased_pre_enc_per[4:0]):(pre_enc_per[4:0]);
end
endmodule
// 1 cycle - deglitch,
// 2-cycle - upgdate current position counter (register it)
// 3 cycle - read target position, subtract current
//1111 (0x457 )
module deglitch_encoder (clk, // posedge, 80 MHz
en_in, // enable (just for simulation), for real - let it on even when motors are off
process, // process data this cycle (store inc, dec)
pre_first, // next whill be the first motor in a cycle (may use just spread bits)
cycle_div, // [3:0] clock divisor - nominally 1/7 (80/4/3/7~=1MHz)
deglitch_cur, // [4:0] current value of deglitch counter for this channel , read from RAM
deglitch_new, // [4:0] next value of deglitch counter for this channel, to write to RAM
encoder, // [1:0] current encoder data
encoder_used, // [1:0] encoder data from RAM (deglitched)
encoder_new, // encoder data to RAM (deglitched)
pre_incdec, // combinatorial output, valid same cucle
inc, // increment position counter, registered. On top level apply inc/dec to the next cycle, not to the current
dec, // decrement position counter, registered
inc_dec // increment or decrement position counter, registered
);
parameter IGNORE_EN=1;
input clk; // posedge, 80MHz
input en_in; // enable, 0 turns off motors and resets counterts
input process; // process data this cycle (store inc, dec)
input pre_first; // next whill be the first motor in a cycle (may use just spread bits)
input [3:0] cycle_div; // [3:0] clock divisor - nominally 1/7 (80/4/3/7~=1MHz)
input [4:0] deglitch_cur; // [4:0] current value of deglitch counter for this channel , read from RAM
output [4:0] deglitch_new; // [4:0] next value of deglitch counter for this channel, to write to RAM
input [1:0] encoder; // current encoder data
input [1:0] encoder_used; // encoder data from RAM (deglitched)
output [1:0] encoder_new; // encoder data to RAM (deglitched)
output pre_incdec; // will increment/decrement position counter
output inc; // increment position counter
output dec; // decrement position counter
output inc_dec; // increment or decrement position counter, registered
wire en=(IGNORE_EN)?1'b1:en_in; // will be overwritten, so en will be used in simulation only, ignored in synthesis
wire [4:0] deglitch_new;
wire [1:0] encoder_new;
reg inc; // increment position counter
reg dec; // decrement position counter
reg inc_dec; // increment or decrement position counter, registered
reg [3:0] cycle_cntr;
reg deglitch_next;
wire pre_incdec;
// assign deglitch_new=(!en || (encoder[1:0]==encoder_used[1:0]))?0:((deglitch_cur==5'h1f)?5'h1f:(deglitch_cur+1));
assign deglitch_new=(!en || (encoder[1:0]==encoder_used[1:0]))?0:((deglitch_cur==5'h1f)?5'h1f:(deglitch_cur+deglitch_next));
assign encoder_new= (!en || (deglitch_cur==5'h1f))?encoder:encoder_used;
assign pre_incdec=en && (encoder_new[1:0]!=encoder_used[1:0]);
always @ (posedge clk) if (pre_first) begin // change these registers once per cycle of all motors
cycle_cntr= (!en || (cycle_cntr==0))?cycle_div:(cycle_cntr-1);
deglitch_next= en && (cycle_cntr==0);
end
always @ (posedge clk) if (process) begin
inc_dec <= pre_incdec;
dec<=en && ((encoder_new==2'b00) && (encoder_used==2'b01) ||
(encoder_new==2'b01) && (encoder_used==2'b11) ||
(encoder_new==2'b11) && (encoder_used==2'b10) ||
(encoder_new==2'b10) && (encoder_used==2'b00));
inc<=en && ((encoder_new==2'b00) && (encoder_used==2'b10) ||
(encoder_new==2'b10) && (encoder_used==2'b11) ||
(encoder_new==2'b11) && (encoder_used==2'b01) ||
(encoder_new==2'b01) && (encoder_used==2'b00));
// cycle_cntr<= (!en || (cycle_cntr==0))?cycle_div:(cycle_cntr-1);
// deglitch_next<= en && (cycle_cntr==0);
end
endmodule
module motor_pwm( clk, // posedge, 80MHz
en, // enable, 0 turns off motors and resets counterts
pre_first,// next whill be the first motor in a cycle (may use just spread bits)
pwm_delay,// [2:0] - turns off bridge during transition (i.e. 10->00->11->00->10 ..). Nominal 0.3usec - 2 (0x18) cycles (80/4/3=6.66MHz)
pwm_cycle,// [7:0] - pwm cycle duration Nominal 10usec or 67 (0x43) 6.66MHz cycles. Total PWM period will be 8 of these cycles
spread, // [2:0] shift on phase between motors, adds this number to the current phase (use just 2 MSBs for 3 motors)
cur_pwm, // [2:0] - PWM data stored in per-motor memory. [1] - 'on', [0] direction, [2] - enable. That bit is used to turn off motor during PWM transitions
pwm_code, // [3:0] - code from the RAM. 0x8 - stop, , otherwise [3] - direction, [2:0]/8 - duty cycle (8 - 100% on), 0 - 0%, 1 - 25%, 3 - 37.5%...
new_pwm, // [2:0]
mot // [1:0] - data to be copied to the motor outputs
);
input clk; // posedge, 80MHz
input en; // enable, 0 turns off motors and resets counterts
input pre_first;// next whill be the first motor in a cycle (may use just spread bits)
input [2:0] pwm_delay;// [2:0] - turns off bridge during transition (i.e. 10->00->11->00->10 ..). Nominal 0.3usec - 24 (0x18) cycles
input [7:0] pwm_cycle;// [7:0] - pwm cycle duration Nominal 10usec oror 67 (0x43) 6.66MHz cycles. Total PWM period will be 8 of these cycles
input [2:0] spread; // [2:0] shift on phase between motors, adds this number to the current phase (use just 2 MSBs for 3 motors)
input [2:0] cur_pwm; // [2:0] - PWM data stored in per-motor memory. [1:0] - motors, [2] - enable. That bit is used to turn off motor during PWM transitions
input [3:0] pwm_code; // [3:0] - code from the RAM. 0x8 - stop , otherwise [3] - direction, [2:0]/7 - duty cycle (7 - 100% on)
output [2:0] new_pwm; // [2:0]
output [1:0] mot; // [1:0] - data to be copied to the motor outputs
reg [9:0] pwm_cycle_count;
reg pwm_cycle_next;
reg [3:0] pwm_delay_count;
reg pwm_delay_end;
reg [2:0] pwm_phase;
wire [2:0] spreaded_phase;
wire pwn_on;
wire pwn_off;
wire [2:0] new_pwm;
wire stop_cmd;
wire [3:0] pwm_diff;
wire [1:0] mot;
assign spreaded_phase[2:0]= pwm_phase[2:0]+spread[2:0];
assign pwn_on= pwm_cycle_next && (spreaded_phase == 0) && (pwm_code != 0);
assign pwn_off=pwm_cycle_next && (spreaded_phase == pwm_code);
assign stop_cmd= !en || (pwm_code==8) ;
assign pwm_diff[3:0]={1'b0,pwm_code[2:0]}-{1'b0,spreaded_phase[2:0]};
assign new_pwm[0]=!stop_cmd && (pwm_cycle_next? pwm_code[3] : cur_pwm[0]); // direction
assign new_pwm[1]=!stop_cmd && (pwm_cycle_next?((pwm_code[2:0]!=0) && !pwm_diff[3]):cur_pwm[1]); // turn off (by en) immediately, others - only at pwm_cycle_next;
assign new_pwm[2]=!en || (pwm_cycle_next? (new_pwm[1:0]!=cur_pwm[1:0]):(cur_pwm[2]&& !pwm_delay_end));
assign mot[1:0]=(stop_cmd || new_pwm[2])? 2'b0:(new_pwm[1]?{new_pwm[0],!new_pwm[0]}:2'b11);
always @ (posedge clk) if (pre_first) begin // change these registers once per cycle of all motors
pwm_cycle_count<= (!en || (pwm_cycle_count==0))?pwm_cycle:(pwm_cycle_count-1);
pwm_cycle_next<= en && (pwm_cycle_count==0);
// pwm_delay_count<= (!en || (pwm_delay_count==0))?0:(pwm_cycle_next?pwm_delay: (pwm_delay_count-1));
pwm_delay_count<= (!en || pwm_cycle_next)?pwm_delay:((pwm_delay_count==0)?0: (pwm_delay_count-1));
pwm_delay_end<= en && (pwm_delay_count==1);
pwm_phase<= (!en)? 0: (pwm_phase + pwm_cycle_next); // divide by 8
end
endmodule
/*
** -----------------------------------------------------------------------------**
** camsync.v
**
** Synchronization between cameras using GPIO lines on th 10353 board:
** - triggering from selected line(s) with filter;
** - programmable delay to actual trigger (in pixel clock periods)
** - Generating trigger output to selected GPIO line (and polarity)
** or directly to the input delay generator (see bove)
** - single/repetitive output with specified period in pixel clocks
**
** Copyright (C) 2007 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 camsync (sclk, // @negedge
pre_wen, // 1 cycle ahead of write data
// di, // [31:0] data in
di, // [15:0] data in
wa, // [1:0] write address
// 0 - source of trigger (12 bit pairs, LSB - level to trigger, MSB - use this bit). All 0 - internal trigger
// in internal mode output has variable delay from the internal trigger (relative to sensor trigger)
// 1 - input trigger delay (pixel clocks) (NOTE: 0 - trigger disabled - WRONG)
// 2 - 24 bit pairs: MSB - enable selected line, LSB - level to send when trigger active
// bit 25==1 some of the bits use test mode signals:
// 3 - output trigger period (duration constant of 256 pixel clocks).
// d==0 - disable (stop periodic mode)
// d==1 - single trigger
// d==2..255 - set output pulse / input-output serial bit duration (no start generated)
// 256>=d - repetitive trigger
pclk, // pixel clock (global)
triggered_mode, // use triggered mode (0 - sensor is free-running)
trigrst, // single-clock start of frame input (resets trigger output) posedge
gpio_in, // 12-bit input from GPIO pins
gpio_out,// 12-bit output to GPIO pins
gpio_out_en,// 12-bit output enable to GPIO pins
trigger1, // 1 cycle-long trigger output
trigger, // active high trigger to the sensor (reset by vacts)
overdue, // prevents lock-up when no vact was detected during one period and trigger was toggled
ts_snd_en, // enable sending timestamp over sync line
ts_external, // 1 - use external timestamp, if available. 0 - always use local ts
ts_snap, // make a timestamp pulse single @(posedge pclk)
// timestamp should be valid in <16 pclk cycles
ts_snd_sec, // [31:0] timestamp seconds to be sent over the sync line
ts_snd_usec, // [19:0] timestamp microseconds to be sent over the sync line
ts_rcv_sec, // [31:0] timestamp seconds received over the sync line
ts_rcv_usec,// [19:0] timestamp microseconds received over the sync line
ts_stb); // strobe when received timestamp is valid
parameter PRE_MAGIC= 6'b110100;
parameter POST_MAGIC=6'b001101;
input sclk;
input pre_wen;
// input [31:0] di;
input [15:0] di;
input [ 1:0] wa;
input pclk;
input triggered_mode; // use triggered mode (0 - sensor is free-running)
input trigrst; //vacts;
input [11:0] gpio_in;
output [11:0] gpio_out;
output [11:0] gpio_out_en;
output trigger1;
output trigger;
output overdue;
input ts_snd_en; // enable sending timestamp over sync line
input ts_external; // 1 - use external timestamp, if available. 0 - always use local ts
output ts_snap; // make a timestamp pulse (from the internal generator
// timestamp should be valid in <16 pclk cycles
input [31:0] ts_snd_sec; // [31:0] timestamp seconds to be sent over the sync line
input [19:0] ts_snd_usec; // [19:0] timestamp microseconds to be sent over the sync line
output [31:0] ts_rcv_sec; // [31:0] timestamp seconds received over the sync line
output [19:0] ts_rcv_usec;// [19:0] timestamp microseconds received over the sync line
output ts_stb; // strobe when received timestamp is valid
// delaying everything by 1 clock to reduce data fan in
reg [1:0] wad;
reg [31:0] did;
reg pre_wend;
reg [3:0] wen;
reg high_zero; // 24 MSBs are zero
reg [11:0] input_use; // 1 - use this bit
reg [11:0] input_pattern; // data to be compared for trigger event to take place
reg pre_input_use_intern;// @(negedge sclk) Use internal trigger generator, 0 - use external trigger (also switches delay from input to output)
reg input_use_intern;// @(posedge clk)
reg [31:0] input_dly; // delay value for the trigger
reg [11:0] gpio_out_en; // which GPIO lines to drive
reg [11:0] gpio_active; // output levels on the selected GPIO lines during output pulse (will be negated when inactive)
reg testmode; // drive some internal signals to GPIO bits
reg outsync; // during output active
reg out_data; // output data (modulated with timestamp if enabled)
reg [31:0] repeat_period; // restart period in repetitive mode
reg start,start_d; // start single/repetitive output pulse(s)
reg rep_en; // enable repetitive mode
reg start_en;
wire start_to_pclk;
reg [2:0] start_pclk; // start and restart
reg [31:0] restart_cntr; // restart period counter
reg [1:0] restart_cntr_run; // restart counter running
wire restart; // restart out sync
reg [8:0] out_pulse_cntr;
reg trigger_condition; // GPIO input trigger condition met
reg trigger_condition_d; // GPIO input trigger condition met, delayed (for edge detection)
reg trigger_condition_filtered; // trigger condition filtered
// reg trigger_condition_filtered_d; // trigger condition filtered, delayed (for edge detection)
reg [6:0] trigger_filter_cntr;
reg trigger1;
wire trigger1_dly16; // trigger1 delayed by 16 clk cycles to get local timestamp
// reg trigger;
wire trigger; // for happy simulator
reg overdue;
reg start_dly; // start delay (external input filtered or from internal single/rep)
reg [31:0] dly_cntr; // trigger delay counter
// reg dly_cntr_run; // trigger delay counter running
wire dly_cntr_run; // trigger delay counter running (to use FD for simulation)
reg dly_cntr_run_d; // trigger delay counter running - delayed by 1
wire pre_start_out_pulse;
reg start_out_pulse; /// start generation of output pulse. In internal trigger mode uses delay counter, in external - no delay
reg pre_start;
reg [31:0] pre_period;
reg [ 7:0] bit_length='hff; /// Output pulse duration or bit duration in timestamp mode
/// input will be filtered with (bit_length>>2) duration
wire [ 7:0] bit_length_plus1; // bit_length+1
reg [ 7:0] bit_length_short; /// 3/4 bit duration, delay for input strobe from the leading edge.
wire pre_start0;
reg start0;
wire pre_set_bit;
reg set_bit;
wire pre_set_period;
reg set_period;
wire start_pclk16 ;// delayed start to wait for time stamp to be available
reg [31:0] sr_snd_first;
reg [31:0] sr_snd_second;
reg [31:0] sr_rcv_first;
reg [31:0] sr_rcv_second;
reg [ 7:0] bit_snd_duration;
reg [ 5:0] bit_snd_counter;
reg [ 7:0] bit_rcv_duration;
reg bit_rcv_duration_zero; // to make it faster, duration always >=2
reg [ 6:0] bit_rcv_counter; // includes "deaf" period ater receving
reg bit_snd_duration_zero; //
// input ts_snd_en; // enable sending timestamp over sync line
reg ts_snd_en_pclk;
reg [31:0] ts_rcv_sec; // timestamp seconds received over the sync line
reg [19:0] ts_rcv_usec; // timestamp microseconds received over the sync line
reg rcv_run_or_deaf; // counters active
wire rcv_run; // receive in progress, will always last for 64 bit_length+1 intervals before ready for the new input pulse
reg rcv_run_d;
reg rcv_done_rq; // request to copy time stamp (if it is not ready yet)
reg rcv_done_rq_d;
reg rcv_done; /// rcv_run ended, copy timestamp if requested
// reg rcv_deaf; // would not accept new trigger until this is over
// reg rcv_run_or_deaf; // counters active
wire pre_rcv_error; // pre/post magic does not match, set ts to all ff-s
reg rcv_error;
reg ts_external_pclk; // 1 - use external timestamp (combines ts_external and input_use_intern)
reg triggered_mode_pclk;
reg ts_snap;
reg ts_stb; // strobe when received timestamp is valid (single sclk cycle)
wire ts_stb_pclk;
reg [2:0] ts_pre_stb;
//! in testmode GPIO[11] and GPIO[10] use internal signals instead of the outsync:
//! bit 11 - same as TRIGGER output to the sensor (signal to the sensor may be disabled externally)
//! then that bit will be still from internall trigger to frame valid
//! bit 10 - dly_cntr_run (delay counter run) - active during trigger delay
assign rcv_run=rcv_run_or_deaf && bit_rcv_counter[6];
assign bit_length_plus1 [ 7:0] =bit_length[7:0]+1;
assign pre_start_out_pulse=input_use_intern?(dly_cntr_run_d && !dly_cntr_run):start_pclk16;
assign gpio_out[9: 0] = out_data? gpio_active[9: 0]: ~gpio_active[9: 0];
assign gpio_out[10] = (testmode? dly_cntr_run: out_data)? gpio_active[10]: ~gpio_active[10];
assign gpio_out[11] = (testmode? trigger: out_data)? gpio_active[11]: ~gpio_active[11];
assign restart= restart_cntr_run[1] && !restart_cntr_run[0];
assign pre_set_bit= (|did[31:8]==0) && |did[7:1]; // 2..255
assign pre_start0= |did[31:0] && !pre_set_bit;
assign pre_set_period = !pre_set_bit;
always @ (negedge sclk) begin
pre_wend <= pre_wen;
if (pre_wen) wad[1:0] <= wa[1:0];
if (pre_wen) did[15: 0] <= di[15:0];
if (pre_wend) did[31:16] <= di[15:0];
wen[3:0] <= pre_wend?{(wad[1:0]==2'h3),(wad[1:0]==2'h2),(wad[1:0]==2'h1),(wad[1:0]==2'h0)}:4'b0;
if (wen[0]) input_use[11:0] <= {did[23],did[21],did[19],did[17],did[15],did[13],did[11],did[9],did[7],did[5],did[3],did[1]};
pre_input_use_intern <= (input_use[11:0]==12'h0); // use internal source for triggering
if (wen[0]) input_pattern[11:0] <= {did[22],did[20],did[18],did[16],did[14],did[12],did[10],did[8],did[6],did[4],did[2],did[0]};
if (wen[1]) input_dly[31:0] <= did[31:0];
if (wen[2]) gpio_out_en[11:0] <= {did[23],did[21],did[19],did[17],did[15],did[13],did[11],did[9],did[7],did[5],did[3],did[1]};
if (wen[2]) gpio_active[11:0] <= {did[22],did[20],did[18],did[16],did[14],did[12],did[10],did[8],did[6],did[4],did[2],did[0]};
if (wen[2]) testmode <= did[24];
// if (wen[3]) repeat_period[31:0] <= did[31:0];
if (wen[3]) pre_period[31:0] <= did[31:0];
if (wen[3]) high_zero = did[31:8]==24'b0;
// start <= wen[3] && (did[31:0]!=32'h0);
start0 <= wen[3] && pre_start0;
set_bit <= wen[3] && pre_set_bit;
set_period <= wen[3] && pre_set_period;
if (set_period) repeat_period[31:0] <= pre_period[31:0];
if (set_bit) bit_length[7:0] <= pre_period[ 7:0];
start <= start0;
start_d <= start;
start_en <= (repeat_period[31:0]!=0);
if (set_period) rep_en <= !high_zero;
end
MSRL16 i_start_pclk16 (.Q(start_pclk16), .A('hf), .CLK(pclk), .D(start_pclk[2]));
MSRL16 i_strigger1_dly16(.Q(trigger1_dly16), .A('hf), .CLK(pclk), .D(trigger1));
//! synchronize start from sclk to pclk
//! Generating repetition (period should be exactly N, not N+/-1) and output pulse
FDCE_1 i_start_to_pclk (.C(sclk), .CE(start_d),.CLR(start_pclk[1] || !start_en),.D(1'b1),.Q(start_to_pclk));
always @ (posedge pclk) begin
ts_snap <= (start_pclk[2] && ts_snd_en_pclk) || //strobe by internal generator if output timestamp is enabled
(trigger1 && !ts_external_pclk); // get local timestamp of trigger1 if it is used
ts_snd_en_pclk<=ts_snd_en;
input_use_intern <= pre_input_use_intern;
ts_external_pclk<= ts_external && !input_use_intern;
// start_pclk[1:0] <= {start_pclk[0] || (restart && rep_en), start_to_pclk && !start_pclk[0]};
start_pclk[2:0] <= {(restart && rep_en) || (start_pclk[1] && !restart_cntr_run[1] && !restart_cntr_run[0] && !start_pclk[2]),
start_pclk[0],
start_to_pclk && !start_pclk[0]};
restart_cntr_run[1:0] <= {restart_cntr_run[0],start_en && (start_pclk[2] || (restart_cntr_run[0] && (restart_cntr[31:2] !=0)))};
if (restart_cntr_run[0]) restart_cntr[31:0] <= restart_cntr[31:0] - 1;
else restart_cntr[31:0] <= repeat_period[31:0];
start_out_pulse <= pre_start_out_pulse;
/// Generating output pulse - 64* bit_length if timestamp is disabled or
/// 64 bits with encoded timestamp, including pre/post magic for error detectrion
outsync <= start_en && (start_out_pulse || (outsync && !((bit_snd_duration[7:0]==0) &&(bit_snd_counter[5:0]==0))));
if (!outsync || (bit_snd_duration[7:0]==0)) bit_snd_duration[7:0] <= bit_length[7:0];
else bit_snd_duration[7:0] <= bit_snd_duration[7:0] - 1;
bit_snd_duration_zero <= bit_snd_duration[7:0]==8'h1;
if (!outsync) bit_snd_counter[5:0] <=ts_snd_en_pclk?63:3; /// when no ts serial, send pulse 4 periods long (max 1024 pclk)
/// Same bit length (1/4) is used in input filter/de-glitcher
else if (bit_snd_duration[7:0]==0) bit_snd_counter[5:0] <= bit_snd_counter[5:0] -1;
if (!outsync) sr_snd_first[31:0] <= {PRE_MAGIC,ts_snd_sec[31:6]};
// else if (bit_snd_duration[7:0]==0) sr_snd_first[31:0] <={sr_snd_first[30:0],sr_snd_second[31]};
else if (bit_snd_duration_zero) sr_snd_first[31:0] <={sr_snd_first[30:0],sr_snd_second[31]};
if (!outsync) sr_snd_second[31:0] <= {ts_snd_sec[5:0], ts_snd_usec[19:0],POST_MAGIC};
// else if (bit_snd_duration[7:0]==0) sr_snd_second[31:0] <={sr_snd_second[30:0],1'b0};
else if (bit_snd_duration_zero) sr_snd_second[31:0] <={sr_snd_second[30:0],1'b0};
out_data <=outsync && (ts_snd_en_pclk?sr_snd_first[31]:1'b1);
end
// Detecting input sync pulse (filter - 64 pclk, pulse is 256 pclk)
// FD i_dly_cntr_run (.C(pclk),.D(start_dly || (dly_cntr_run && (dly_cntr[31:0]!=0))),.Q(dly_cntr_run)); // for simulator to be happy
// even more for simulator
FD i_dly_cntr_run (.C(pclk),.D(triggered_mode && (start_dly || (dly_cntr_run && (dly_cntr[31:0]!=0)))),.Q(dly_cntr_run)); // for simulator to be happy
// FD i_trigger (.C(pclk),.D(trigger1 || (trigger && !trigrst)), .Q(trigger)); // for simulator to be happy
/// Now trigger1 toggles trigger output to prevent lock-up if no vacts
/// Lock-up could take place if:
/// 1 - Sesnoris in snapshot mode
/// 2 - trigger was applied before end of previous frame.
/// With implemented toggling 1 extra pulse can be missed (2 with the original missed one), but the system will not lock-up
/// if the trigger pulses continue to come.
assign pre_rcv_error= (sr_rcv_first[31:26]!=PRE_MAGIC) || (sr_rcv_second[5:0]!=POST_MAGIC);
FD i_trigger (.C(pclk),.D(trigrst?1'b0:(trigger1 ^ trigger)), .Q(trigger)); // for simulator to be happy
always @ (posedge pclk) begin
if (trigrst) overdue <= 1'b0;
else if (trigger1) overdue <= trigger;
triggered_mode_pclk<= triggered_mode;
bit_length_short[7:0] <= bit_length[7:0]-bit_length_plus1[7:2]-1; // 3/4 of the duration
trigger_condition <= (((gpio_in[11:0] ^ input_pattern[11:0]) & input_use[11:0]) == 12'b0);
trigger_condition_d <= trigger_condition;
if (!triggered_mode || (trigger_condition !=trigger_condition_d)) trigger_filter_cntr <= {1'b0,bit_length[7:2]};
else if (!trigger_filter_cntr[6]) trigger_filter_cntr<=trigger_filter_cntr-1;
if (input_use_intern) trigger_condition_filtered <= 1'b0;
else if (trigger_filter_cntr[6]) trigger_condition_filtered <= trigger_condition_d;
rcv_run_or_deaf <= start_en && (trigger_condition_filtered ||
// (rcv_run_or_deaf && !((bit_rcv_duration[7:0]==0) &&(bit_rcv_counter[6:0]==0))));
(rcv_run_or_deaf && !(bit_rcv_duration_zero && (bit_rcv_counter[6:0]==0))));
rcv_run_d <= rcv_run;
start_dly <= input_use_intern ? (start_pclk16 && start_en) : (rcv_run && !rcv_run_d);
// simulation problems w/o "start_en &&" ?
dly_cntr_run_d <= dly_cntr_run;
if (dly_cntr_run) dly_cntr[31:0] <= dly_cntr[31:0] -1;
else dly_cntr[31:0] <= input_dly[31:0];
trigger1 <= input_use_intern ? (start_pclk16 && start_en):(dly_cntr_run_d && !dly_cntr_run);/// bypass delay to trigger1 in internal trigger mode
/// 64-bit serial receiver (52 bit payload, 6 pre magic and 6 bits post magic for error checking
if (!rcv_run_or_deaf) bit_rcv_duration[7:0] <= bit_length_short[7:0]; // 3/4 bit length-1
else if (bit_rcv_duration[7:0]==0) bit_rcv_duration[7:0] <= bit_length[7:0]; // bit length-1
else bit_rcv_duration[7:0] <= bit_rcv_duration[7:0]-1;
bit_rcv_duration_zero <= bit_rcv_duration[7:0]==8'h1;
if (!rcv_run_or_deaf) bit_rcv_counter[6:0] <= 127;
// else if (bit_rcv_duration[7:0]==0) bit_rcv_counter[6:0] <= bit_rcv_counter[6:0] -1;
else if (bit_rcv_duration_zero) bit_rcv_counter[6:0] <= bit_rcv_counter[6:0] -1;
// if (rcv_run && (bit_rcv_duration[7:0]==0)) begin
if (rcv_run && bit_rcv_duration_zero) begin
sr_rcv_first[31:0] <={sr_rcv_first[30:0],sr_rcv_second[31]};
sr_rcv_second[31:0] <={sr_rcv_second[30:0],trigger_condition_filtered};
end
rcv_done_rq <= start_en && ((ts_external_pclk && trigger1_dly16) || (rcv_done_rq && rcv_run));
rcv_done_rq_d <= rcv_done_rq;
rcv_done <= rcv_done_rq_d && !rcv_done_rq;
// triggered_mode_pclk<= triggered_mode;
rcv_error <= pre_rcv_error;
if (rcv_done) begin
ts_rcv_sec [31:0] <= {sr_rcv_first[25:0],sr_rcv_second[31:26]};
ts_rcv_usec [19:0] <= rcv_error?20'hfffff: sr_rcv_second[25:6];
end else if (!triggered_mode_pclk || (!ts_external_pclk && trigger1_dly16 )) begin
ts_rcv_sec [31:0] <= ts_snd_sec [31:0];
ts_rcv_usec [19:0] <= ts_snd_usec[19:0];
end
// ts_stb<= rcv_done || (!ts_external_pclk && trigger1_dly16 ); // strobe when received timestamp is valid
end
FDCE i_ts_stb_pclk (.C(pclk), .CE(rcv_done || (!ts_external_pclk && trigger1_dly16 )),.CLR(ts_stb),.D(1'b1),.Q(ts_stb_pclk));
always @ (negedge sclk) begin
ts_pre_stb[2:0] <= {ts_pre_stb[1:0],ts_stb_pclk};
ts_stb <= ts_pre_stb[1] && !ts_pre_stb[2];
end
endmodule
/*
** -----------------------------------------------------------------------------**
** clkios353.v
**
** I/O pads related circuitry
**
** Copyright (C) 2002-2006 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// Some placement constraints are in this file
module dcm333(
sclk, // input global clock, 120MHz, phase=0
SDCLK, // positive clock to SDRAM
SDNCLK, // negative clock to SDRAM
sdcl_fb,
xclk, // 60MHz for compressor
phsel, // additional phase control for SDRAM CLK
dcm_rst, // reset DCM phase
dcm_incdec, // variable phase control to adjust SDCLK so read DQS is aligned with sclk90/sclk270
dcm_en,
dcm_clk,
dcm_done,
locked, // dcm locked
status // dcm status (bit 1 - dcm clkin stopped)
);
input sclk;
output xclk;
output SDCLK, SDNCLK;
input [1:0] phsel;
input sdcl_fb;
input dcm_rst, dcm_incdec, dcm_en, dcm_clk;
output dcm_done;
output [7:0] status; // dcm status (bit 1 - dcm clkin stopped)
output locked; // dcm locked
wire isdclk0, isdclk90, isdclk180, isdclk270;
wire ixclk;
wire gsdclk; //used only for the feedback
wire isdclk;
reg dcm_done;
wire dcm_done_dcm; // single-cycle
assign isdclk=phsel[1]? (phsel[0]?isdclk270:isdclk180):(phsel[0]?isdclk90:isdclk0);
FD i_ixclk (.C(sclk), .D(!ixclk), .Q(ixclk));
BUFG i_xclk (.I(ixclk), .O(xclk));
// second - adjustable DCM. Will be adjusted so read DQS (dependent on SDCLK) will be aligned with sclk90/270
// maybe will need some delay as there is DLL in SDRAM and responce may be slow.
DCM i_dcm2(
.CLKIN (sclk),
.CLKFB (isdclk90),
.RST (dcm_rst),
.PSEN (dcm_en),
.PSINCDEC (dcm_incdec),
.PSCLK (dcm_clk),.DSSEN (1'b0),
// .CLK0 (isdclk0),
// .CLK90 (isdclk90),
// .CLK180 (isdclk180),
// .CLK270 (isdclk270),
.CLK0 (isdclk90),
.CLK90 (isdclk180),
.CLK180 (isdclk270),
.CLK270 (isdclk0),
.CLKDV (),
.CLK2X (),
.CLK2X180 (),
.CLKFX (),
.CLKFX180 (),
.STATUS (status[7:0]),
.LOCKED (locked),
.PSDONE (dcm_done_dcm));
// s-ynthesis attribute loc of i_dcm2 is "DCM_X1Y1"
// synthesis attribute CLK_FEEDBACK of i_dcm2 is "1X"
// synthesis attribute CLKIN_DIVIDE_BY_2 of i_dcm2 is "FALSE"
// synthesis attribute CLKIN_PERIOD of i_dcm2 is 8.33333
// synthesis attribute CLKOUT_PHASE_SHIFT of i_dcm2 is "VARIABLE"
// synthesis attribute DESKEW_ADJUST of i_dcm2 is "SYSTEM_SYNCHRONOUS"
// synthesis attribute DLL_FREQUENCY_MODE of i_dcm2 is "LOW"
// synthesis attribute DUTY_CYCLE_CORRECTION of i_dcm2 is "TRUE"
// put here default phase shift ....
// synthesis attribute PHASE_SHIFT of i_dcm2 is 0
// synthesis translate_off
defparam i_dcm2.CLK_FEEDBACK="1X";
defparam i_dcm2.CLKIN_DIVIDE_BY_2="FALSE";
defparam i_dcm2.CLKIN_PERIOD=8.33333;
defparam i_dcm2.CLKOUT_PHASE_SHIFT="VARIABLE";
defparam i_dcm2.DESKEW_ADJUST="SYSTEM_SYNCHRONOUS";
defparam i_dcm2.DLL_FREQUENCY_MODE="LOW";
defparam i_dcm2.DUTY_CYCLE_CORRECTION="TRUE";
defparam i_dcm2.PHASE_SHIFT=0;
// synthesis translate_on
// BUFG i_gsdclk (.I(isdclk90), .O(gsdclk));
OBUFDS i_SDCLK (.O(SDCLK),.OB(SDNCLK),.I(isdclk));
// OBUFDS i_SDCLK (.O(SDNCLK),.OB(SDCLK),.I(!isdclk));
// make dcm_done behave as dcm_ready
always @ (posedge dcm_clk or posedge dcm_rst)
if (dcm_rst) dcm_done <= 1'b1;
else if (dcm_en) dcm_done <=1'b0;
else if (dcm_done_dcm) dcm_done <=1'b1;
endmodule
module clockios353(
CLK0, // input clock pad - 120MHz
sclk0, // global clock, 120MHz, phase=0 (addresses, commands should be strobed at neg edge)
/*sclk90,*/ // global clock, 120MHz, phase=90 (strobe data write to sdram)
sclk180, // global clock, 120MHz, phase=180 (just to generate DQS :-( )
sclk270, // global clock, 120MHz, phase=270 (strobe data write to sdram)
iclk0, //before BUFG
dcmrst, //reset dcm
locked, // dcm locked
status // dcm status (bit 1 - dcm clkin stopped)
);
input CLK0;
output sclk0,/*sclk90,*/sclk270,sclk180;
output iclk0;
input dcmrst; //reset dcm
output [7:0] status; // dcm status (bit 1 - dcm clkin stopped)
output locked; // dcm locked
wire iclk0;
wire isclk0, /*isclk90,*/ isclk270, isclk180;
IBUFG i_iclk0 (.I(CLK0), .O(iclk0));
// DCM - just 4 phases out
DCM i_dcm1(
.CLKIN (iclk0),
.CLKFB (sclk0),
.RST (dcmrst), .PSEN (1'b0),.PSINCDEC (1'b0), .PSCLK (1'b0),.DSSEN (1'b0),
.CLK0 (isclk0),
.CLK90 (/*isclk90*/),
.CLK180 (isclk180),
.CLK270 (isclk270),
.CLKDV (),
.CLK2X (),
.CLK2X180 (),
.CLKFX (),
.CLKFX180 (),
.STATUS (status[7:0]),
.LOCKED (locked),
.PSDONE ());
// s- ynthesis attribute loc of i_dcm1 is "DCM_X0Y0"
// synthesis attribute CLK_FEEDBACK of i_dcm1 is "1X"
// synthesis attribute CLKIN_DIVIDE_BY_2 of i_dcm1 is "FALSE"
// synthesis attribute CLKIN_PERIOD of i_dcm1 is 8.33333
// synthesis attribute DESKEW_ADJUST of i_dcm1 is "SYSTEM_SYNCHRONOUS"
// synthesis attribute DLL_FREQUENCY_MODE of i_dcm1 is "LOW"
// synthesis attribute DUTY_CYCLE_CORRECTION of i_dcm1 is "TRUE"
// synthesis translate_off
defparam i_dcm1.CLK_FEEDBACK="1X";
defparam i_dcm1.CLKIN_DIVIDE_BY_2="FALSE";
defparam i_dcm1.CLKIN_PERIOD=8.33333;
defparam i_dcm1.DESKEW_ADJUST="SYSTEM_SYNCHRONOUS";
defparam i_dcm1.DLL_FREQUENCY_MODE="LOW";
defparam i_dcm1.DUTY_CYCLE_CORRECTION="TRUE";
// synthesis translate_on
BUFG i_sclk0 (.I(isclk0),. O(sclk0));
// s-ynthesis attribute loc of i_sclk0 is "BUFGMUX0"
/* BUFG i_sclk90 (.I(isclk90), .O(sclk90)); */
// s-ynthesis attribute loc of i_sclk90 is "BUFGMUX1"
BUFG i_sclk180(.I(isclk180),.O(sclk180));
// s-ynthesis attribute loc of i_sclk180 is "BUFGMUX2"
BUFG i_sclk270(.I(isclk270),.O(sclk270));
// s-ynthesis attribute loc of i_sclk270 is "BUFGMUX3"
endmodule
/*
module clock_pclk( clk0, // global clock (phase =0)
CLK1, // external input clock
pclk, // global clock, sensor pixel rate
clk_en, // enable clock output to sensor
pclk_src,// [3:0] - source fror the pclk
dclk); // clock output to sensor (sync to pclk)
input CLK1,clk0,clk_en;
input [3:0] pclk_src;
output pclk,dclk;
wire ipclk,dclk,pclk;
reg clk_en_r;
IBUF i_iclk1 (.I(CLK1), .O(iclk1));
// and global clock (divided by 1, 1.5,2,...,8)
pclk_cntrl i_pclk_cntrl(.ext_clk(iclk1), // external clock, may be stopped (will wait for up to 16 clk periods?)
.clk(clk0), // always running global clock
.div(pclk_src[3:0]), // 0: q=ext_clk
// 1: q=clk - temporary made clk/1.5 - not to fry MI1300
// 2: q=clk/1.5
//...0'hf: q=clk/8
.q(ipclk)); // output clock
always @ (posedge pclk) clk_en_r<=clk_en;
assign dclk=!clk_en_r || !ipclk;
BUFG i_pclk (.I(ipclk), .O(pclk));
endmodule
// switches between external clock (no divisor)
// and global clock (divided by 1, 1.5,2,...,8)
module pclk_cntrl(ext_clk, // external clock, may be stopped (will wait for up to 16 clk periods?)
clk, // always running global clock
div, // 0: q=ext_clk
// 1: q=clk - temporary made clk/1.5 - not to fry MI1300
// 2: q=clk/1.5
//...0'hf: q=clk/8
q); // output clock
input ext_clk;
input clk;
input [3:0] div;
output q;
reg ena;
reg enb;
// reg clksel;
wire [3:0] div_p;
wire blank;
wire copy_div,blank_off;
wire a_on, a_off0, b_on, b_off;
reg [3:0] da0; // from a_start to a_on
reg [3:0] da1; // from a_on to a_off
reg [3:0] db0; // from a_start to a_on
reg [3:0] db1; // from a_on to a_off
reg a_start;
reg b_start;
reg a_off;
reg a_singleon; // a stays on for 1 cycle;
reg use_b;
wire a,b,ab;
FDE i_div_p0 (.C(clk),.CE(copy_div),.D(div[0]),.Q(div_p[0]));
FDE i_div_p1 (.C(clk),.CE(copy_div),.D(div[1]),.Q(div_p[1]));
FDE i_div_p2 (.C(clk),.CE(copy_div),.D(div[2]),.Q(div_p[2]));
FDE i_div_p3 (.C(clk),.CE(copy_div),.D(div[3]),.Q(div_p[3]));
always @ (posedge enb or posedge ext_clk) begin
if (enb) ena <=1'b0;
else ena <= (div[3:0]==4'b0);
end
always @ (posedge clk) begin
enb <= (div_p[3:0]!=4'b0);
a_off <= a_singleon?a_on:a_off0;
a_start <= blank_off || (!blank && (a_singleon?a_on:a_off0));
end
always @ (negedge clk) begin
b_start <= a_start;
use_b <= (div_p[3:0]!=4'h0) && (div_p[1:0]!=2'h3);
end
FD i_blank (.C(clk),.D((div[3:0] != div_p[3:0]) || (blank && !blank_off)),.Q(blank)); // add always blank if (div==0)? no!
SRL16 i_copy_div (.Q(copy_div),.D((div[3:0] != div_p[3:0]) && !blank), .CLK(clk), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b1)); // dly=max (16)
SRL16 i_blank_off(.Q(blank_off),.D(copy_div), .CLK(clk), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0)); // 2
SRL16 i_a_on (.Q(a_on), .D(a_start), .CLK(clk), .A0(da0[0]), .A1(da0[1]), .A2(da0[2]), .A3(da0[3]));
SRL16 i_a_off0(.Q(a_off0),.D(a_on), .CLK(clk), .A0(da1[0]), .A1(da1[1]), .A2(da1[2]), .A3(da1[3]));
SRL16_1 i_b_on (.Q(b_on), .D(b_start), .CLK(clk), .A0(db0[0]), .A1(db0[1]), .A2(db0[2]), .A3(db0[3]));
SRL16_1 i_b_off (.Q(b_off), .D(b_on), .CLK(clk), .A0(db1[0]), .A1(db1[1]), .A2(db1[2]), .A3(db1[3]));
FD i_a (.C(clk),.D(enb && (a_on || (a && !a_off))),.Q(a));
FD_1 i_b (.C(clk),.D(use_b && (b_on || (b && !b_off))),.Q(b));
assign ab= ~(a ^ b);
assign q= (!ena || ext_clk) && (!enb || ab);
always @ (posedge clk) case (div_p[3:0])
4'h0: begin da0<=4'h0; da1<=4'h0; a_singleon<=1'b0; end // any, not used
// 4'h1: begin da0<=4'h0; da1<=4'h0; a_singleon<=1'b1; end
4'h1: begin da0<=4'h0; da1<=4'h0; a_singleon<=1'b0; end // for safety - not higher than clk0/1.5 (50MHz for 75 MHz)
4'h2: begin da0<=4'h0; da1<=4'h0; a_singleon<=1'b0; end
4'h3: begin da0<=4'h0; da1<=4'h0; a_singleon<=1'b1; end
4'h4: begin da0<=4'h3; da1<=4'h0; a_singleon<=1'b1; end
4'h5: begin da0<=4'h2; da1<=4'h1; a_singleon<=1'b0; end
4'h6: begin da0<=4'h1; da1<=4'h3; a_singleon<=1'b0; end
4'h7: begin da0<=4'h1; da1<=4'h0; a_singleon<=1'b0; end
4'h8: begin da0<=4'h6; da1<=4'h0; a_singleon<=1'b0; end
4'h9: begin da0<=4'h4; da1<=4'h3; a_singleon<=1'b0; end
4'ha: begin da0<=4'h2; da1<=4'h6; a_singleon<=1'b0; end
4'hb: begin da0<=4'h2; da1<=4'h1; a_singleon<=1'b0; end
4'hc: begin da0<=4'h9; da1<=4'h1; a_singleon<=1'b0; end
4'hd: begin da0<=4'h6; da1<=4'h5; a_singleon<=1'b0; end
4'he: begin da0<=4'h3; da1<=4'h9; a_singleon<=1'b0; end
4'hf: begin da0<=4'h3; da1<=4'h2; a_singleon<=1'b0; end
endcase
always @ (negedge clk) case (div_p[3:0])
4'h0: begin db0<=4'h0; db1<=4'h0; end
// 4'h1: begin db0<=4'h1; db1<=4'h0; end
4'h1: begin db0<=4'h0; db1<=4'h0; end // for safety - not higher than clk0/1.5 (50MHz for 75 MHz)
4'h2: begin db0<=4'h0; db1<=4'h0; end
4'h3: begin db0<=4'h0; db1<=4'h0; end
4'h4: begin db0<=4'h0; db1<=4'h0; end
4'h5: begin db0<=4'h0; db1<=4'h2; end
4'h6: begin db0<=4'h2; db1<=4'h1; end
4'h7: begin db0<=4'h0; db1<=4'h0; end
4'h8: begin db0<=4'h1; db1<=4'h1; end
4'h9: begin db0<=4'h1; db1<=4'h4; end
4'ha: begin db0<=4'h4; db1<=4'h2; end
4'hb: begin db0<=4'h0; db1<=4'h0; end
4'hc: begin db0<=4'h2; db1<=4'h2; end
4'hd: begin db0<=4'h2; db1<=4'h6; end
4'he: begin db0<=4'h6; db1<=4'h3; end
4'hf: begin db0<=4'h0; db1<=4'h0; end
endcase
endmodule
*/
/*
** -----------------------------------------------------------------------------**
** cmd_sequencer.v
**
** command sequencer with FIFO
**
** Copyright (C) 2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// This command sequencer is designed (together with i2c sequencer) to provide
// pipelined operation of the sensor, FPGA pre-processor and compressor, to avoid
// requirement of resetting the circuitry and loosing several frames when the sensor
// acquisition parameters are changed (especially geometry - WOI, decimation).
// It also reduces real-time requirements to the software, as it is possible to
// program parameters related to the events several frames in the future.
//
// Commands related to the particular frames go to one of the 8 FIFO buffers (64 commands deep each),
// each command is 32 bits wide, with 8MSBs being register address, and the remaining 24 bits - data
// to be written.
// That limits data that can be written to the FPGA registers compared to the direct register writes
// (8MSBs are always zero), but all the relevant information can be written with just 24 data bits.
//
//
// Controller is programmed through 16 locations (currently mapped to 0x60..0x6f):
// 0x0..0x7 write directly to the frame number [2:0] modulo 8, except if you write to the frame
// "just missed" - in that case data will go to the current frame.
// 0x8 - write seq commands to be sent ASAP
// 0x9 - write seq commands to be sent after the next frame starts
//
// 0xe - write seq commands to be sent after the next 6 frames start
// 0xf - control register:
// [14] - reset all FIFO (takes 16 clock pulses), also - stops seq until run command
// [13:12] - 3 - run seq, 2 - stop seq , 1,0 - no change to run state
module cmd_sequencer (sclk, // @negedge
wen, // sync to address and d[0:15]
wa, // [3:0] 0..7 - absolute data, 8..0x0e relative data, 0x0f - command
di, // [15:0] data in
sync, // frame sync (used to synchronize data), vacts_sclk @negedge sclk
// condition,// condition to wait
seq_rq, // request from the sequencer
seq_ack, // sequencer acknowledge
seq_a, // address from the sequencer
seq_d, // data from the sequencer
frame_no);// [2:0] current frame modulo 8
input sclk;
input wen;
input [ 3:0] wa;
input [15:0] di;
input sync;
// output [ 7:0] condition;
output seq_rq; // request from the sequencer
input seq_ack; // sequencer acknowledge
output [ 7:0] seq_a; // address from the sequencer
output [23:0] seq_d; // data from the sequencer
output [2:0] frame_no;
// reg [4:0] wen_d; // [0] - not just fifo, but any PIO writes, [1] and next - filtered for FIFO only
reg [3:0] wen_d; // [0] - not just fifo, but any PIO writes, [1] and next - filtered for FIFO only
reg [3:0] wad;
reg [15:0] di_1;
reg [15:0] di_2;
reg [15:0] di_3;
reg [2:0] wpage0; // FIFO page were ASAP writes go
reg [2:0] wpage7; // unused page, currently being cleared
reg [2:0] page_r; // FIFO page were current write goes (reading)
reg [2:0] wpage_w; // FIFO page were current write goes (reading)
reg wpage0_inc; // increment wpage0 (after frame syn or during reset
reg wpage0_inc_d; // next cycle after wpage0_inc
reg reset_cmd;
reg run_cmd;
reg reset_on; // reset FIFO in progress
wire seq_enrun; // enable seq
reg we_fifo_wp; // enable writing to fifo write pointer memory
reg req_clr; // request for clearing fifo_wp
wire is_ctl= (wad[3:0]==4'hf);
// wire is_rel= ((wad[3]==1) && (wad[2:0]!=3'h7));
wire is_abs= (wad[3]==0);
wire pre_wpage0_inc;
wire [2:0] frame_no=wpage0[2:0];
//fifo write pointers (dual port distributed RAM)
reg [5:0] fifo_wr_pointers [0:7];
wire [5:0] fifo_wr_pointers_outw=fifo_wr_pointers[wpage_w[2:0]];
wire [5:0] fifo_wr_pointers_outr=fifo_wr_pointers[page_r[2:0]];
reg [5:0] fifo_wr_pointers_outw_r;
reg [5:0] fifo_wr_pointers_outr_r;
// command seq fifo (RAMB16_S9_S18)
reg [9:0] seq_cmd_wa; // wite address for the current pair of 16-bit data words
// {page[2:0],word[5:0],MSW[0]}
reg seq_cmd_we; // write enable to blockRAM
reg [1:0] page_r_inc; // increment page_r[2:0]; - signal and delayed version
reg [5:0] rpointer; // FIFO read pointer for current page
// wire word_number; // BlockRAM output word (0 - low, 1 - high)
reg seq_rq; // request from the sequencer
reg [15:0] seq_dh; // address from the sequencer
wire [15:0] seq_dl; // sequencer data as read from BlockRAM
reg seq_re; // read enable from BlockRAM
reg seq_re_last; // second clock of seq_re
wire [1:0] por; //power on reset
wire initialized; // command fifo initialized
assign seq_a[ 7:0]= seq_dh[15:8];
assign seq_d[23:0]= {seq_dh[7:0],seq_dl[15:0]};
assign pre_wpage0_inc = (!wen_d[0] && !wen_d[1] && !wpage0_inc) && ((req_clr && initialized)|| reset_on) ;
// input seq_ack; // sequencer acknowledge
// setting control parameters
// if (reset_cmd || (run_cmd && !di_2[12])) seq_enrun <= 1'b0;
// else if (run_cmd && di_2[12]) seq_enrun <= 1'b1;
FD_1 i_seq_enrun (.Q(seq_enrun), .C(sclk),.D( !(reset_cmd || (run_cmd && !di_2[12])) &&
((run_cmd && di_2[12]) || seq_enrun )));
FD_1 i_por0 (.Q(por[0]), .C(sclk),.D( 1'b1));
FD_1 i_por1 (.Q(por[1]), .C(sclk),.D(por[0]));
FD_1 i_initialized ( .Q(initialized), .C(sclk), .D(por[1] && ( initialized || (reset_on && !(wpage0_inc && ( wpage0[2:0]==3'h7))))) );
always @ (negedge sclk) begin
// signals related to writing to seq FIFO
// delayed versions of address, data write strobe
if (wen) wad [ 3:0] <= wa[ 3:0];
if (wen || wen_d[0]) di_1[15:0] <= di[15:0];
di_2[15:0] <= di_1[15:0];
di_3[15:0] <= di_2[15:0];
// wen_d[4:0] <= {wen_d[3:1],wen_d[0] && !is_ctl,wen};
wen_d[3:0] <= {wen_d[2:1],wen_d[0] && !is_ctl, !reset_on && wen};
// decoded commands
reset_cmd <= (!reset_on & wen_d[0] && is_ctl && di_1[14]) || (por[0] && !por[1]);
run_cmd <= wen_d[0] && is_ctl && di_1[13];
// write pointer memory
wpage0_inc <= pre_wpage0_inc && &por[1:0];
wpage0_inc_d <= wpage0_inc && &por[1:0];
if (reset_cmd || !por[1]) wpage0[2:0]<=3'h0;
else if (wpage0_inc) wpage0[2:0]<=wpage0[2:0]+1;
if (reset_cmd || !por[1]) wpage7[2:0]<=3'h7;
else if (wpage0_inc) wpage7[2:0]<=wpage0[2:0];
reset_on <= por[1] && (reset_cmd || (reset_on && !(wpage0_inc && ( wpage0[2:0]==3'h7))));
req_clr <= sync || (req_clr && !wpage0_inc);
if (wen_d[0]) wpage_w[2:0] <= is_abs?((wad[2:0]==wpage7[2:0])? wpage0[2:0] : wad[2:0]):(wpage0[2:0]+wad[2:0]);
else if (wpage0_inc) wpage_w[2:0] <= wpage7[2:0];
we_fifo_wp <= wen_d[1] || wpage0_inc;
if (wen_d[1]) fifo_wr_pointers_outw_r[5:0] <= fifo_wr_pointers_outw[5:0];
if (we_fifo_wp) fifo_wr_pointers[wpage_w[2:0]] <= wpage0_inc_d? 7'h0:(fifo_wr_pointers_outw_r[5:0]+1);
fifo_wr_pointers_outr_r[5:0] <= fifo_wr_pointers_outr[5:0]; // just register distri
// command seq fifo (RAMB16_S9_S18)
if (wen_d[1]) seq_cmd_wa[9:1] <= {wpage_w[2:0],fifo_wr_pointers_outw[5:0]};
seq_cmd_wa[0] <= !wen_d[1]; // 0 for the first in a pair, 1 - for the second
seq_cmd_we <= !reset_cmd && (wen_d[1] || (seq_cmd_we && !wen_d[3])); //reset_cmd added to keep simulator happy
// signals related to reading from seq FIFO
seq_re_last<=seq_re && !seq_re_last;
if (seq_re_last) seq_dh[15:0]<=seq_dl[15:0];
if (reset_cmd || page_r_inc[0]) rpointer[5:0] <= 6'h0;
else if (seq_re_last) rpointer[5:0] <= rpointer[5:0] + 1;
seq_re <= seq_enrun &&
!seq_re_last &&
!reset_on &&
!page_r_inc[1] &&
!page_r_inc[0] &&
(((rpointer[5:0]!= fifo_wr_pointers_outr_r[5:0]) &&
!(seq_rq && !seq_ack)) ||
seq_re);
seq_rq <= seq_enrun && (seq_re_last || (seq_rq && !seq_ack));
page_r_inc[1:0] <= {page_r_inc[0] && !(seq_re && !seq_re_last),
!(page_r_inc[0] && !(seq_re && !seq_re_last)) &&
(rpointer[5:0] == fifo_wr_pointers_outr_r[5:0]) &&
(page_r[2:0]!=wpage0[2:0])};
if (reset_on) page_r[2:0]<=3'h0;
else if (page_r_inc[0] && !(seq_re && !seq_re_last)) page_r[2:0]<=page_r[2:0]+1;
end
RAMB16_S18_S18 i_fifo (
.DOA(seq_dl[15:0]), // Port A 16-bit Data Output
.DOPA(), // Port A 2-bit Parity Output
.ADDRA({page_r[2:0],
rpointer[5:0],
~seq_re_last}), // Port A 10-bit Address Input
.CLKA(!sclk), // Port A Clock
.DIA(16'h0), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(seq_re), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.DOB(), // Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.ADDRB(seq_cmd_wa[9:0]), // Port B 10-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB(di_3[15:0]), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(seq_cmd_we), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b1) // Port B Write Enable Input
);
endmodule
/*
** -----------------------------------------------------------------------------**
** color_proc353.v
**
** Color space converter (bayer-> YCbCr 4:2:1) for JPEG compressor
**
** Copyright (C) 2002-2010 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
`define debug_compressor
module color_proc (clk, // pixel clock (1/2 system clock - 80MHz)
en, // Enable (0 will reset states)
en_sdc, // enable subtracting of DC component
go, // pulse to star/restart (needed for each frame, repeat generated by the caller)
nblocks, // [17:0] number of 16x16 blocks to read (valid @ "go" pulse)
eot, // single-cycle end of transfer pulse
m_cb, // [9:0] scale for CB - default 0.564 (10'h90)
m_cr, // [9:0] scale for CB - default 0.713 (10'hb6)
memWasInit, // memory channel2 was just initialized - reset page address (at posedge clk)
di, // [7:0]
sdram_a, // [10:0] (MSB - SDRAM buffer page number)
sdram_rdy, // SDRAM buffer ready
sdram_next, // request to read a page to SDRAM buffer
inc_sdrama, // enable read sdram buffer
noMoreData, // used as alternative to end frame input (possibly broken frame)
dv_raw, // data valid for di (for testing to bypass color conversion - use di[7:0])
ignore_color, //zero Cb/Cr components
four_blocks, // use only 6 blocks fro the output, not 6
jp4_dc_improved, // in JP4 mode, compare DC coefficients to the same color ones
tile_margin, // margins around 16x16 tiles (0/1/2)
tile_shift, // tile shift from top left corner
converter_type, // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff, // divide differences by 2 (to fit in 8-bit range)
hdr, // second green absolute, not difference
do, // [9:0] data out (4:2:0) (signed, average=0)
avr, // [8:0] DC (average value) - RAM output, no register. For Y components 9'h080..9'h07f, for C - 9'h100..9'h0ff!
dv, // out data valid (will go high for at least 64 cycles)
ds, // single-cycle mark of the first pixel in a 64 (8x8) - pixel block
tn, // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start)
first, // sending first MCU (valid @ ds)
last, // sending last MCU (valid @ ds)
n000, // [7:0] number of zero pixels (255 if 256)
n255, // [7:0] number of 0xff pixels (255 if 256)
bayer_phase, //[1:0]) bayer color filter phase 0:(GR/BG), 1:(RG/GB), 2: (BG/GR), 3: (GB/RG)
// below signals valid at ds ( 1 later than tn, first, last)
component_num, //[2:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift) 4 - don't use
component_color, // use color quantization table (YCbCR, jp4diff)
component_first, // first this component in a frame (DC absolute, otherwise - difference to previous)
component_lastinmb // last component in a macroblock;
`ifdef debug_compressor
,bcntrIsZero
,bcntr
`endif
);
input ignore_color;
input four_blocks; // use only 6 blocks fro the output, not 6
input jp4_dc_improved; // in JP4 mode, compare DC coefficients to the same color ones
input [1:0] tile_margin; // margins around 16x16 tiles (0/1/2)
input [2:0] tile_shift; // tile shift from top left corner
input [2:0] converter_type; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
input scale_diff; // divide differences by 2 (to fit in 8-bit range)
input hdr; // second green absolute, not difference
input clk, en, go, en_sdc;
input [17:0] nblocks;
output eot;
input [ 9:0] m_cb; // [9:0] scale for CB - default 0.564 (10'h90)
input [ 9:0] m_cr; // [9:0] scale for CB - default 0.713 (10'hb6)
input memWasInit; // memory channel2 was just initialized - reset page address (at posedge clk)
input [ 7:0] di;
output [ 10:0] sdram_a;
input sdram_rdy;
output sdram_next;
output inc_sdrama;
input noMoreData; // (@posedge clk) used as alternative to end frame input (possibly broken frame)
output dv_raw;
// output [ 8:0] do;
output [ 9:0] do;
// output [ 7:0] avr;
output [ 8:0] avr;
output dv;
output ds;
output [ 2:0] tn;
output first;
output last;
output [7:0] n000;
output [7:0] n255;
input [1:0] bayer_phase;
output [2:0] component_num; //[1:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift), >=4 - don't use
output component_color; // use color quantization table (YCbCR, jp4diff)
output component_first; // first this component in a frame (DC absolute, otherwise - difference to previous)
output component_lastinmb; // last component in a macroblock;
//debug
`ifdef debug_compressor
output bcntrIsZero;
output [17:0] bcntr;
`endif
wire [ 9:0] m_cb; // [9:0] scale for CB - default 0.564 (10'h90)
wire [ 9:0] m_cr; // [9:0] scale for CB - default 0.713 (10'hb6)
wire [7:0] di;
wire [8:0] y_out; // data from buffer
wire [8:0] c_out; // data from buffer
reg [1:0] wpage; // page (0/1) where data is being written to (both Y and CbCr)
reg [1:0] rpage; // page (0/1) from where data is sent out ( both Y and CbCr)
wire [10:0] sdram_a;
reg sdram_next;
reg [17:0] bcntr; // down counter of blocks left
reg bcntrIsZero; // one cycle of bcntr[]==0
reg eot;
reg ccv_start_en; //
reg ccv_out_start,ccv_out_start_d; // start output of YCbCr from buffers
reg [8:0] raddr; // output address of buffer memories (MSB selects Y(0)/CbCr(1))
reg dv0; // "dv0" - one cycle ahead of "dv" to compensate for "do" register latency
reg ds0; // "ds0" - one cycle ahead of "ds" to compensate for "do" register latency
// reg [8:0] do;
// reg [8:0] pre_do;
reg [9:0] do;
reg [9:0] pre_do;
reg [1:0] pre_dv, pre_ds;
wire dv=pre_dv[1];
wire ds=pre_ds[1];
wire [2:0] tn;
reg dv_raw;
// reg [13:0] accYA,accYB,accCb, accCr;
// reg [13:0] accY0,accY1,accY2,accY3,accC2b, accCr; //will use 6 individual accumulators for larger flexibility (different input sequence)
// 16x8 dual port RAM
reg buf_sel;
reg willbe_first;
reg first,first0;
reg last,last0;
reg [4:0] preline; // number of line in a tile, down counter (0x13->0, 0x11->0, 0x0f->0), 1 cycles ahead of data from SDRAM
reg [4:0] prepix; // number of pixel in a line in a tile, down counter (0x13->0, 0x11->0, 0x0f->0)
// reg [1:0] sdram_page;
reg [1:0] sdram_a9_page;
reg [8:0] sdram_a9;
reg [8:0] seq_cntr; // master
// reg [2:0] pre_inc_sdrama;
wire [4:0] tile_size;
wire [8:0] macroblock_period_minus1;
wire all_ready;
reg preline_was_0;
reg pre_start_of_line;
reg pre_first_pixel;
reg [8:0] sdrama_top_left; // address of top left corner to be processed
reg [2:0] sdrama_line_inc; // increment amount when proceeding to next tile line
reg inc_sdrama;
reg last_from_sdram; // reading last byte from SDRAM
reg first_pixel; // reading first pixel to color converter (di will be evailable next cycle)
reg tim2next;
reg [8:0] y_in, c_in;
reg [7:0] yaddrw, caddrw;
reg ywe, cwe;
reg color_enable, pre_color_enable;// prevent random colors in monochrome/JP46 modes (pre_* - sync input)
reg cs_pre_first_out; // clear color accumulators
wire [7:0] conv18_y_in, conv20_y_in, mono_y_in, jp4_y_in;
// wire [8:0] jp4diff_y_in, conv18_c_in, conv20_c_in;
wire [8:0] jp4diff_y_in, conv18_c_in, conv20_c_in;
wire [7:0] conv18_yaddrw, conv20_yaddrw, mono_yaddrw, jp4_yaddrw, jp4diff_yaddrw;
wire [6:0] conv18_caddrw, conv20_caddrw;
wire conv18_ywe, conv18_cwe, conv20_ywe, conv20_cwe, mono_ywe, jp4_ywe, jp4diff_ywe;
wire conv18_pre_first_out, conv20_pre_first_out, mono_pre_first_out, jp4_pre_first_out, jp4diff_pre_first_out;
reg [4:0] en_converters;
reg [2:0] converter_type_r;
reg ignore_color_r;
reg jp4_dc_improved_r;
// reg jp4_diff_r;
reg four_blocks_r;
reg scale_diff_r;
reg hdr_r;
reg [1:0] tile_margin_r;
// reg [2:0] tile_shift_r;
reg [1:0] bayer_phase_r;
reg [3:0] bayer_phase_onehot;
reg raddr_lastInBlock;
reg raddr_updateBlock; // first in block, after last also. Should be when *_r match the currently selected converter for the macroblock
wire [2:0] component_num; //[1:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift) >=4 - don't use
wire component_color; // use color quantization table (YCbCR, jp4diff)
wire component_first; // first this component in a frame (DC absolute, otherwise - difference to previous)
// component_num,component_color,component_first for different converters vs tn (1 bit per tn (0..5)
reg component_lastinmb; // last component in a macroblock;
reg [5:0] component_numsL, component_numsLS; // component_num[0] vs tn
reg [5:0] component_numsM, component_numsMS; // component_num[1] vs tn
reg [5:0] component_numsH, component_numsHS; // component_num[2] vs tn
reg [5:0] component_colors, component_colorsS; // use color quantization table (YCbCR, jp4diff)
reg [5:0] component_firsts, component_firstsS; // first this component in a frame (DC absolute, otherwise - difference to previous)
reg eof_rq; // request to end frame if there will be no more data
assign sdram_a={sdram_a9_page[1:0],sdram_a9[8:0]};
assign tn[2:0]=raddr[8:6];
assign component_num[2:0]= {component_numsH[0],component_numsM[0],component_numsL[0]};
assign component_color = component_colors[0];
assign component_first = component_firsts[0];
assign all_ready = sdram_rdy && ccv_start_en;
assign macroblock_period_minus1[8:0] = four_blocks?(tile_margin[1]?9'h18f:(tile_margin[0]?9'h143:9'h0ff)):(tile_margin[1]?9'h18f:9'h17f);
assign tile_size[4:0] = tile_margin[1]?5'h13:(tile_margin[0]?5'h11:5'h0f);
always @ (posedge clk) begin
if (!en) seq_cntr[8:0] <=9'h0;
else if (seq_cntr[8:0]!=0) seq_cntr[8:0] <= seq_cntr[8:0] -1;
else if (all_ready) seq_cntr[8:0] <= macroblock_period_minus1;
preline_was_0 <= (preline[4:0]==5'h0);
if ((seq_cntr[8:0]==0) || ((prepix[4:0]==0) && !preline_was_0) ) prepix[4:0] <= tile_size[4:0];
else if (prepix[4:0]!=0) prepix[4:0] <= prepix[4:0] - 1;
if (seq_cntr[8:0]==0) preline[4:0] <= tile_size[4:0];
else if ((prepix[4:0]==0) && !preline_was_0) preline[4:0] <= preline[4:0] - 1;
pre_start_of_line <= ((seq_cntr[8:0]==0) || ((prepix[4:0]==0) && !preline_was_0) );
pre_first_pixel <= en && (seq_cntr[8:0]==9'h0) && all_ready;
case (tile_shift[2:0])
3'h0: sdrama_top_left[8:0] <= 9'h0;
3'h1: sdrama_top_left[8:0] <= 9'h15;
3'h2: sdrama_top_left[8:0] <= 9'h2a;
3'h3: sdrama_top_left[8:0] <= 9'h3f;
3'h4: sdrama_top_left[8:0] <= 9'h54;
endcase
case (tile_margin[1:0])
2'h0: sdrama_line_inc[2:0] <= 3'h5;
2'h1: sdrama_line_inc[2:0] <= 3'h3;
2'h2: sdrama_line_inc[2:0] <= 3'h1;
endcase
first_pixel <= pre_first_pixel;
last_from_sdram <= en & preline_was_0 && (prepix[4:0]==0);
inc_sdrama <= en & (pre_first_pixel || (inc_sdrama && !last_from_sdram ));
if (pre_first_pixel) sdram_a9[8:0] <= sdrama_top_left[8:0];
else if (inc_sdrama) sdram_a9[8:0] <= sdram_a9[8:0] + (pre_start_of_line ? sdrama_line_inc[2:0] : 1);
if (!en || memWasInit) sdram_a9_page[1:0] <= 2'h0;
else if (last_from_sdram && inc_sdrama) sdram_a9_page[1:0] <= sdram_a9_page[1:0]+1;
// wpage[1:0] valid with ywe
if (cs_pre_first_out) wpage[1:0] <= sdram_a9_page[1:0]; // copy page from SDRAM buffer
// register control modes to be valid while overlapping
if (pre_first_pixel) begin
converter_type_r [2:0] <= converter_type[2:0];
ignore_color_r <= ignore_color;
jp4_dc_improved_r <= jp4_dc_improved;
// jp4_diff_r <= (converter_type[2:0]==3'h4);
four_blocks_r <= four_blocks;
scale_diff_r <= scale_diff;
hdr_r <= hdr;
// scale_diff <= (converter_type[2:0]==3'h5);
tile_margin_r[1:0] <= tile_margin[1:0];
// tile_shift_r[2:0] <= tile_shift[2:0];
bayer_phase_r[1:0] <= bayer_phase[1:0];
bayer_phase_onehot[3:0]<={(bayer_phase[1:0]==2'h3)?1'b1:1'b0,
(bayer_phase[1:0]==2'h2)?1'b1:1'b0,
(bayer_phase[1:0]==2'h1)?1'b1:1'b0,
(bayer_phase[1:0]==2'h0)?1'b1:1'b0};
end
if (!en) en_converters[4:0] <= 0;
else if (pre_first_pixel)
en_converters[4:0]<= {(converter_type[2:0]==3'h4)?1'b1:1'b0,
(converter_type[2:0]==3'h3)?1'b1:1'b0,
(converter_type[2:0]==3'h2)?1'b1:1'b0,
(converter_type[2:0]==3'h1)?1'b1:1'b0,
(converter_type[2:0]==3'h0)?1'b1:1'b0};
end
// new
//cs_pre_first_out
reg [3:0] accYen;
reg [1:0] accCen; // individual accumulator enable (includes clearing)
reg [3:0] accYfirst;
reg [1:0] accCfirst; // add to zero, instead of to acc @ acc*en
// reg [7:0] preAccY, preAccC; // registered data from color converters, matching acc selection latency
reg [8:0] preAccY, preAccC; // registered data from color converters, matching acc selection latency
// reg [13:0] accY0,accY1,accY2,accY3,accC0,accC1;
reg [14:0] accY0,accY1,accY2,accY3,accC0,accC1;
reg cs_first_out;
reg [5:0] accCntrY0,accCntrY1,accCntrY2,accCntrY3,accCntrC0,accCntrC1;
wire [3:0] pre_accYdone;
wire [1:0] pre_accCdone; // need to make sure that pre_accCdone do not happen with pre_accYdone
reg [3:0] accYrun;
reg [1:0] accCrun;
reg [3:0] accYdone;
// reg [1:0] accCdone;
reg accYdoneAny;
reg [1:0] avrY_wa, pre_avrY_wa;
reg avrC_wa, pre_avrC_wa;
reg avrPage_wa, pre_avrPage_wa;
reg avr_we;
// reg [7:0] avermem[0:15];
reg [8:0] avermem[0:15];
wire [3:0] avr_wa= {avrPage_wa,accYdoneAny?{1'b0,avrY_wa[1:0]}:{2'b10,avrC_wa}};
reg [3:0] avr_ra; // read address
// wire [7:0] avrY_di= avrY_wa[1] ? (avrY_wa[0]?accY3[13:6]:accY2[13:6]):(avrY_wa[0]?accY1[13:6]:accY0[13:6]);
wire [8:0] avrY_di= avrY_wa[1] ? (avrY_wa[0]?accY3[14:6]:accY2[14:6]):(avrY_wa[0]?accY1[14:6]:accY0[14:6]);
// wire [7:0] avrC_di= avrC_wa ?accC1[13:6]:accC0[13:6];
wire [8:0] avrC_di= avrC_wa ?accC1[14:6]:accC0[14:6];
// wire [7:0] avr = avermem[avr_ra[3:0]];
wire [8:0] avr = avermem[avr_ra[3:0]];
assign pre_accYdone[3:0] = {(accCntrY3[5:0]==6'h3e)?1'b1:1'b0,(accCntrY2[5:0]==6'h3e)?1'b1:1'b0,(accCntrY1[5:0]==6'h3e)?1'b1:1'b0,(accCntrY0[5:0]==6'h3e)?1'b1:1'b0} & accYen[3:0];
assign pre_accCdone[1:0] = { (accCntrC1[5:0]==6'h3e)?1'b1:1'b0,(accCntrC0[5:0]==6'h3e)?1'b1:1'b0} & accCen[1:0];
always @ (posedge clk) begin
cs_first_out<=cs_pre_first_out;
// if (ywe) preAccY[7:0] <= y_in[7:0];
if (ywe) preAccY[8:0] <= y_in[8:0];
// if (cwe) preAccC[7:0] <= c_in[7:0];
if (cwe) preAccC[8:0] <= c_in[8:0];
accYen[3:0] <= {4{en & ywe}} & {yaddrw[7] & yaddrw[6], yaddrw[7] & ~yaddrw[6],~ yaddrw[7] & yaddrw[6], ~yaddrw[7] & ~yaddrw[6]};
accCen[1:0] <= {2{en & cwe}} & {caddrw[6], ~caddrw[6]};
accYfirst[3:0] <= {4{cs_first_out}} | (accYfirst[3:0] & ~accYen[3:0]);
accCfirst[1:0] <= {2{cs_first_out}} | (accCfirst[1:0] & ~accCen[1:0]);
// accAllFirst <= cs_first_out || ( accAllFirst && !(|accYen[3:0] || |accCen[1:0])); // until the first starts
if (accYen[0]) accY0[14:0]<= (accYfirst[0]?15'h0:accY0[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
if (accYen[1]) accY1[14:0]<= (accYfirst[1]?15'h0:accY1[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
if (accYen[2]) accY2[14:0]<= (accYfirst[2]?15'h0:accY2[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
if (accYen[3]) accY3[14:0]<= (accYfirst[3]?15'h0:accY3[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
if (accCen[0]) accC0[14:0]<= (accCfirst[0]?15'h0:accC0[14:0]) + {{6{preAccC[8]}},preAccC[8:0]};
if (accCen[1]) accC1[14:0]<= (accCfirst[1]?15'h0:accC1[14:0]) + {{6{preAccC[8]}},preAccC[8:0]};
/*
if (accYen[0]) accCntrY0[5:0]<= (accYfirst[0]?6'h0:(accCntrY0[5:0]+1));
if (accYen[1]) accCntrY1[5:0]<= (accYfirst[1]?6'h0:(accCntrY1[5:0]+1));
if (accYen[2]) accCntrY2[5:0]<= (accYfirst[2]?6'h0:(accCntrY2[5:0]+1));
if (accYen[3]) accCntrY3[5:0]<= (accYfirst[3]?6'h0:(accCntrY3[5:0]+1));
if (accCen[0]) accCntrC0[5:0]<= (accCfirst[0]?6'h0:(accCntrC0[5:0]+1));
if (accCen[1]) accCntrC1[5:0]<= (accCfirst[1]?6'h0:(accCntrC1[5:0]+1));
*/
if (!en) accCntrY0[5:0]<= 6'h0; else if (accYen[0]) accCntrY0[5:0]<= (accYfirst[0]?6'h0:(accCntrY0[5:0]+1));
if (!en) accCntrY1[5:0]<= 6'h0; else if (accYen[1]) accCntrY1[5:0]<= (accYfirst[1]?6'h0:(accCntrY1[5:0]+1));
if (!en) accCntrY2[5:0]<= 6'h0; else if (accYen[2]) accCntrY2[5:0]<= (accYfirst[2]?6'h0:(accCntrY2[5:0]+1));
if (!en) accCntrY3[5:0]<= 6'h0; else if (accYen[3]) accCntrY3[5:0]<= (accYfirst[3]?6'h0:(accCntrY3[5:0]+1));
if (!en) accCntrC0[5:0]<= 6'h0; else if (accCen[0]) accCntrC0[5:0]<= (accCfirst[0]?6'h0:(accCntrC0[5:0]+1));
if (!en) accCntrC1[5:0]<= 6'h0; else if (accCen[1]) accCntrC1[5:0]<= (accCfirst[1]?6'h0:(accCntrC1[5:0]+1));
accYrun[3:0] <= {4{en}} & ((accYfirst[3:0] & accYen[3:0]) | (accYrun[3:0] & ~pre_accYdone[3:0]));
accCrun[1:0] <= {2{en}} & ((accCfirst[1:0] & accCen[1:0]) | (accCrun[1:0] & ~pre_accCdone[1:0]));
accYdone[3:0] <= pre_accYdone[3:0] & accYrun[3:0];
// accCdone[1:0] <= pre_accCdone[1:0] & accCrun[1:0];
accYdoneAny <= |(pre_accYdone[3:0] & accYrun[3:0]);
avr_we <= |(pre_accYdone[3:0] & accYrun[3:0]) || |(pre_accCdone[1:0] & accCrun[1:0]);
pre_avrY_wa[1:0] <= yaddrw[7:6];
avrY_wa[1:0] <= pre_avrY_wa[1:0];
pre_avrC_wa <= caddrw[ 6];
avrC_wa <= pre_avrC_wa;
pre_avrPage_wa <= wpage[0];
avrPage_wa <= pre_avrPage_wa;
// if (avr_we) avermem[avr_wa[3:0]] <= accYdoneAny?avrY_di[7:0]:avrC_di[7:0];
if (avr_we) avermem[avr_wa[3:0]] <= en_sdc?(accYdoneAny?avrY_di[8:0]:avrC_di[8:0]):9'h0;
avr_ra[3:0] <= {rpage[0],raddr[8:6]};
end
reg transfer_ended=0; /// there was already EOT pulse for the current frame
always @ (posedge clk) begin
transfer_ended <= bcntrIsZero && (transfer_ended || eot);
/*+*/ tim2next <= (seq_cntr[8:0]=='h10); // rather arbitrary number - sdram buffer should in no case be actually overwritten before data read out
// it may depend on relation between SDRAM clk frequency (75MHz) and this clk (variable? 30MHz)
// eof_rq <= (tim2next && !bcntrIsZero) || (eof_rq && !(inc_sdrama || noMoreData ||transfer_ended));
eof_rq <= (tim2next && !bcntrIsZero) || (eof_rq && !(inc_sdrama || transfer_ended));
// ccv_start_en <= en && (ccv_start_en || go); //NOTE: Just for simulation
ccv_start_en <= en && !eot && (ccv_start_en || go); //FIXME: Still uncaught problem: SDRAM ready occurs before go_single!
// bcntrIsZero <= (bcntr[17:0]==18'b0) || noMoreData;
bcntrIsZero <= (bcntr[17:0]==18'b0);
sdram_next <= tim2next && ~sdram_next;
// eot <= (tim2next && bcntrIsZero) || (eof_rq && noMoreData);
eot <= !transfer_ended && !eot && bcntrIsZero && (tim2next || (eof_rq && noMoreData));
if (go) bcntr[17:0] <= nblocks[17:0];
else if (noMoreData) bcntr[17:0] <= 18'b0;
else if (sdram_next && !bcntrIsZero) bcntr[17:0] <= bcntr[17:0]-1;
if (ccv_out_start) rpage[1:0] <=wpage[1:0];
if (ccv_out_start) color_enable <= pre_color_enable;
ccv_out_start_d <= ccv_out_start;
raddr_lastInBlock <= en && (raddr[5:0]==6'h3e);
raddr_updateBlock <= raddr_lastInBlock || ccv_out_start;
if (ccv_out_start || !en) raddr[8:0] <= {!en,!en,7'h0}; // 9'h180/9'h000;
else if (!raddr[8] || (!four_blocks_r && !raddr[7])) raddr[8:0] <= raddr[8:0]+1; // for 4 blocks - count for 0,1; 6 blocks - 0,1,2
dv0 <= en && raddr_updateBlock?(!raddr[8] || (!four_blocks_r && !raddr[7])):dv0;
ds0 <= raddr_updateBlock && (!raddr[8] || (!four_blocks_r && !raddr[7]));
buf_sel <= raddr[8];
// pre_do[8:0] <= (buf_sel?c_out[7:0]:y_out[7:0])-avr[7:0];
// pre_do[9:0] <= (buf_sel?{c_out[8],c_out[8:0]}:{y_out[8],y_out[8:0]})-{avr[8],avr[8:0]};
pre_do[9:0] <= buf_sel?(color_enable?({c_out[8],c_out[8:0]}-{avr[8],avr[8:0]}):10'b0):({y_out[8],y_out[8:0]}-{avr[8],avr[8:0]});
//color_enable
// do[8:0] <= pre_do[8:0];
do[9:0] <= pre_do[9:0];
dv_raw <= inc_sdrama && en;
if (go) willbe_first <= 1'b1;
else if (first_pixel) willbe_first <= 1'b0;
if (first_pixel) begin
first0 <= willbe_first;
last0 <= (bcntr[17:0]==17'b0);
end
if (ccv_out_start) begin
first <= first0;
last <= last0;
end
// 8x8 memory to hold average values
// if (avm_we) avermem[avm_a[3:0]] <= avm_d[7:0];
pre_dv[1:0] <= {pre_dv[0],dv0};
pre_ds[1:0] <= {pre_ds[0],ds0};
// Shift registers - generating block attributes to be used later in compressor
if (raddr_updateBlock) begin
if (ccv_out_start_d) begin
component_numsL[5:0] <= component_numsLS[5:0];
component_numsM[5:0] <= component_numsMS[5:0];
component_numsH[5:0] <= component_numsHS[5:0];
component_colors[5:0] <= component_colorsS[5:0];
component_firsts[5:0] <= first0? component_firstsS[5:0]:6'h0; // here we may use first0 that is one cycle earlier and ends much earlier
end else begin
component_numsL[5:0] <= {1'b0,component_numsL[5:1]};
component_numsM[5:0] <= {1'b0,component_numsM[5:1]};
component_numsH[5:0] <= {1'b0,component_numsH[5:1]};
component_colors[5:0] <= {1'b0,component_colors[5:1]};
component_firsts[5:0] <= {1'b0,component_firsts[5:1]};
end
end
component_lastinmb <= tn[0] && (four_blocks_r? tn[1] : tn[2]); // last component in a macroblock;
end
// average for each block should be calculated before the data goes to output output
always @ (posedge clk) case (converter_type_r[2:0])
3'h0:begin //color 18
cs_pre_first_out <= conv18_pre_first_out;
y_in[8:0] <= {conv18_y_in[7],conv18_y_in[7:0]};
ywe <= conv18_ywe;
yaddrw[7:0] <= {conv18_yaddrw[7],conv18_yaddrw[3],conv18_yaddrw[6:4],conv18_yaddrw[2:0]};
c_in[8:0] <= {conv18_c_in[8:0]};
cwe <= conv18_cwe;
pre_color_enable <= 1'b1;
caddrw[7:0] <= {1'b0,conv18_caddrw[6:0]};
ccv_out_start <= (conv18_yaddrw[7:0]==8'hc5); //TODO: adjust to minimal latency?
component_numsLS <= 6'h10; // component_num [0]
component_numsMS <= 6'h20; // component_num [1]
component_numsHS <= 6'h00; // component_num [2]
component_colorsS <= 6'h30; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= 6'h31; // first this component in a frame (DC absolute, otherwise - difference to previous)
end
3'h1:begin //color 20
cs_pre_first_out <= conv20_pre_first_out;
y_in[8:0] <= {conv20_y_in[7],conv20_y_in[7:0]};
ywe <= conv20_ywe;
yaddrw[7:0] <= {conv20_yaddrw[7],conv20_yaddrw[3],conv20_yaddrw[6:4],conv20_yaddrw[2:0]};
c_in[8:0] <= {conv20_c_in[8:0]};
cwe <= conv20_cwe;
pre_color_enable <= 1'b1;
caddrw[7:0] <= {1'b0,conv20_caddrw[6:0]};
ccv_out_start <= (conv20_yaddrw[7:0]==8'hc5); //TODO: adjust to minimal latency?
component_numsLS <= 6'h10; // component_num [0]
component_numsMS <= 6'h20; // component_num [1]
component_numsHS <= 6'h3f; // component_num [2]
component_colorsS <= 6'h30; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= 6'h31; // first this component in a frame (DC absolute, otherwise - difference to previous)
end
3'h2:begin //mono
cs_pre_first_out <= mono_pre_first_out;
y_in[8:0] <= {mono_y_in[7],mono_y_in[7:0]};
ywe <= mono_ywe;
yaddrw[7:0] <= {mono_yaddrw[7],mono_yaddrw[3],mono_yaddrw[6:4],mono_yaddrw[2:0]};
c_in[8:0] <= 9'h0;
cwe <= 1'b0;
pre_color_enable <= 1'b0;
caddrw[7:0] <= 8'h0;
ccv_out_start <= accYdone[0];
component_numsLS <= 6'h10; // component_num [0]
component_numsMS <= 6'h20; // component_num [1]
component_numsHS <= 6'h30; // component_num [2]
component_colorsS <= 6'h30; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= 6'h31; // first this component in a frame (DC absolute, otherwise - difference to previous)
end
3'h3:begin // jp4
cs_pre_first_out <= jp4_pre_first_out;
y_in[8:0] <= {jp4_y_in[7],jp4_y_in[7:0]};
ywe <= jp4_ywe;
yaddrw[7:0] <= {jp4_yaddrw[7],jp4_yaddrw[3],jp4_yaddrw[6:4],jp4_yaddrw[2:0]};
c_in[8:0] <= 9'h0;
cwe <= 1'b0;
pre_color_enable <= 1'b0;
caddrw[7:0] <= 8'h0;
ccv_out_start <= accYdone[0];
component_numsLS <= jp4_dc_improved_r?6'h0a:6'h10; // LSb of component_num
component_numsMS <= jp4_dc_improved_r?6'h0c:6'h20; // MSb of component_num
component_numsHS <= 6'h30; // component_num [2]
component_colorsS <= 6'h30; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= jp4_dc_improved_r?6'h3f:6'h31; // first this component in a frame (DC absolute, otherwise - difference to previous)
end
3'h4:begin //jp4diff
cs_pre_first_out <= jp4diff_pre_first_out;
y_in[8:0] <= {jp4diff_y_in[8:0]};
ywe <= jp4diff_ywe;
yaddrw[7:0] <= {jp4diff_yaddrw[7],jp4diff_yaddrw[3],jp4diff_yaddrw[6:4],jp4diff_yaddrw[2:0]};
c_in[8:0] <= 9'h0;
cwe <= 1'b0;
pre_color_enable <= 1'b0;
caddrw[7:0] <= 8'h0;
ccv_out_start <= accYdone[0];
component_numsLS <= 6'h0a; // LSb of component_num
component_numsMS <= 6'h0c; // MSb of component_num
component_numsHS <= 6'h30; // component_num [2]
component_colorsS <= {2'h3,~bayer_phase_onehot[3:0] | (hdr_r? {~bayer_phase_onehot[1:0],~bayer_phase_onehot[3:2]} : 4'h0)}; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= 6'h3f; // first this component in a frame (DC absolute, otherwise - difference to previous)
end
endcase
wire limit_diff=1'b1;
csconvert18 i_csconvert18 (.RST(!en_converters[0]),
.CLK(clk),
.mono(ignore_color_r),
.limit_diff(limit_diff), // 1 - limit color outputs to -128/+127 range, 0 - let them be limited downstream
.m_cb(m_cb[9:0]), // [9:0] scale for CB - default 0.564 (10'h90)
.m_cr(m_cr[9:0]), // [9:0] scale for CB - default 0.713 (10'hb6)
.din(di[7:0]),
.pre_first_in(first_pixel),
.signed_y(conv18_y_in[7:0]),
.q(conv18_c_in[8:0]),
.yaddr(conv18_yaddrw[7:0]), //
.ywe(conv18_ywe),
.caddr(conv18_caddrw[6:0]),
.cwe(conv18_cwe),
.pre_first_out(conv18_pre_first_out),
.bayer_phase(bayer_phase_r[1:0]),
.n000(n000[7:0]), // TODO:remove ?
.n255(n255[7:0]));
csconvert_mono i_csconvert_mono (
.en(en_converters[2]),
.clk(clk),
.din(di[7:0]),
.pre_first_in(first_pixel),
.y_out (mono_y_in[7:0]),
.yaddr (mono_yaddrw[7:0]),
.ywe (mono_ywe),
.pre_first_out(mono_pre_first_out));
csconvert_jp4 i_csconvert_jp4 (
.en(en_converters[3]),
.clk(clk),
.din(di[7:0]),
.pre_first_in(first_pixel),
.y_out (jp4_y_in[7:0]),
.yaddr (jp4_yaddrw[7:0]),
.ywe (jp4_ywe),
.pre_first_out(jp4_pre_first_out));
csconvert_jp4diff i_csconvert_jp4diff (
.en(en_converters[4]),
.clk(clk),
.scale_diff(scale_diff_r),
.hdr(hdr_r),
.din(di[7:0]),
.pre_first_in(first_pixel),
.y_out (jp4diff_y_in[8:0]),
.yaddr (jp4diff_yaddrw[7:0]),
.ywe (jp4diff_ywe),
.pre_first_out(jp4diff_pre_first_out),
.bayer_phase(bayer_phase_r[1:0]));
//TODO: temporary plugs, until module is cretaed
// will be wrong, of course
assign conv20_y_in[7:0]= conv18_y_in[7:0];
assign conv20_yaddrw[7:0]= conv18_yaddrw[7:0];
assign conv20_ywe= conv18_ywe;
assign conv20_c_in[8:0]= conv18_c_in[8:0];
assign conv20_caddrw[6:0]= conv18_caddrw[6:0];
assign conv20_cwe= conv18_cwe;
assign conv20_pre_first_out= conv18_pre_first_out;
// currently only 8 bits are used in the memories
RAMB16_S9_S9 i_y_buff (
.DOA(), // Port A 8-bit Data Output
.DOPA(), // Port A 8-bit Parity Output
.ADDRA({1'b0,wpage[1:0],yaddrw[7:0]}), // Port A 11-bit Address Input
.CLKA(clk), // Port A Clock
.DIA(y_in[7:0]), // Port A 8-bit Data Input
.DIPA(y_in[8]), // Port A 1-bit parity Input
.ENA(ywe), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b1), // Port A Write Enable Input
.DOB(y_out[7:0]), // Port B 8-bit Data Output
.DOPB(y_out[8]), // Port B 1-bit Parity Output
.ADDRB({1'b0,rpage[1:0],raddr[7:0]}), // Port B 11-bit Address Input
.CLKB(clk), // Port B Clock
.DIB(8'h0), // Port B 8-bit Data Input
.DIPB(1'h0), // Port-B 1-bit parity Input
.ENB(!raddr[8]), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
RAMB16_S9_S9 i_CrCb_buff (
.DOA(), // Port A 8-bit Data Output
.DOPA(), // Port A 8-bit Parity Output
.ADDRA({1'b0,wpage[1:0],caddrw[7:0]}), // Port A 11-bit Address Input
.CLKA(clk), // Port A Clock
.DIA(c_in[7:0]), // Port A 8-bit Data Input
.DIPA(c_in[8]), // Port A 1-bit parity Input
.ENA(cwe), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b1), // Port A Write Enable Input
.DOB(c_out[7:0]), // Port B 8-bit Data Output
.DOPB(c_out[8]), // Port B 1-bit Parity Output
.ADDRB({1'b0,rpage[1:0],raddr[7:0]}), // Port B 11-bit Address Input
.CLKB(clk), // Port B Clock
.DIB(8'h0), // Port B 8-bit Data Input
.DIPB(1'h0), // Port-B 1-bit parity Input
.ENB(raddr[8]), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
endmodule
/*
** -----------------------------------------------------------------------------**
** compressor333.v
**
** Top level module for JPEG compressor part of FPGA
**
** Copyright (C) 2002-2010 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
`timescale 1ns/1ps
`define debug_compressor
module compressor(// cwr, // CPU write - global clock
clk, // compressor pixel clock.(80MHz)
clk2x, // twice clk, used for huffman/stuffer stages. leading front should be before clk leading front (160MHz)
cwe, // we to compressor from CPU (now @ negedge clk) - only command register and number of MCUs
wr_saturation, // write color saturation vaues
// (currently 10 bits - cb from idi[9:0],
// cr - from idi[21:12]
wr_quantizer_mode, // Quantizer tuning - Coring table pair number (0..7)
rs, // 0 - bit modes,
// 1 - number of MCUs
twqe, // quantization table write enable
twce, // coring functions tables (@negedge clk - addr and data valid this cycle and one before)
twhe, // huffamn table write enable
twfe, // table to be multiplied by DCT coefficients (then squared and accumulated)
// to determine focus sharpness
ta, // [8:0] addresses words in tables (quantization and huffman)
di, // [31:0] data from CPU
vacts_long, // long vacts pulse (15 scan lines) to delay comprssor start (@pixel clock, need re-sync)
eot, // ( to interrupts?) pulse while processing the last MCU in a frame - predictable time to end of DMA transfer
// SDRAM interface
done_input, // will go high after EOT and persist until DCT is enabled
done_compress, // will go high after all data is sent out
done_compress_pulse, // Does not need to be reset
compressor_started, // single sclk compressor started
is_compressing, // @posedge clk, from go_single to eot (actual or simulated)
chInitOnehot2, // decoded channel init pulses, 2 cycles behind chInit (to reset page address)
nextBlocksEn, // When combined with SDRAM data ready, may be used to end frame compression input (instead of block counter)
pxd, // [7:0] data from SDRAM organized as 18x18x8bit MCUs+overlapping margins
pxa, // [10:0] - address to SDRAM buffer (2 MSBs - page. Starts with 0)
pxrdy, // SDRAM buffer (channel 2) has a page ready
nxtpage,// read next page to SDRAM buffer (from SDRAM)
inc_sdrama, //enable read from SDRAM buffer
confirmFrame2Compressor, // (re) enable reading SDRAM to channel 2 FIFO (it stops after each frame over and after channel init)
restart_memory, // restart memory channel (to align after broken frames) - masked by enable bit in memory controller
bonded, // channel bonded with the other (just for channel 2), make it TIG
bayer_phase,// [1:0] bayer color filter phase 0:(GR/BG), 1:(RG/GB), 2: (BG/GR), 3: (GB/RG)
// Reusing channel 3 for DC components output (****** currently disconnected ******)
dccout, //enable output of DC and HF components for brightness/color/focus adjustments
hfc_sel, // [2:0] (for autofocus) only components with both spacial frequencies higher than specified will be added
statistics_dv, //sclk
statistics_do,//[15:0] sclk
// start of frame time (set at first HACT after first VACT)
sec, // [31:0] number of seconds
usec, // [19:0] number of microseconds
q,
qv,
imgptr, // [23:0]image pointer in 32-byte chunks
hifreq //[31:0]) // accumulated high frequency components in a frame sub-window
,dma_is_reset // DMA module is reset, enable resetting data counters
,test_state // {is_compressing, cmprs_repeat,cmprs_en}
`ifdef debug_compressor
,test_cntr0 // [31:0] just for testing
`endif
`ifdef debug_stuffer
,tst_stuf_negedge, // [3:0] just for testing
tst_stuf_posedge, // [3:0] just for testing
tst_stuf_etrax, // [3:0] just for testing
test_cntr, // [3:0] just for testing
test_cntr1 // [3:0] just for testing
`endif
);
input clk;
input clk2x;
input cwe;
input wr_saturation;
input wr_quantizer_mode;
input rs;
input twqe;
input twce;
input twhe;
input twfe;
// input [11:0] ta;
input [ 9:0] ta;
input [15:0] di;
input vacts_long; // long vacts pulse (15 scan lines) to delay comprssor start (@pixel clock, need re-sync)
output eot;
output done_input; // will go high after EOT and persist until DCT is enabled
output done_compress; // will go high after all data is sent out
output done_compress_pulse; // Does not need to be reset
output compressor_started;
output is_compressing;
input chInitOnehot2; // @negedge clk2x
input nextBlocksEn; // (@negedge clk2x) When combined with SDRAM data ready, may be used to end frame compression input (instead of block counter)
input [ 7:0] pxd;
output [10:0] pxa;
input pxrdy;
output nxtpage;
output inc_sdrama;
output confirmFrame2Compressor;
output restart_memory; // restart memory channel (to align after broken frames) - masked by enable bit in memory controller
input bonded; // channel bonded with the other (just for channel 2), make it TIG
input [ 1:0] bayer_phase;
input dccout;
input [2:0] hfc_sel;
output statistics_dv;
output [15:0] statistics_do;
input [31:0] sec;
input [19:0] usec;
output [15:0] q;
output qv;
output [23:0] imgptr;
output [31:0] hifreq;
input dma_is_reset; // DMA module is reset, enable resetting data counters
output [ 2:0] test_state; // {is_compressing, cmprs_repeat,cmprs_en}
// wire is_compressing; // from go_single to eot (@posedge clk)
`ifdef debug_compressor
output [31:0] test_cntr0;
`endif
`ifdef debug_stuffer
output [3:0] tst_stuf_negedge;
output [3:0] tst_stuf_posedge;
output [3:0] tst_stuf_etrax;
output [3:0] test_cntr;
output [7:0] test_cntr1;
`endif
wire [ 9:0] m_cb; // variable Cb coefficient (was 'h90 constant)
wire [ 9:0] m_cr; // variable Cr coefficient (was 'hb6 constant)
reg [15:0] stuffer_do_p;
reg stuffer_dv_p;
wire [15:0] q;
wire qv;
wire [ 1:0] bayer_phase;
wire [7:0] n000; // number of zero pixels (255 if 256) in a 16x16 tile (overlap ignored,before color conversion)
wire [7:0] n255; // number of 0xff pixels (255 if 256) in a 16x16 tile (overlap ignored,before color conversion)
wire [15:0] dccdata;
reg finish_dcc;
wire dccvld;
wire dccout;
reg dcc_en;
wire eot;
wire eot_real;
wire nxtpage;
//TODO: move focus control outside,
// add second bit to scaling differences (not just 0.5 and 1.0, but also 0.75 - probably most reasonable)
//================NOTE: After memory controller is reprogrammed, compressor should be reset (reset+restarted) - else buffer pages would mismatch (seen that) =============================
// wire [ 8:0] ta; // now inputs
// wire twqe;
// wire twhe;
// new control bits:
// [23] ==1 - set focus mode
// [22:21] 0 - none
// 1 - replace
// 2 - combine for all image
// 3 - combine in window only
// [20] ==1 - set bayer shift (from the gammas)
// [19:18] - bayer shift value (from the gammas)
// [17] == 1 - set processed tile position in the 20x20 tile got from memory
// [16:14] 0 - top left alignment
// 1 - 1 pixel right and 1 - down from the top left alignment
// 2 - 2 pixels right and 2 - down from the top left alignment
// 3 - 3 pixels right and 3 - down from the top left alignment
// 4 - 4 pixels right and 4 - down from the top left alignment
// [13]==1 - enable color modes
// [12:9]== 0 - monochrome, (4:2:0),
// 1 - color, 4:2:0, 18x18(old)
// 2 - jp4, original (4:2:0),
// 3 - jp4, dc -improved (4:2:0),
// 4 - color, 4:2:0, 20x20, middle of the tile (not yet implemented)
// 5 - jp4, 4 blocks, (legacy)
// 6 - jp4, 4 blocks, dc -improved
// 7 - jp4, 4 blocks, differential red := (R-G1), blue:=(B-G1), green=G1, green2 (G2-G1). G1 is defined by Bayer shift, any pixel can be used
// 8 - jp4, 4 blocks, differential HDR: red := (R-G1), blue:=(B-G1), green=G1, green2 (high gain)=G2) (G1 and G2 - diagonally opposite)
// 9 - jp4, 4 blocks, differential, divide differences by 2: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (G2-G1)/2
// 10 - jp4, 4 blocks, differential HDR: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (high gain)=G2),
// 11-13 - reserved
// 14 - mono, 4 blocks
// 15 - reserved
// [8:7] == 0,1 - NOP, 2 - disable, 3 - enable subtracting of average value (DC component), bypassing DCT
// [6] == 1 - enable quantization bank select, 0 - disregard bits [5:3]
// [5:3] = quantization page number (0..7)
// [2]== 1 - enable on/off control:
// [1:0]== 0 - reset compressor, stop immediately
// 1 - enable compressor, disable repetitive mode
// 2 - enable compressor, compress single frame
// 3 - enable compressor, enable repetitive mode
//
// control registetr bits
wire cr_w; // data written to cr (1 cycle) - now just to reset legacy IRQ
wire raw_dv; // input pixel data valid (pxd[7:0]may be sent to DMA buffer through multiplexor)
wire color_dv; // unused // color data valid (color_d[7:0] may be sent to DMA buffer through multiplexor)
wire [ 9:0] color_d; // data out stream from color space converter (6X64 blocks for each MCU - 4Y, Cb,Cr)
wire [ 2:0] color_tn; // tile number in an MCU from color space converter (valid @ color_dv)
wire [ 8:0] color_avr; // [8:0] DC (average value) 9 bit signed for Y: 9'h000..9'h0ff, for C - 9h100..9'h000..9'h0ff
wire color_first; // sending first MCU (valid @ ds)
wire color_last; // sending last MCU (valid @ ds)
// wire dct_en;
wire dct_start;
wire dct_dv;
wire [12:0] dct_out;
wire dct_last_in; // output high during input of the last of 64 pixels in a 8x8 block
wire dct_pre_first_out; // 1 cycle ahead of the first output in a 64 block
wire [17:0] ntiles; //number of 16x16 MCU tiles in a frame to process
reg quant_start;
wire [12:0] quant_do;
// wire quant_dv;
wire quant_ds;
//usefocus
wire [12:0] focus_do;
wire focus_ds;
// wire enc_first;
wire enc_last;
wire [15:0] enc_do;
wire enc_dv;
wire [15:0] huff_do;
wire [ 3:0] huff_dl;
wire huff_dv;
wire flush; // flush stuffer
wire stuffer_rdy;
//assign stuffer_rdy=1'b1;
wire [15:0] stuffer_do;
wire stuffer_dv;
wire stuffer_done;
reg stuffer_done_persist;
reg done_input; // will go high after EOT and persist until DCT is enabled
reg done_compress; // will go high after all data is sent out
reg [1:0] stuffer_done_sync;
reg done_compress_pulse;
reg [1:0] compressor_starting;
reg compressor_started; // sync @(negedge clk2x)
// interclock sync
reg cmprs_en_2x_n; // enable DCT (0- resets buffer pages) - negedge, earlier than
// reg cmprs_en_2x_p; // enable DCT (0- resets buffer pages) - posedge
reg cr_w_2x_n; // 2 cycles long
// reg cr_w_2x_p; // 2 cycles long
reg wr_saturation_d; //wr_saturation next
// reg wr_quantizer_mode_d;
reg pre_finish_dcc;
// reg [1:0] vlong;
reg vlong;
reg vlong1_or_not_bonded;
reg not_vlong1_or_not_bonded;
// reg go_dly;
reg go_rq; // request for "go" pulse (will wait for the end of vlong[1] if started during that time
reg go_single; // single pulse to start/restart compressor (not in the vacts_long interval)
wire confirmFrame2Compressor;
wire is_compressing; // from go_single to eot (@posedge clk)
wire is_compressing_d; // delayed by several cycles (8) to overlap possible abort_compress_clk;
wire force_flush; // force flush - abort compressing (when writing tiles during is_compressing)
// single cycle @ negedge clk2x
reg abort_compress; //from force_flush till stuffer_done @negedge clk2x
reg [1:0] abort_compress_clk; // sync to posedge clk - at the end will be simulated
reg force_eot;
wire [2:0] memWasInit; // syncronizing chInitOnehot2 to clk so buffer page may be reset
wire cmprs_en;
wire cmprs_start;
wire cmprs_repeat;
wire [ 2:0] cmprs_qpage;
wire cmprs_dcsub;
wire [ 3:0] cmprs_mode;
wire [ 1:0] cmprs_fmode;
wire [ 2:0] tile_shift;
// signals synchronized to start of frame compress
reg [ 2:0] cmprs_qpage_this;
reg cmprs_dcsub_this;
// reg [ 3:0] cmprs_mode_this;
reg [ 1:0] cmprs_fmode_this;
reg [ 2:0] tile_shift_this;
reg [ 1:0] cmprs_bayer_this;
wire pre_go_single;
reg ignore_color; // ignore color information
reg four_blocks;
reg jp4_dc_improved;
reg [ 1:0] tile_margin;
reg [ 2:0] converter_type; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff , 5 jp4-diff, divide diffs by 2
wire [1:0] bayer_shift;
wire [2:0] component_num; //[1:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift)
wire component_color; // use color quantization table (YCbCR, jp4diff)
wire component_first; // first this component in a frame (DC absolute, otherwise - difference to previous)
wire component_lastinmb; // last component in a macroblock;
reg scale_diff;
reg hdr;
reg confirm_en;
reg confirm;
wire restart_memory;
reg noMoreData_en=0; // enable noMoreData (to delay noMoreData, preventing it from the previous frame)
reg noMoreData; // used as alternative to end frame input (possibly broken frame)
reg [ 1:0] nextBlocksEnS; // re-sync to clock
assign test_state={is_compressing,cmprs_repeat,cmprs_en};
// input dma_is_reset; // DMA module is reset, enable resetting data counters
reg [1:0] reset_data_counters;
always @ (negedge clk2x) begin
reset_data_counters[1:0] <={reset_data_counters[0], dma_is_reset && !cmprs_en_2x_n};
end
assign eot=eot_real || force_eot; // force_eot during abort compress
// input dma_is_reset; // DMA module is reset, enable resetting data counters
// assign finish_dcc=stuffer_done;
assign q[15:0]= stuffer_do_p[15:0];
assign qv= stuffer_dv_p;
// assign pre_go_single= cmprs_en && go_rq && !vlong[1] && !is_compressing && !go_single;
assign pre_go_single= cmprs_en &&
go_rq &&
// !vlong[1] &&
not_vlong1_or_not_bonded &&
!is_compressing &&
!is_compressing_d &&
!abort_compress_clk[1] &&
!go_single;
always @ (posedge clk) begin
confirm_en <= cmprs_en;
// confirm <= confirm_en && (go_single || (confirm && !inc_sdrama));
confirm <= confirm_en && (go_single || // confirm memory so it can start reading new frame
// memWasInit[2] || // re-confirm memory if it was reset
// (confirm && !inc_sdrama));
(confirm && !nxtpage)); // until the next block is requestedfrom SDRAM
nextBlocksEnS[1:0] <= {nextBlocksEnS[0], nextBlocksEn};
noMoreData_en <= cmprs_en && (nxtpage || (noMoreData_en && !go_single));
/// noMoreData <= noMoreData_en && confirm_en && !confirm && !nextBlocksEnS[1] && !nextBlocksEnS[0] && !pxrdy;
// noMoreData <= confirm_en && !confirm && !nextBlocksEnS[1] && !nextBlocksEnS[0] && !pxrdy;
// noMoreData <= confirm_en && !confirm && !nextBlocksEnS[1] && !nextBlocksEnS[0] && !pxrdy && !go_rq;
noMoreData <= confirm_en &&
!confirm &&
!nextBlocksEnS[1] && !nextBlocksEnS[0] &&
!pxrdy &&
(!go_rq || is_compressing); // prevent noMoreData when just starting, but not when could not finish (too high fps)
end
reg bonded_sync;
always @ (posedge clk) bonded_sync <= bonded; // TIG
/// assign confirmFrame2Compressor= go_rq;
assign confirmFrame2Compressor= confirm;
assign restart_memory=go_single;
//restart_memory
/// synchronizing chInitOnehot2 from negedge clk2x to posedge clk
FDCE_1 i_memWasInit0 (.C(clk2x),.CE(chInitOnehot2),.CLR(memWasInit[2]), .D(1'b1), .Q(memWasInit[0]));
FD i_memWasInit1 (.C(clk), .D(memWasInit[0]), .Q(memWasInit[1]));
FD i_memWasInit2 (.C(clk), .D(memWasInit[1] & !memWasInit[2]),.Q(memWasInit[2]));
//TODO: add longer delay between frames to make sure they will not get corruped because of the trailer?
FD i_is_compressing (.Q(is_compressing),.C(clk), .D(cmprs_en && (go_single || (is_compressing && !eot)) ));
// SRL16 i_is_compressing_d(.Q(is_compressing_d),.D(is_compressing_d), .CLK(clk), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0)); // dly=7+1
SRL16 i_is_compressing_d(.Q(is_compressing_d),.D(is_compressing), .CLK(clk), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0)); // dly=7+1
always @ (negedge clk2x) begin
abort_compress <= cmprs_en_2x_n && (force_flush || (abort_compress && !stuffer_done));
end
always @ (posedge clk) begin
abort_compress_clk[1:0] <= {abort_compress_clk[0],abort_compress};
force_eot <= abort_compress_clk[0] && !abort_compress_clk[1];
end
always @ (posedge clk) begin // any write to cr will reset done
// vlong[1:0] <= {vlong[0],vacts_long}; // dual sync
vlong <= vacts_long; // dual sync
vlong1_or_not_bonded <= vlong || !bonded_sync;
not_vlong1_or_not_bonded <= !vlong || !bonded_sync;
// go_rq <= cmprs_en && (cmprs_start || (cmprs_repeat && vlong[1]) || (go_rq && !go_single));
go_rq <= cmprs_en && (cmprs_start || (cmprs_repeat && vlong1_or_not_bonded) || (go_rq && !go_single));
go_single <= pre_go_single;
if (pre_go_single) begin
cmprs_qpage_this[2:0]<=cmprs_qpage[2:0];
cmprs_dcsub_this <=cmprs_dcsub;
// cmprs_mode_this[3:0] <=cmprs_mode[3:0];
cmprs_fmode_this[1:0]<=cmprs_fmode[1:0];
tile_shift_this[2:0]<= tile_shift[2:0];
// will inctanciate ROM
case (cmprs_mode[3:0])
4'h0: begin //monochrome, (4:2:0),
ignore_color <= 1;
four_blocks <= 0;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 2; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{tile_shift[0]}};
end
4'h1: begin //color, 4:2:0, 18x18(old)
ignore_color <= 0;
four_blocks <= 0;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 1;
converter_type[2:0] <= 0; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{tile_shift[0]}};
end
4'h2: begin // jp4, original (4:2:0),
ignore_color <= 1;
four_blocks <= 0;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 3; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{tile_shift[0]}};
end
4'h3: begin // jp4, dc -improved (4:2:0),
ignore_color <= 1;
four_blocks <= 0;
jp4_dc_improved <= 1;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 3; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{tile_shift[0]}};
end
4'h4: begin // color, 4:2:0, 20x20, middle of the tile (not yet implemented)
ignore_color <= 0;
four_blocks <= 0;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 2;
converter_type[2:0] <= 1; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{~tile_shift[0]}};
end
4'h5: begin // jp4, 4 blocks, (legacy)
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 3; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{~tile_shift[0]}};
end
4'h6: begin // jp4, 4 blocks, dc -improved
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 1;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 3; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{~tile_shift[0]}};
end
4'h7: begin // jp4, 4 blocks, differential
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 4; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{~tile_shift[0]}};
end
4'h8: begin // jp4, 4 blocks, differential, hdr
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 4; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=1;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{~tile_shift[0]}};
end
4'h9: begin // jp4, 4 blocks, differential, divide diff by 2
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 4; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=1;
hdr <=0;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{~tile_shift[0]}};
end
4'ha: begin // jp4, 4 blocks, differential, hdr, divide diff by 2
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 4; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=1;
hdr <=1;
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{~tile_shift[0]}};
end
4'he: begin // mono, 4 blocks
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
tile_margin[1:0] <= 0;
converter_type[2:0] <= 2; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
cmprs_bayer_this[1:0] <= (bayer_phase[1:0]+bayer_shift[1:0]) ^ {2{~tile_shift[0]}};
end
endcase
end
end
// [12:9]== 0 - color, 4:2:0
// 1 - monochrome, (4:2:0),
// 2 - jp4, original (4:2:0),
// 3 - jp4, dc -improved (4:2:0),
// 4 - color, 4:2:0, 20x20, middle of the tile (not yet implemented)
// 5 - jp4, 4 blocks, (legacy)
// 6 - jp4, 4 blocks, dc -improved
// 7 - jp4, 4 blocks, differential red := (R-G1), blue:=(B-G1), green=G1, green2 (G2-G1). G1 is defined by Bayer shift, any pixel can be used
// 8 - jp4, 4 blocks, differential HDR: red := (R-G1), blue:=(B-G1), green=G1, green2 (high gain)=G2) (G1 and G2 - diagonally opposite)
// 9 - jp4, 4 blocks, differential, divide differences by 2: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (G2-G1)/2
// 10 - jp4, 4 blocks, differential HDR: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (high gain)=G2),
// 11-13 - reserved
// 14 - mono, 4 blocks
// 15 - reserved
always @ (negedge clk2x) begin
cmprs_en_2x_n <= cmprs_en;
cr_w_2x_n <= cr_w;
end
always @ (posedge clk2x) begin
// cmprs_en_2x_p <= cmprs_en_2x_n;
// cr_w_2x_p <= cr_w_2x_n;
end
always @ (negedge clk2x) begin // any write to cr will reset done
stuffer_done_persist <= !cr_w_2x_n && cmprs_en_2x_n && (stuffer_done_persist || stuffer_done );
done_compress <= !cr_w_2x_n && cmprs_en_2x_n && (done_compress || stuffer_done_persist);
stuffer_done_sync[1:0] <= {stuffer_done_sync[0],stuffer_done};
done_compress_pulse <= stuffer_done_sync[0] && !stuffer_done_sync[1];
compressor_starting[1:0] <= {compressor_starting[0],color_first & dct_start};
compressor_started <= (color_tn[2:0]==3'h0) &&compressor_starting[0] && !compressor_starting[1]; // sync @(negedge clk2x)
end
always @ (posedge clk) begin // any write to cr will reset done
done_input <= !cr_w && cmprs_en && (done_input || eot);
end
always @ (posedge clk2x) begin
stuffer_do_p[15:0] <= stuffer_do[15:0];
stuffer_dv_p <= stuffer_dv;
end
wire stuffer_flushing;
`ifdef debug_stuffer
//testing
reg [3:0] tst_stuf_negedge, tst_stuf_posedge;
reg tst_enc_dv_r;
// always @ (negedge clk2x) begin // any write to cr will reset done
// cmprs_en_2x_n
/*if (!cmprs_en_2x_n) tst_stuf_negedge <=0;
else*/ //if (stuffer_dv) tst_stuf_negedge <= tst_stuf_negedge+1;
// end
// always @ (posedge clk2x) begin // any write to cr will reset done
/*if (!cmprs_en) tst_stuf_posedge <=0;
else*/ //if (stuffer_dv_p) tst_stuf_posedge <= tst_stuf_posedge+1;
// end
always @ (negedge clk2x) begin
tst_enc_dv_r <= enc_dv;
if (stuffer_done) tst_stuf_negedge <=0;
else if (tst_enc_dv_r) tst_stuf_negedge <= tst_stuf_negedge+1; // twice per
end
always @ (posedge clk) begin // any write to cr will reset done
// if (stuffer_done) tst_stuf_negedge <=0;
// else if (enc_dv) tst_stuf_negedge <= tst_stuf_negedge+1;
if (go_single) tst_stuf_posedge <= 0;
else if (enc_dv) tst_stuf_posedge <= tst_stuf_posedge+1;
end
`endif
always @ (negedge clk2x) pre_finish_dcc <= stuffer_done;
always @ (posedge clk2x) finish_dcc <= pre_finish_dcc; //stuffer+done - @negedge clk2x
//propagation of first block through compressor pipeline
wire first_block_color=(color_tn[2:0]==3'h0) && color_first; // while color conversion,
reg first_block_color_after; // after color conversion,
reg first_block_dct; // after DCT
wire first_block_quant; // after quantizer
always @ (posedge clk) begin
if (dct_start) first_block_color_after <= first_block_color;
if (dct_last_in) first_block_dct <= first_block_color_after;
end
compr_ifc i_compr_ifc (.clk(clk), // pixel clock (80MHz)
.sclk(clk2x), // system clock (160MHz)
.cwe(cwe), // we to compressor from CPU (sync to negedge sclk)
.rs(rs), // register select:
// 0 - bit modes,
// 1 - write ntiles;
.di(di[15:0]), // [15:0] data from CPU
.cr_w(cr_w), // data written to cr (1 cycle long)
.ntiles(ntiles[17:0]),// - number of 16x16 MCU tiles in a frame to process
.cmprs_en(cmprs_en), // enable compressor
.cmprs_start(cmprs_start), // single cycle when single or constant compression is turned on
.cmprs_repeat(cmprs_repeat),// high in repetitive mode
.cmprs_qpage(cmprs_qpage), // [2:0] - quantizator page number (0..7)
.cmprs_dcsub(cmprs_dcsub), // subtract dc level before DCT, restore later
.cmprs_mode(cmprs_mode), // [3:0] - compressor mode
.cmprs_shift(tile_shift[2:0]), // tile shift from top left corner
.cmprs_fmode(cmprs_fmode), //[1:0] - focus mode
.bayer_shift(bayer_shift), // additional shift to bayer mosaic
.is_compressing(is_compressing), // high from start of compressing till EOT (sync to posedge clk)
.abort_compress(abort_compress),
.force_flush(force_flush)); // abort compress - generate flush pulse, force end of image over DMA, update counter
// single-cycle @ negedge sclk
`ifdef debug_compressor
wire debug_bcntrIsZero;
wire [17:0] debug_bcntr;
`endif
color_proc i_color_proc(.clk(clk), // pixel clock 37.5MHz
.en(cmprs_en), // Enable (0 will reset states)
.en_sdc(cmprs_dcsub_this), // enable subtracting of DC component
.go(go_single), // now - always single-cycle pulse (TODO: simplify color_proc)
.nblocks(ntiles[17:0]),// [15:0] number of 16x16 blocks to read (valid @ "go" pulse only)
.eot(eot_real), // single-cycle end of transfer pulse
.m_cb(m_cb[9:0]), // [9:0] scale for CB - default 0.564 (10'h90)
.m_cr(m_cr[9:0]), // [9:0] scale for CB - default 0.713 (10'hb6)
.ignore_color(ignore_color), //zero Cb/Cr components
.four_blocks(four_blocks), // use only 6 blocks for the output, not 6
.jp4_dc_improved(jp4_dc_improved), // in JP4 mode, compare DC coefficients to the same color ones
.tile_margin(tile_margin[1:0]), // margins around 16x16 tiles (0/1/2)
.tile_shift(tile_shift_this[2:0]), // tile shift from top left corner
.converter_type(converter_type[2:0]), // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
.scale_diff(scale_diff), // divide differences by 2 (to fit in 8-bit range)
.hdr(hdr), // second green absolute, not difference
.memWasInit(memWasInit[2]), // memory channel2 was just initialized - reset page address
.di(pxd[7:0]), // [7:0]
.sdram_a(pxa[10:0]), // [10:0] (2 MSBs - SDRAM buffer page number)
.sdram_rdy(pxrdy), // SDRAM buffer ready
.sdram_next(nxtpage), // request to read a page to SDRAM buffer
.inc_sdrama(inc_sdrama), // enable read sdram buffer
.noMoreData(noMoreData), // used as alternative to end frame input (possibly broken frame)
.dv_raw(raw_dv), // data valid for di (for testing to bypass color conversion - use di[7:0])
// .do(color_d[8:0]), // [9:0] data out (4:2:0) (signed, average=0)
.do(color_d[9:0]), // [9:0] data out (4:2:0)
.avr(color_avr[8:0]), // [8:0] DC (average value) - RAM output, no register. For Y components 9'h000..9'h0ff, for C - 9'h100..9'h0ff
.dv(color_dv), // out data valid (will go high for at least 64 cycles)
.ds(dct_start), // single-cycle mark of the first pixel in a 64 (8x8) - pixel block
.tn(color_tn[2:0]), // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start)
.first(color_first), // sending first MCU (valid @ ds)
.last(color_last), // sending last MCU (valid @ ds)
.n000(n000[7:0]), // [7:0] number of zero pixels (255 if 256)
.n255(n255[7:0]), // [7:0] number of 0xff pixels (255 if 256)
.bayer_phase(cmprs_bayer_this[1:0]), // bayer color filter phase 0:(GR/BG), 1:(RG/GB), 2: (BG/GR), 3: (GB/RG)
// below signals valid at ds ( 1 later than tn, first, last)
.component_num(component_num[2:0]), //[1:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift) >=4 - don't use
.component_color(component_color), // use color quantization table (YCbCR, jp4diff)
.component_first(component_first), // first this component in a frame (DC absolute, otherwise - difference to previous)
.component_lastinmb(component_lastinmb) // last component in a macroblock;
`ifdef debug_compressor
,.bcntrIsZero(debug_bcntrIsZero)
,.bcntr(debug_bcntr[17:0])
`endif
);
//assign color_d[9]=color_d[8]; // temporary
xdct i_xdct ( .clk(clk), // top level module
.en(cmprs_en), // if zero will reset transpose memory page numbers
.start(dct_start), // single-cycle start pulse that goes with the first pixel data. Other 63 should follow
.xin(color_d[9:0]), // [7:0] - input data
.last_in(dct_last_in), // output high during input of the last of 64 pixels in a 8x8 block //
.pre_first_out(dct_pre_first_out),// 1 cycle ahead of the first output in a 64 block
.dv(dct_dv), // data output valid. Will go high on the 94-th cycle after the start
.d_out(dct_out[12:0]));// [12:0]output data
// probably dcc things are not needed anymore
always @ (posedge clk) quant_start <= dct_pre_first_out;
always @ (posedge clk) begin
if (!dccout) dcc_en <=1'b0;
else if (dct_start && color_first && (color_tn[2:0]==3'b001)) dcc_en <=1'b1; // 3'b001 - closer to the first "start" in quantizator
end
wire [15:0] quant_dc_tdo;// MSB aligned coefficient for the DC component (used in focus module)
//wire [3:0] coring_num;
wire [2:0] coring_num;
quantizator i_quantizator(.clk(clk), // pixel clock
.en(cmprs_en), // enable (0 resets counter)
.sclk(clk2x), // system clock, twe, ta,tdi - valid @negedge (ra, tdi - 2 cycles ahead
.twqe(twqe), // enable write to a table
.twce(twce), // coring functions tables (@negedge clk - addr and data valid this cycle and one before)
.ta(ta[8:0]), // [6:0] table address
.tdi(di[15:0]), //
.ctypei(component_color), // component type input (Y/C)
.dci(color_avr[8:0]), // [8:0] - average value in a block - subtracted before DCT (now 9 bits signed)
.first_stb(first_block_color), //this is first stb pulse in a frame
.stb(dct_start), // strobe that writes ctypei, dci
.tsi(cmprs_qpage_this[2:0]), // table (quality) select
.pre_start(dct_pre_first_out),
.first_in(first_block_dct), // first block in (valid @ start)
.first_out(first_block_quant), // valid @ ds
.di(dct_out[12:0]), // [8:0] pixel data in (signed)
.do(quant_do[12:0]), // [11:0] pixel data out signed
// .dv(quant_dv), // data out valid
.dv(), // data out valid
.ds(quant_ds), // data out strobe (one ahead of the start of dv)
.dc_tdo(quant_dc_tdo[15:0]), //[15:0], MSB aligned coefficient for the DC component (used in focus module)
// .dc_tdo_stb(quant_dc_tdo_stb),
.dcc_en(dcc_en), // enable dcc (sync to beginning of a new frame)
.hfc_sel(hfc_sel), // hight frequency components select [2:0] (includes components with both numbers >=hfc_sel
.color_first(color_first), // first MCU in a frame NOTE: ONLY NEEDED for DCC
.coring_num(coring_num), ///coring table par number
.dcc_vld(dccvld),
.dcc_data(dccdata[15:0]),
.n000(n000[7:0]), // input [7:0] number of zero pixels (255 if 256) - to be multiplexed with dcc
.n255(n255[7:0])); // input [7:0] number of 0xff pixels (255 if 256) - to be multiplexed with dcc
//TODO: compact table
focus_sharp i_focus_sharp(.clk(clk), // pixel clock
.en(cmprs_en), // enable (0 resets counter)
.sclk(clk2x), // system clock, twe, ta,tdi - valid @negedge (ra, tdi - 2 cycles ahead
.twe(twfe), // enable write to a table
.ta(ta[9:0]), // [9:0] table address
.tdi(di[15:0]), // [15:0] table data in (8 LSBs - quantization data)
.mode(cmprs_fmode_this[1:0]), // focus mode (combine image with focus info) - 0 - none, 1 - replace, 2 - combine all, 3 - combine woi
// .stren(focus_strength),
.firsti(color_first), // first macroblock
.lasti(color_last), // last macroblock
.tni(color_tn[2:0]), // block number in a macronblock - 0..3 - Y, >=4 - color (sync to stb)
.stb(dct_start), // strobe that writes ctypei, dci
.start(quant_start),// marks first input pixel (needs 1 cycle delay from previous DCT stage)
.di(dct_out[12:0]), // [11:0] pixel data in (signed)
.quant_ds(quant_ds), // quantizator data strobe (1 before DC)
.quant_d(quant_do[12:0]), // quantizator data output
.quant_dc_tdo(quant_dc_tdo[15:0]), //[15:0], MSB aligned coefficient for the DC component (used in focus module)
// .quant_dc_tdo_stb(quant_dc_tdo_stb),
.do(focus_do[12:0]), // [11:0] pixel data out (AC is only 9 bits long?) - changed to 10
.ds(focus_ds), // data out strobe (one ahead of the start of dv)
.hifreq(hifreq[31:0]) //[31:0]) // accumulated high frequency components in a frame sub-window
);
dcc_sync i_dcc_sync(//.clk(clk),
.sclk(clk2x),
.dcc_en(dcc_en), // clk rising, sync with start of the frame
.finish_dcc(finish_dcc), // sclk rising
.dcc_vld(dccvld), // clk rising
.dcc_data(dccdata[15:0]), //[15:0] clk risimg
.statistics_dv(statistics_dv), //sclk
.statistics_do(statistics_do[15:0])//[15:0] sclk
);
// generate DC data/strobe for the direct output (re) using sdram channel3 buffering
// encoderDCAC is updated to handle 13-bit signed data instead of the 12-bit. It will limit the values on ot's own
encoderDCAC i_encoderDCAC(.clk(clk),
.en(cmprs_en),
// .firsti(color_first), // was "first MCU in a frame" (@ stb)
.lasti(color_last), // was "last MCU in a frame" (@ stb)
// .tni(color_tn[2:0]), // [2:0] tile number in MCU (0..5) - was valid @ stb
.first_blocki(first_block_color), // first block in frame - save fifo write address (@ stb)
.comp_numberi(component_num[2:0]), // [2:0] component number 0..2 in color, 0..3 - in jp4diff, >= 4 - don't use (@ stb)
.comp_firsti(component_first), // fitst this component in a frame (reset DC) (@ stb)
.comp_colori(component_color), // use color - huffman? (@ stb)
.comp_lastinmbi(component_lastinmb), // last component in a macroblock (@ stb)
.stb(dct_start), // strobe that writes firsti, lasti, tni,average
.zdi(focus_do[12:0]), // [12:0]
.first_blockz(first_block_quant), // first block input (@zds)
.zds(focus_ds), // strobe - one ahead of the DC component output
.last(enc_last), // - not used
.do(enc_do[15:0]),
.dv(enc_dv)
);
wire last_block, test_lbw;
huffman i_huffman (.pclk(clk), // pixel clock
.clk(clk2x), // twice frequency - uses negedge inside
.en(cmprs_en), // enable (0 resets counter) sync to .pclk(clk)
// .cwr(cwr), // CPU WR global clock
.twe(twhe), // enable write to a table
.ta(ta[8:0]), // [8:0] table address
.tdi(di[15:0]), // [23:0] table data in (8 LSBs - quantization data, [13:9] zigzag address
.di(enc_do[15:0]), // [15:0] specially RLL prepared 16-bit data (to FIFO)
.ds(enc_dv), // di valid strobe
.rdy(stuffer_rdy), // receiver (bit stuffer) is ready to accept data
.do(huff_do), // [15:0] output data
.dl(huff_dl), // [3:0] output width (0==16)
.dv(huff_dv), // output data bvalid
.flush(flush),
.last_block(last_block),
.test_lbw(),
.gotLastBlock(test_lbw)); // last block done - flush the rest bits
`ifdef debug_compressor
reg eot_2x_n,stuffer_flush_enable;
// wire stuffer_flushing;
always @ (negedge clk2x) begin
eot_2x_n <=eot;
stuffer_flush_enable <= cmprs_en_2x_n && (stuffer_flush_enable?(!stuffer_flushing):eot_2x_n);
end
reg [31:0] test_cntr0;
reg [1:0] was_flush;
reg [1:0] was_eot;
reg [1:0] was_last_block;
reg [1:0] was_test_lbw;
reg [1:0] was_go_single;
reg [1:0] was_is_compressing;
// reg [1:0] was_go_single;
reg [1:0] was_bcntrIsZero;
reg [1:0] was_go_rq;
always @ ( negedge clk2x) begin
// was_flush[1:0] <= {was_flush[0],flush};
was_flush [1:0] <= {was_flush[0], flush && stuffer_flush_enable};
// was_eot [1:0] <= {was_eot[0], eot_2x_n};
was_last_block[1:0] <= {was_last_block[0],last_block};
was_test_lbw [1:0] <= {was_test_lbw[0], test_lbw};
was_go_single[1:0] <= {was_go_single[0],go_single};
was_is_compressing [1:0] <= {was_is_compressing[0], is_compressing};
// if (!cmprs_en_2x_n) test_cntr0[7:0] <= 0;
// else if (was_flush[1:0]==2'h1) test_cntr0[7:0] <=test_cntr0[7:0] + 1; // 1->7a (was 7b without mask?)
//// if (!cmprs_en_2x_n) test_cntr0[15:8] <= 0;
//// else if (was_eot[1:0]==2'h1) test_cntr0[15:8] <=test_cntr0[15:8] + 1; // 1->7a !!!
////// if (!cmprs_en_2x_n) test_cntr0[23:16] <= 0;
////// else if (was_last_block[1:0]==2'h1) test_cntr0[23:16] <=test_cntr0[23:16] + 1; // 1->7b
////// if (!cmprs_en_2x_n) test_cntr0[31:24] <= 0;
////// else if (was_test_lbw[1:0]==2'h1) test_cntr0[31:24] <=test_cntr0[31:24] + 1; // 1->7b
//// if (!cmprs_en_2x_n) test_cntr0[23:16] <= 0;
//// else if (was_go_single[1:0]==2'h1) test_cntr0[23:16] <=test_cntr0[23:16] + 1; // 1->2
//// if (!cmprs_en_2x_n) test_cntr0[31:24] <= 0;
//// else if (was_is_compressing[1:0]==2'h1) test_cntr0[31:24] <=test_cntr0[31:24] + 1; // 1->2
end
// debug_bcntrIsZero
// reg [1:0] was_go_single;
// reg [1:0] was_bcntrIsZero;
// debug_bcntrIsZero
reg debug1;
always @ ( posedge clk) begin
was_eot [1:0] <= {was_eot[0], eot};
was_go_rq [1:0] <= {was_go_rq[0], go_rq};
was_bcntrIsZero [1:0] <= {was_bcntrIsZero[0], debug_bcntrIsZero};
//// test_cntr0[7:0] <= debug_bcntr[7:0]; // 0 -> 0 -> 78 -> 78 -> 78
/// test_cntr0[15:0] <= debug_bcntr[15:0]; // 0 -> 0 -> 78 -> 78 -> 78
// if (was_go_rq[1:0]==2'h1) test_cntr0[15:8] <= 0;
// else if (was_eot[1:0]==2'h1) test_cntr0[15:8] <=test_cntr0[15:8] + 1;
// if (!cmprs_en) test_cntr0[23:16] <= 0;
// else if (go_single) test_cntr0[23:16] <=test_cntr0[23:16] + 1; // 0 -> 1 -> 2 -> 3 -> 4
// if (!cmprs_en) test_cntr0[31:24] <= 0;
// else if (was_bcntrIsZero[1:0]==2'h1) test_cntr0[31:24] <=test_cntr0[31:24] + 1; // 0 -> 1 -> 1 -> 2 -> 3
// should end up 1 more than number of blocks?
// if (go_single) test_cntr0[31:16] <= 0;
// else if (nxtpage) test_cntr0[31:16] <=test_cntr0[31:16] + 1; //
if (go_single) test_cntr0[15:0] <= 0;
else if (nxtpage) test_cntr0[14:0] <= test_cntr0[14:0] + 1; //
if (go_single) test_cntr0[30:16] <= test_cntr0[14:0];
if (was_go_rq[1:0]==2'h1) debug1 <= 1'b0;
else if (pxrdy) debug1 <= 1'b1;
if (go_single) test_cntr0[31] <= debug1;
test_cntr0[15] <= pxrdy;
end
`endif
stuffer i_stuffer (.clk(clk2x), //clock - uses negedge inside
.en(cmprs_en_2x_n), // enable, 0- reset
.reset_data_counters(reset_data_counters[1]), // reset data transfer counters (only when DMA and compressor are disabled)
// .flush(flush), // flush output data (fill byte with 0, long word with FFs
.flush(flush || force_flush), // flush output data (fill byte with 0, long word with FFs
.stb(huff_dv), // input data strobe
.dl(huff_dl), // [3:0] number of bits to send (0 - 16)
.d(huff_do), // [15:0] input data to shift (only lower bits are valid)
// time stamping - will copy time at the end of color_first (later than the first hact after vact in the current froma, but before the next one
// and before the data is needed for output
.color_first(color_first), //
.sec(sec[31:0]),
.usec(usec[19:0]),
.rdy(stuffer_rdy), // enable huffman encoder to proceed. Used as CE for many huffman encoder registers
.q(stuffer_do), // [15:0] output data
.qv(stuffer_dv), // output data valid
.done(stuffer_done),
.imgptr (imgptr[23:0]), // [23:0]image pointer in 32-byte chunks
.flushing(stuffer_flushing)
`ifdef debug_stuffer
,.etrax_dma_r(tst_stuf_etrax[3:0]) // [3:0] just for testing
,.test_cntr(test_cntr[3:0])
,.test_cntr1(test_cntr1[7:0])
`endif
);
always @ (negedge clk2x) wr_saturation_d <= wr_saturation;
FDE_1 i_m_cb0 (.C(clk2x),.CE(wr_saturation),.D(di[ 0]),.Q(m_cb[0]));
FDE_1 i_m_cb1 (.C(clk2x),.CE(wr_saturation),.D(di[ 1]),.Q(m_cb[1]));
FDE_1 i_m_cb2 (.C(clk2x),.CE(wr_saturation),.D(di[ 2]),.Q(m_cb[2]));
FDE_1 i_m_cb3 (.C(clk2x),.CE(wr_saturation),.D(di[ 3]),.Q(m_cb[3]));
FDE_1 i_m_cb4 (.C(clk2x),.CE(wr_saturation),.D(di[ 4]),.Q(m_cb[4]));
FDE_1 i_m_cb5 (.C(clk2x),.CE(wr_saturation),.D(di[ 5]),.Q(m_cb[5]));
FDE_1 i_m_cb6 (.C(clk2x),.CE(wr_saturation),.D(di[ 6]),.Q(m_cb[6]));
FDE_1 i_m_cb7 (.C(clk2x),.CE(wr_saturation),.D(di[ 7]),.Q(m_cb[7]));
FDE_1 i_m_cb8 (.C(clk2x),.CE(wr_saturation),.D(di[ 8]),.Q(m_cb[8]));
FDE_1 i_m_cb9 (.C(clk2x),.CE(wr_saturation),.D(di[ 9]),.Q(m_cb[9]));
FDE_1 i_m_cr0 (.C(clk2x),.CE(wr_saturation), .D(di[12]),.Q(m_cr[0]));
FDE_1 i_m_cr1 (.C(clk2x),.CE(wr_saturation), .D(di[13]),.Q(m_cr[1]));
FDE_1 i_m_cr2 (.C(clk2x),.CE(wr_saturation), .D(di[14]),.Q(m_cr[2]));
FDE_1 i_m_cr3 (.C(clk2x),.CE(wr_saturation), .D(di[15]),.Q(m_cr[3]));
FDE_1 i_m_cr4 (.C(clk2x),.CE(wr_saturation_d),.D(di[ 0]),.Q(m_cr[4]));
FDE_1 i_m_cr5 (.C(clk2x),.CE(wr_saturation_d),.D(di[ 1]),.Q(m_cr[5]));
FDE_1 i_m_cr6 (.C(clk2x),.CE(wr_saturation_d),.D(di[ 2]),.Q(m_cr[6]));
FDE_1 i_m_cr7 (.C(clk2x),.CE(wr_saturation_d),.D(di[ 3]),.Q(m_cr[7]));
FDE_1 i_m_cr8 (.C(clk2x),.CE(wr_saturation_d),.D(di[ 4]),.Q(m_cr[8]));
FDE_1 i_m_cr9 (.C(clk2x),.CE(wr_saturation_d),.D(di[ 5]),.Q(m_cr[9]));
//synthesis translate_off
defparam i_m_cb0.INIT = 1'b0; // 'h90
defparam i_m_cb1.INIT = 1'b0;
defparam i_m_cb2.INIT = 1'b0;
defparam i_m_cb3.INIT = 1'b0;
defparam i_m_cb4.INIT = 1'b1;
defparam i_m_cb5.INIT = 1'b0;
defparam i_m_cb6.INIT = 1'b0;
defparam i_m_cb7.INIT = 1'b1;
defparam i_m_cb8.INIT = 1'b0;
defparam i_m_cb9.INIT = 1'b0;
defparam i_m_cr0.INIT = 1'b0; //'hb6
defparam i_m_cr1.INIT = 1'b1;
defparam i_m_cr2.INIT = 1'b1;
defparam i_m_cr3.INIT = 1'b0;
defparam i_m_cr4.INIT = 1'b1;
defparam i_m_cr5.INIT = 1'b1;
defparam i_m_cr6.INIT = 1'b0;
defparam i_m_cr7.INIT = 1'b1;
defparam i_m_cr8.INIT = 1'b0;
defparam i_m_cr9.INIT = 1'b0;
//synthesis translate_on
//synthesis attribute INIT of i_m_cb0 is "0"
//synthesis attribute INIT of i_m_cb1 is "0"
//synthesis attribute INIT of i_m_cb2 is "0"
//synthesis attribute INIT of i_m_cb3 is "0"
//synthesis attribute INIT of i_m_cb4 is "1"
//synthesis attribute INIT of i_m_cb5 is "0"
//synthesis attribute INIT of i_m_cb6 is "0"
//synthesis attribute INIT of i_m_cb7 is "1"
//synthesis attribute INIT of i_m_cb8 is "0"
//synthesis attribute INIT of i_m_cb9 is "0"
//synthesis attribute INIT of i_m_cr0 is "0"
//synthesis attribute INIT of i_m_cr1 is "1"
//synthesis attribute INIT of i_m_cr2 is "1"
//synthesis attribute INIT of i_m_cr3 is "0"
//synthesis attribute INIT of i_m_cr4 is "1"
//synthesis attribute INIT of i_m_cr5 is "1"
//synthesis attribute INIT of i_m_cr6 is "0"
//synthesis attribute INIT of i_m_cr7 is "1"
//synthesis attribute INIT of i_m_cr8 is "0"
//synthesis attribute INIT of i_m_cr9 is "0"
//always @ (negedge clk2x) wr_quantizer_mode_d <= wr_quantizer_mode;
FDE_1 i_coring_num0 (.C(clk2x),.CE(wr_quantizer_mode),.D(di[ 0]),.Q(coring_num[0]));
FDE_1 i_coring_num1 (.C(clk2x),.CE(wr_quantizer_mode),.D(di[ 1]),.Q(coring_num[1]));
FDE_1 i_coring_num2 (.C(clk2x),.CE(wr_quantizer_mode),.D(di[ 2]),.Q(coring_num[2]));
endmodule
// ----------------- submodules ---------------------
// [16] ==1 - set focus mode
// [15:14] 0 - none
// 1 - replace
// 2 - combine for all image
// 3 - combine in window only
// [13]==1 - enable color modes
// [12:9]== 0 - color, 4:2:0
// 1 - monochrome, 6/4 blocks (as 4:2:0)
// 2 - jp4, 6 blocks, original
// 3 - jp4, 6 blocks, dc -improved
// 4 - mono, 4 blocks (but still not actual monochrome JPEG as the blocks are scanned in 2x2 macroblocks)
// 5 - jp4, 4 blocks, dc-improved
// 6 - jp4, differential
// 7 - 15 - reserved
// [8:7] == 0,1 - NOP, 2 - disable, 3 - enable subtracting of average value (DC component), bypassing DCT
// [6] == 1 - enable quantization bank select, 0 - disregard bits [5:3]
// [5:3] = quantization page number (0..7)
// [2]== 1 - enable on/off control:
// [1:0]== 0 - reset compressor, stop immediately
// 1 - enable compressor, disable repetitive mode
// 2 - enable compressor, compress single frame
// 3 - enable compressor, enable repetitive mode
module compr_ifc (clk, // compressor input clock (1/2 of sclk)
// cwr, // CPU write - global clock
sclk, // system clock (120MHz)
cwe, // we to compressor from CPU (sync to negedge sclk)
rs, // 0 - bit modes,
// 1 - write ntiles;
di, // [15:0] data from CPU (sync to negedge sclk)
cr_w, // data written to cr (1 cycle long) - just to reset legacy IRQ
ntiles,//[17:0] - number of tiles in a frame to process
cmprs_en, // enable compressor
cmprs_start, // single cycle when single or constant compression is turned on
cmprs_repeat,// high in repetitive mode
cmprs_qpage, // [2:0] - quantizator page number (0..7)
cmprs_dcsub, // subtract dc level before DCT, restore later
cmprs_mode, // [3:0] - compressor mode
cmprs_shift, // tile shift from top left corner
cmprs_fmode, //[1:0] - focus mode
bayer_shift, // additional shift to bayer mosaic
is_compressing, // high from start of compressing till EOT (sync to posedge clk)
abort_compress,
force_flush); // abort compress - generate flush pulse, force end of image over DMA, update counter
// single-cycle @ negedge sclk
// force_eot); // sync to posedge clk - simulates eot to abort compression
input clk,
sclk,
cwe;
input rs;
input [15:0] di;
output cr_w;
output [17:0] ntiles;
output cmprs_en; // enable compressor
output cmprs_start; // single cycle when single or constant compression is turned on
output cmprs_repeat;// high in repetitive mode
output [ 2:0] cmprs_qpage; // [2:0] - quantizator page number (0..7)
output cmprs_dcsub; // subtract dc level before DCT, restore later
output [ 3:0] cmprs_mode; // [3:0] - compressor mode
output [ 2:0] cmprs_shift; // tile shift from top left corner
output [ 1:0] cmprs_fmode; // [1:0] - focus mode
output [ 1:0] bayer_shift; // additional shift to bayer mosaic
input is_compressing; // high from start of compressing till EOT (sync to posedge clk)
input abort_compress;
output force_flush; // abort compress - generate flush pulse, force end of image over DMA, update counter
// output force_eot; // sync to posedge clk - simulates eot to abort compression
reg cmprs_en; // enable compressor
wire cmprs_start; // single cycle when single or constant compression is turned on
reg cmprs_repeat;// high in repetitive mode
reg [ 2:0] cmprs_qpage; // [2:0] - quantizator page number (0..7)
reg cmprs_dcsub; // subtract dc level before DCT, restore later
reg [ 3:0] cmprs_mode; // [3:0] - compressor mode
reg [ 2:0] cmprs_shift; // tile shift from top left corner
reg [ 1:0] cmprs_fmode; // [1:0] - focus mode
reg [ 1:0] bayer_shift; // additional shift to bayer mosaic
wire [ 1:0] cmprs_start_c;
wire cmprs_en_s; // enable compressor
wire cmprs_start_s; // single cycle when single or constant compression is turned on
wire cmprs_repeat_s;// high in repetitive mode
wire [ 2:0] cmprs_qpage_s; // [2:0] - quantizator page number (0..7)
wire cmprs_dcsub_s; // subtract dc level before DCT, restore later
wire [ 3:0] cmprs_mode_s; // [3:0] - compressor mode
wire [ 2:0] cmprs_shift_s; // tile shift from top left corner
wire [ 1:0] cmprs_fmode_s; // [1:0] - focus mode
wire [ 1:0] bayer_shift_s; // additional shift to bayer mosaic
reg [23:0] cr;
reg [17:0] ntiles;
reg [15:0] ntiles0;
reg [17:0] ntiles1;
reg [17:0] ntiles1_prev;
wire [23:0] cri;
wire [1:0] rcs;
wire cr_w;
wire [1:0] cr_wi;
assign rcs[1:0]={cwe && rs, cwe && ~rs};
reg rcs0_d, rcs0_dd, rcs1_d;
reg [2:0] rcs1d;
reg [1:0] is_compressing_sclk; // sync to negedge sclk
reg [1:0] is_compressing_or_flushing_sclk=2'h0; // includes flushing
reg force_flush; // abort compress - generate flush pulse, force end of image over DMA, update counter
// wire [1:0] f_eot;
// wire force_eot;
reg cmprs_en_long; /// waits for compressor to finish gracefully with timeout enforced
reg cmprs_en_finish; /// finishing compressor flushing
reg [6:0] cmprs_en_timeout;
reg cmprs_en_s_d;
reg force_flush1; ///force flush caused by turning compressor off
always @ (negedge sclk) begin
cmprs_en_s_d <= cmprs_en_s;
cmprs_en_finish <= is_compressing_or_flushing_sclk[1] && /// when compressor is still running
((!cmprs_en_s && cmprs_en_s_d) || /// and compressor is disabled by command
(cmprs_en_finish && (cmprs_en_timeout[6:0]!= 7'h0))); /// timeout (maybe not needed?)
if (!cmprs_en_finish) cmprs_en_timeout[6:0] <= 7'h50; //80
else cmprs_en_timeout[6:0] <=cmprs_en_timeout[6:0]-1;
cmprs_en_long <= cmprs_en_s || cmprs_en_s_d || cmprs_en_finish;
force_flush1<= is_compressing_sclk[1] && /// is still compressing
!cmprs_en_s && /// first cycle when compressor enable is turned off
cmprs_en_s_d;
end
always @ (negedge sclk) begin
rcs0_d <= rcs[0];
// rcs1_d <= rcs[1];
rcs1d[2:0]<={rcs1d[1:0],rcs[1]};
rcs0_dd <= rcs0_d;
is_compressing_or_flushing_sclk[1:0] <= {is_compressing_or_flushing_sclk[0],
is_compressing | (abort_compress & is_compressing_or_flushing_sclk[1])};
is_compressing_sclk[1:0] <= {is_compressing_sclk[0], is_compressing};
// force_flush <= is_compressing_sclk[1] && rcs[1];
///add double cycle if needed
force_flush <= force_flush1 ||(rcs1d[2] && is_compressing_sclk[1] && (ntiles1_prev[17:0] != ntiles1[17:0]));
end
FDE_1 i_cri00 (.C(sclk),.CE(rcs[0]),.D(di[ 0]),.Q(cri[ 0]));
FDE_1 i_cri01 (.C(sclk),.CE(rcs[0]),.D(di[ 1]),.Q(cri[ 1]));
FDE_1 i_cri02 (.C(sclk),.CE(rcs[0]),.D(di[ 2]),.Q(cri[ 2]));
FDE_1 i_cri03 (.C(sclk),.CE(rcs[0]),.D(di[ 3]),.Q(cri[ 3]));
FDE_1 i_cri04 (.C(sclk),.CE(rcs[0]),.D(di[ 4]),.Q(cri[ 4]));
FDE_1 i_cri05 (.C(sclk),.CE(rcs[0]),.D(di[ 5]),.Q(cri[ 5]));
FDE_1 i_cri06 (.C(sclk),.CE(rcs[0]),.D(di[ 6]),.Q(cri[ 6]));
FDE_1 i_cri07 (.C(sclk),.CE(rcs[0]),.D(di[ 7]),.Q(cri[ 7]));
FDE_1 i_cri08 (.C(sclk),.CE(rcs[0]),.D(di[ 8]),.Q(cri[ 8]));
FDE_1 i_cri09 (.C(sclk),.CE(rcs[0]),.D(di[ 9]),.Q(cri[ 9]));
FDE_1 i_cri10 (.C(sclk),.CE(rcs[0]),.D(di[10]),.Q(cri[10]));
FDE_1 i_cri11 (.C(sclk),.CE(rcs[0]),.D(di[11]),.Q(cri[11]));
FDE_1 i_cri12 (.C(sclk),.CE(rcs[0]),.D(di[12]),.Q(cri[12]));
FDE_1 i_cri13 (.C(sclk),.CE(rcs[0]),.D(di[13]),.Q(cri[13]));
FDE_1 i_cri14 (.C(sclk),.CE(rcs[0]),.D(di[14]),.Q(cri[14]));
FDE_1 i_cri15 (.C(sclk),.CE(rcs[0]),.D(di[15]),.Q(cri[15]));
FDE_1 i_cri16 (.C(sclk),.CE(rcs0_d),.D(di[ 0]),.Q(cri[16]));
FDE_1 i_cri17 (.C(sclk),.CE(rcs0_d),.D(di[ 1]),.Q(cri[17]));
FDE_1 i_cri18 (.C(sclk),.CE(rcs0_d),.D(di[ 2]),.Q(cri[18]));
FDE_1 i_cri19 (.C(sclk),.CE(rcs0_d),.D(di[ 3]),.Q(cri[19]));
FDE_1 i_cri20 (.C(sclk),.CE(rcs0_d),.D(di[ 4]),.Q(cri[20]));
FDE_1 i_cri21 (.C(sclk),.CE(rcs0_d),.D(di[ 5]),.Q(cri[21]));
FDE_1 i_cri22 (.C(sclk),.CE(rcs0_d),.D(di[ 6]),.Q(cri[22]));
FDE_1 i_cri23 (.C(sclk),.CE(rcs0_d),.D(di[ 7]),.Q(cri[23]));
// just for legacy cr_w
FDCE_1 i_cr_wi0 (.C(sclk),.CE(rcs0_d),.CLR(cr_w),.D(1'b1), .Q(cr_wi[0]));
FD i_cr_wi1 (.C(clk), .D(cr_wi[0] ),.Q(cr_wi[1]));
FD i_cr_w (.C(clk), .D(cr_wi[1] & !cr_w),.Q(cr_w ));
// always @ (posedge clk) cr[23:0] <=cri[23:0]; // make it sync
always @ (negedge sclk) if (rcs[1]) ntiles0[15:0] <= di[15:0];
// always @ (negedge sclk) if (rcs1_d) ntiles1[17:0] <= {di[15:0],ntiles0[15:0]};
always @ (negedge sclk) if (rcs1d[0]) ntiles1[17:0] <= {di[15:0],ntiles0[15:0]};
always @ (negedge sclk) if (rcs1d[2]) ntiles1_prev[17:0] <= ntiles1[17:0];
// rcs1d[2:0]<={rcs1d[1:0],rcs[1]};
// command decode
FDE_1 i_cmprs_en_s (.C(sclk),.CE(rcs0_dd && cri[2]), .D(cri[1:0]!=2'h0),.Q(cmprs_en_s));
FDE_1 i_cmprs_repeat_s (.C(sclk),.CE(rcs0_dd && cri[2]), .D(cri[1:0]==2'h3),.Q(cmprs_repeat_s));
FD_1 i_cmprs_start_s (.C(sclk),.D (rcs0_dd && cri[2] && ((cri[1:0]==2'h2) || ((cri[1:0]==2'h3) && ! cmprs_repeat_s ))),.Q(cmprs_start_s));
FDE_1 i_cmprs_qpage_s0 (.C(sclk),.CE(rcs0_dd && cri[6]), .D(cri[ 3]), .Q(cmprs_qpage_s[0]));
FDE_1 i_cmprs_qpage_s1 (.C(sclk),.CE(rcs0_dd && cri[6]), .D(cri[ 4]), .Q(cmprs_qpage_s[1]));
FDE_1 i_cmprs_qpage_s2 (.C(sclk),.CE(rcs0_dd && cri[6]), .D(cri[ 5]), .Q(cmprs_qpage_s[2]));
FDE_1 i_cmprs_dcsub_s (.C(sclk),.CE(rcs0_dd && cri[8]), .D(cri[ 7]), .Q(cmprs_dcsub_s));
FDE_1 i_cmprs_mode_s0 (.C(sclk),.CE(rcs0_dd && cri[13]),.D(cri[ 9]), .Q(cmprs_mode_s[0]));
FDE_1 i_cmprs_mode_s1 (.C(sclk),.CE(rcs0_dd && cri[13]),.D(cri[10]), .Q(cmprs_mode_s[1]));
FDE_1 i_cmprs_mode_s2 (.C(sclk),.CE(rcs0_dd && cri[13]),.D(cri[11]), .Q(cmprs_mode_s[2]));
FDE_1 i_cmprs_mode_s3 (.C(sclk),.CE(rcs0_dd && cri[13]),.D(cri[12]), .Q(cmprs_mode_s[3]));
FDE_1 i_cmprs_shift_s0 (.C(sclk),.CE(rcs0_dd && cri[17]),.D(cri[14]), .Q(cmprs_shift_s[0]));
FDE_1 i_cmprs_shift_s1 (.C(sclk),.CE(rcs0_dd && cri[17]),.D(cri[15]), .Q(cmprs_shift_s[1]));
FDE_1 i_cmprs_shift_s2 (.C(sclk),.CE(rcs0_dd && cri[17]),.D(cri[16]), .Q(cmprs_shift_s[2]));
FDE_1 i_bayer_shift_s0 (.C(sclk),.CE(rcs0_dd && cri[20]),.D(cri[18]), .Q(bayer_shift_s[0]));
FDE_1 i_bayer_shift_s1 (.C(sclk),.CE(rcs0_dd && cri[20]),.D(cri[19]), .Q(bayer_shift_s[1]));
FDE_1 i_cmprs_fmode_s0 (.C(sclk),.CE(rcs0_dd && cri[23]),.D(cri[21]), .Q(cmprs_fmode_s[0]));
FDE_1 i_cmprs_fmode_s1 (.C(sclk),.CE(rcs0_dd && cri[23]),.D(cri[22]), .Q(cmprs_fmode_s[1]));
always @ (posedge clk) begin
ntiles[17:0] <=ntiles1[17:0]; // make it sync
/// cmprs_en <= cmprs_en_s;
cmprs_en <= cmprs_en_long; // extended enable, waiting for the compressor to output data length
cmprs_repeat <= cmprs_repeat_s;
cmprs_qpage[2:0] <= cmprs_qpage_s[2:0];
cmprs_dcsub <=cmprs_dcsub_s;
cmprs_mode[3:0] <=cmprs_mode_s[3:0];
cmprs_shift[2:0] <=cmprs_shift_s[2:0];
bayer_shift[1:0] <=bayer_shift_s[1:0];
cmprs_fmode[1:0] <=cmprs_fmode_s[1:0];
end
FDCE_1 i_cmprs_start_c0 (.C(sclk),.CE(cmprs_start_s), .CLR(cmprs_start),.D(1'b1), .Q(cmprs_start_c[0]));
FD i_cmprs_start_c1 (.C(clk), .D(cmprs_start_c[0] ),.Q(cmprs_start_c[1]));
FD i_cmprs_start (.C(clk), .D(cmprs_start_c[1] & !cmprs_start),.Q(cmprs_start ));
endmodule
// syncronizes dcc data with dma1 output, adds 16..31 16-bit zero words for Axis DMA
module dcc_sync (//clk,
sclk,
dcc_en, // clk rising, sync with start of the frame
finish_dcc, // sclk rising
dcc_vld, // clk rising
dcc_data, //[15:0] clk risimg
statistics_dv, //sclk
statistics_do //[15:0] sclk
);
//input clk;
input sclk, dcc_en, finish_dcc,dcc_vld;
input [15:0] dcc_data;
output statistics_dv;
output [15:0] statistics_do;
reg [15:0] statistics_do;
reg statistics_we;
reg statistics_dv;
reg dcc_run;
reg dcc_finishing;
reg skip16; // output just 16 zero words (data was multiple of 16 words)
reg [ 4:0] dcc_cntr;
always @ (posedge sclk) begin
dcc_run <= dcc_en;
statistics_we <= dcc_run && dcc_vld && !statistics_we;
statistics_do[15:0] <= statistics_we?dcc_data[15:0]:16'h0;
statistics_dv <= statistics_we || dcc_finishing;
skip16 <= finish_dcc && (statistics_dv?(dcc_cntr[3:0]==4'hf):(dcc_cntr[3:0]==4'h0) );
if (!dcc_run) dcc_cntr[3:0] <= 4'h0;
else if (statistics_dv) dcc_cntr[3:0] <= dcc_cntr[3:0]+1;
dcc_cntr[4] <= dcc_run && ((dcc_finishing && ((dcc_cntr[3:0]==4'hf)^dcc_cntr[4]) || skip16));
dcc_finishing <= dcc_run && (finish_dcc || (dcc_finishing && (dcc_cntr[4:1]!=4'hf)));
end
endmodule
/*
** -----------------------------------------------------------------------------**
** control_regs.v
**
** various control bits (what was a single control register before)
**
** Copyright (C) 2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 control_regs (sclk, // @negedge
wen, // sync to address and d[0:15]
wa, // [1:0] register select
di, // [15:0] data in
/// outputs
bayer_phase, //[1:0]
hact_regen,
reset_mcontr,
break_frames, /// Enable ending frame if no more data is available
zoran,
use_sensor_clk,
xt_pol,
arst,
aro,
encnvclk,
sensor_trigger,
mrst,
external_timestamp, // use external timestamp if available
output_timestamp, // output timestamp, not just pulse
dclkmode,
pxd14,
latehact, //[1:0]=dcr[22:21];// register hact, vact N/4 Tpclk later than data (needed for MT9P001 @ 96MHz)
pclksrc, //[1:0]=dcr[25:24]; // pclk source
hfc_sel, //[2:0]=dcr[30:28];
blockvsync, // block vsync from sensor to sequencers
compressed_frames // 8-bit selection of which frames (modulo 8) to compress. deafaults to 'hff
); // [2:0] current frame modulo 8
input sclk;
input wen;
input [ 1:0] wa;
input [15:0] di;
output [ 1:0] bayer_phase; //[1:0]
output hact_regen;
output reset_mcontr;
output break_frames; /// Enable ending frame if no more data is available
output zoran;
output use_sensor_clk;
output xt_pol;
output arst;
output aro;
output encnvclk;
output sensor_trigger;
output mrst;
output external_timestamp;
output output_timestamp;
output [7:0] compressed_frames;
output dclkmode;
output pxd14;
output [1:0] latehact; //[1:0]=dcr[22:21];// register hact, vact N/4 Tpclk later than data (needed for MT9P001 @ 96MHz)
output [1:0] pclksrc; //[1:0]=dcr[25:24]; // pclk source
output [2:0] hfc_sel; //[2:0]=dcr[30:28];
output blockvsync; // block vsync from sensor to sequencers
reg [1:0] wend; // we delayed
reg [1:0] wad; // address delayed
reg [2:0] reg_wr; // write data to registers (group 0, group1)
reg [15:0] d1;
reg [31:0] d2;
reg [7:0] compressed_frames=8'hff; // TODO change other FDE_1 to registers
always @ (negedge sclk) begin
wend[1:0] <= {wend[0], wen};
if (wen) wad[1:0] <= wa[1:0];
reg_wr[2:0] <= {wend[1] & (wad[1:0]==2'h1), wend[1] & (wad[1:0]==2'h3), wend[1] & (wad[1:0]==2'h2)};
if (wen || wend[0]) d1[15:0] <= di[15:0];
if (wend[0]) d2[15: 0] <= d1[15:0];
if (wend[1]) d2[31:16] <= d1[15:0];
end
FDE_1 i_bayer_phase_0 (.C(sclk),.CE(reg_wr[0] & d2[ 2]),.D(d2[ 0]), .Q(bayer_phase[0]));
FDE_1 i_bayer_phase_1 (.C(sclk),.CE(reg_wr[0] & d2[ 2]),.D(d2[ 1]), .Q(bayer_phase[1]));
FDE_1 i_hact_regen (.C(sclk),.CE(reg_wr[0] & d2[ 4]),.D(d2[ 3]), .Q(hact_regen));
FDE_1 i_reset_mcontr (.C(sclk),.CE(reg_wr[0] & d2[ 6]),.D(d2[ 5]), .Q(reset_mcontr));
FDE_1 i_zoran (.C(sclk),.CE(reg_wr[0] & d2[ 8]),.D(d2[ 7]), .Q(zoran));
FDE_1 i_use_sensor_clk (.C(sclk),.CE(reg_wr[0] & d2[10]),.D(d2[ 9]), .Q(use_sensor_clk));
FDE_1 i_xt_pol (.C(sclk),.CE(reg_wr[0] & d2[12]),.D(d2[11]), .Q(xt_pol));
FDE_1 i_arst (.C(sclk),.CE(reg_wr[0] & d2[14]),.D(d2[13]), .Q(arst));
FDE_1 i_aro (.C(sclk),.CE(reg_wr[0] & d2[16]),.D(d2[15]), .Q(aro));
FDE_1 i_encnvclk (.C(sclk),.CE(reg_wr[0] & d2[18]),.D(d2[17]), .Q(encnvclk));
FDE_1 i_sensor_trigger (.C(sclk),.CE(reg_wr[0] & d2[20]),.D(d2[19]), .Q(sensor_trigger));
FDE_1 i_break_frames (.C(sclk),.CE(reg_wr[0] & d2[22]),.D(d2[21]), .Q(break_frames));
FDE_1 i_mrst (.C(sclk),.CE(reg_wr[1] & d2[ 1]),.D(d2[ 0]), .Q(mrst));
FDE_1 i_external_timestamp(.C(sclk),.CE(reg_wr[1] & d2[ 3]),.D(d2[ 2]), .Q(external_timestamp));
FDE_1 i_dclkmode (.C(sclk),.CE(reg_wr[1] & d2[ 5]),.D(d2[ 4]), .Q(dclkmode));
FDE_1 i_pxd14 (.C(sclk),.CE(reg_wr[1] & d2[ 7]),.D(d2[ 6]), .Q(pxd14));
FDE_1 i_latehact_0 (.C(sclk),.CE(reg_wr[1] & d2[10]),.D(d2[ 8]), .Q(latehact[0]));
FDE_1 i_latehact_1 (.C(sclk),.CE(reg_wr[1] & d2[10]),.D(d2[ 9]), .Q(latehact[1]));
FDE_1 i_pclksrc_0 (.C(sclk),.CE(reg_wr[1] & d2[13]),.D(d2[11]), .Q(pclksrc[0]));
FDE_1 i_pclksrc_1 (.C(sclk),.CE(reg_wr[1] & d2[13]),.D(d2[12]), .Q(pclksrc[1]));
FDE_1 i_hfc_sel_0 (.C(sclk),.CE(reg_wr[1] & d2[17]),.D(d2[14]), .Q(hfc_sel[0]));
FDE_1 i_hfc_sel_1 (.C(sclk),.CE(reg_wr[1] & d2[17]),.D(d2[15]), .Q(hfc_sel[1]));
FDE_1 i_hfc_sel_2 (.C(sclk),.CE(reg_wr[1] & d2[17]),.D(d2[16]), .Q(hfc_sel[2]));
FDE_1 i_blockvsync (.C(sclk),.CE(reg_wr[1] & d2[19]),.D(d2[18]), .Q(blockvsync));
FDE_1 i_output_timestamp (.C(sclk),.CE(reg_wr[1] & d2[21]),.D(d2[20]), .Q(output_timestamp));
always @ (negedge sclk) begin
if (reg_wr[2] & d2[8]) compressed_frames[7:0] <= d2[7:0];
end
endmodule
0000 0000 1111 1111 1111 1111 2222 2222
2222 2222 3333 3333 3333 3333 4444 4444
4444 4444 5555 5555 5555 5555 6666 6666
6666 6666 7777 7777 7777 7777 8888 8888
8888 8888 9999 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 1111 1111 1111 1111 2222 2222
2222 2222 3333 3333 3333 3333 4444 4444
4444 4444 5555 5555 5555 5555 6666 6666
6666 6666 7777 7777 7777 7777 8888 8888
8888 8888 9999 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 1000 1111 1111 1111 2221 2222
2222 2222 3332 3333 3333 3333 4444 4444
4444 4444 5555 5555 5555 5555 6666 6666
6666 6666 7777 7777 7777 7777 8888 8888
8888 8888 9999 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 1000 1111 1111 1111 2221 2222
2222 2222 3332 3333 3333 3333 4444 4444
4444 4444 5555 5555 5555 5555 6666 6666
6666 6666 7777 7777 7777 7777 8888 8888
8888 8888 9999 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 1000 1111 1111 2211 2222
2222 2222 3332 3333 3333 3333 4443 4444
4444 4444 5554 5555 5555 5555 6666 6666
6666 6666 7777 7777 7777 7777 8888 8888
8888 8888 9999 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 1000 1111 1111 2211 2222
2222 2222 3332 3333 3333 3333 4443 4444
4444 4444 5554 5555 5555 5555 6666 6666
6666 6666 7777 7777 7777 7777 8888 8888
8888 8888 9999 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 1000 1111 1111
2111 2222 2222 3332 3333 3333 4433 4444
4444 4444 5554 5555 5555 5555 6665 6666
6666 6666 7776 7777 7777 7777 8888 8888
8888 8888 9999 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 1000 1111 1111
2111 2222 2222 3332 3333 3333 4433 4444
4444 4444 5554 5555 5555 5555 6665 6666
6666 6666 7776 7777 7777 7777 8888 8888
8888 8888 9999 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 0000 0000 1100
1111 1111 1111 2222 2222 3222 3333 3333
4444 4444 5444 5555 5555 5555 6665 6666
6666 6666 7776 7777 7777 7777 8887 8888
8888 8888 9998 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 0000 0000 1100
1111 1111 1111 2222 2222 3222 3333 3333
4444 4444 5444 5555 5555 5555 6665 6666
6666 6666 7776 7777 7777 7777 8887 8888
8888 8888 9998 9999 9999 9999 aaaa aaaa
aaaa aaaa bbbb bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 1110 1111 1111 1111 2221 2222 2222
3333 3333 4433 4444 5444 5555 5555 6665
6666 6666 7766 7777 7777 7777 8887 8888
8888 8888 9998 9999 9999 9999 aaa9 aaaa
aaaa aaaa bbba bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 1110 1111 1111 1111 2221 2222 2222
3333 3333 4433 4444 5444 5555 5555 6665
6666 6666 7766 7777 7777 7777 8887 8888
8888 8888 9998 9999 9999 9999 aaa9 aaaa
aaaa aaaa bbba bbbb bbbb bbbb cccc cccc
cccc cccc dddd dddd dddd dddd eeee eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 1111 1111 1111 1111 1111 1111 2222
2222 2222 3332 3333 3333 4444 4444 5555
5555 6666 7666 7777 8877 8888 9998 9999
aa99 aaaa baaa bbbb bbbb bbbb cccb cccc
cccc cccc dddc dddd dddd dddd eeed eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 1111 1111 1111 1111 1111 1111 2222
2222 2222 3332 3333 3333 4444 4444 5555
5555 6666 7666 7777 8877 8888 9998 9999
aa99 aaaa baaa bbbb bbbb bbbb cccb cccc
cccc cccc dddc dddd dddd dddd eeed eeee
eeee eeee ffff ffff ffff ffff ffff ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
1100 1111 1111 1111 1111 2111 2222 3222
3333 5444 6655 9877 cba9 feed ffff ffff
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
1100 1111 1111 1111 1111 2111 2222 3222
3333 5444 6655 9877 cba9 feed ffff ffff
/*
** -----------------------------------------------------------------------------**
** csconvert18.v
**
** Color space converter (bayer-> YCbCr 4:2:1) for JPEG compressor
**
** Copyright (C) 2002-2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
/*
09/07/2002 Andrey Filippov
Compared to spreadsheet simulation. Y - matches, CbCr in ~25% give result one less than spreadsheet simulation.
It is always odd and s.s. gives next even
TODO: optimize sequencing counters and possibly add some extra bits - as to calculate int((a+b+c+d)/4)
instead of int((int((a+b)/2)+int((c+d)/2))/2)
Color space converter processes one MCU at a time. It receives 16x16 8-bit bayer pixels (now it is always in (GR/BG)
sequence). With some latency it will produce 16x16x8 bit Y data (could be some artifacts on the borders) in scan-line
sequence and clock rate and Cb and Cr at the same time at half rate, so 4:2:0 will be generated at the same
time.
update: now it processes overlapping tiles (18x18) to avoid problems on the MCU boarders
Y= 0.299*R+0.587*G+0.114*B
Cb=-0.168*R-0.3313*G+0.5*B = 0.564*(B-Y)+128
Cr=0.5*R-0.4187*G-0.0813*B = 0.713*(R-Y)+128
For Bayer array (GR/BG)(bayer_phase[1:0]==0), and pixels P[Y,X]:
R[0,0]=0.5* (P[0,-1]+P[0,1])
R[0,1]= P[0,1]
R[1,0]=0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
R[1,1]=0.5 *(P[0,1] +P[2,1])
G[0,0]= P[0,0]
G[0,1]=0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])
G[1,0]=0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])
G[1,1]= P[1,1]
B[0,0]=0.5* (P[-1,0]+P[1,0])
B[0,1]=0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
B[1,0]= P[1,0]
B[1,1]=0.5* (P[1,0]+P[1,2])
Y[0,0]=0.299*0.5*(P[0,-1]+P[0,1]) + 0.587*P[0,0] + 0.114*0.5* (P[-1,0]+P[1,0])
Y[0,1]=0.299*P[0,1]+0.587*0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])+0.114*0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
Y[1,0]=0.299*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])+0.587*0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])+0.114*P[1,0]
Y[1,1]=0.299*0.5 *(P[0,1] +P[2,1])+0.587*P[1,1]+0.114*0.5* (P[1,0]+P[1,2])
Y[0,0]=(0x96*P[0,0]+ 0x4d*((P[0,-1]+P[0,1])/2) + 0x1d*((P[-1,0]+P[1,0])/2))>>8
Y[0,1]=(0x4d*P[0,1]+ 0x96*((P[-1,1]+P[0,0]+P[0,2]+P[1,1])/4)+ 0x1d*((P[-1,0]+P[-1,2]+P[1,0]+P[1,2])/4))>>8
Y[1,0]=(0x1d*P[1,0]+ 0x96*((P[0,0]+P[1,-1]+P[1,1]+P[2,0])/4)+ 0x4d*((P[0,-1]+P[0,1]+P[2,-1]+P[2,1])/4))>>8
Y[1,1]=(0x96*P[1,1]+ 0x1d*((P[1,0]+P[1,2])/2) + 0x4d*((P[0,1] +P[2,1])/2)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[0,1]+0.587*(0.5*P[0,0]+P[1,1])+0.114*P[1,0] )
Cb=0.564*(P[1,0]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128
Cr=0.713*(P[0,1]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128
Cb=0.564*(P[1,0]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128=
0.564*P[1,0]-0.299*0.564*P[0,1]-0.587*0.564*0.5*(P[0,0]+P[1,1])-0.114*0.564*P[1,0]))+128=
0.564*P[1,0]-0.168636*P[0,1]-0.165534*P[0,0]-0.165534*P[1,1]-0.064638*P[1,0]+128=
0.499362*P[1,0]-0.168636*P[0,1]-0.165534*P[0,0]-0.165534*P[1,1]+128=
-0.165534*P[0,0] -0.168636*P[0,1] +0.499362*P[1,0] -0.165534*P[1,1]+ 128=
(-256*0.165534*P[0,0] -256*0.168636*P[0,1] +256*0.499362*P[1,0] -256*0.165534*P[1,1])>>8+ 128=
(-42.5*P[0,0] -43*P[0,1] +128*P[1,0] -42.5*P[1,1])>>8+ 128=
(-85*((P[0,0]+P[1,1])/2) -43*P[0,1] +128*P[1,0])>>8+ 128=
(-0x55*((P[0,0]+P[1,1])/2) -2b*P[0,1] +P[1,0]<<7)>>8+ 0x80=
(-0x55*((P[0,0]+P[1,1])/2) -2b*P[0,1])>>8 +P[1,0]>>1 +0x80=
Cr=0.713*(P[0,1]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128=
0.713* P[0,1]- 0.713*0.299*P[0,1] - 0.713*0.587*0.5*P[0,0]- 0.713*0.587*0.5*P[1,1] -0.713*0.114*P[1,0]+128=
0.713* P[0,1]- 0.213187*P[0,1] - 0.2092655*P[0,0]- 0.2092655*P[1,1] -0.081282*P[1,0]+128=
0.499813* P[0,1] -0.2092655*P[0,0] -0.2092655*P[1,1] -0.081282*P[1,0]+128=
-0.2092655*P[0,0] +0.499813* P[0,1] -0.081282*P[1,0] -0.2092655*P[1,1] +128=
(-256*0.2092655*P[0,0] +256*0.499813* P[0,1] -256*0.081282*P[1,0] -256*0.2092655*P[1,1])>>8 +128=
(-54*P[0,0] +128* P[0,1] -21*P[1,0] -54*P[1,1])>>8 +128= // rounded up, sum=129 -> decreasing
(-53.5*P[0,0] +128* P[0,1] -21*P[1,0] -53.5*P[1,1])>>8 +128=
(-107*((P[0,0]+P[1,1])/2) +P[0,1]<<7 -21*P[1,0])>>8 +128=
(-0x6b*((P[0,0]+P[1,1])/2) +P[0,1]<<7 -0x15*P[1,0])>>8 +0x80=
(-0x6b*((P[0,0]+P[1,1])/2) -0x15*P[1,0])>>8 +P[0,1]>>1 +0x80=
*/ /*
For Bayer array (RG/GB)(bayer_phase[1:0]==1), and pixels P[Y,X]:
R[0,0]= P[0,0]
R[0,1]=0.5 *(P[0,0]+P[0,2])
R[1,0]=0.5 *(P[0,0]+P[2,0])
R[1,1]=0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
G[0,0]=0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0])
G[0,1]= P[0,1]
G[1,0]= P[1,0]
G[1,1]=0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])
B[0,0]=0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
B[0,1]=0.5* (P[-1,1]+P[1,1])
B[1,0]=0.5* (P[1,-1]+P[1,1])
B[1,1]= P[1,1]
Y[0,0]=0.299*P[0,0] + 0.587*0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0]) + 0.114*0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
Y[0,1]=0.299*0.5 *(P[0,0]+P[0,2])+0.587*P[0,1]+0.114*0.5* (P[-1,1]+P[1,1])
Y[1,0]=0.299*0.5 *(P[0,0]+P[2,0])+0.587*P[1,0]+0.114*0.5* (P[1,-1]+P[1,1])
Y[1,1]=0.299*0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])+0.587*0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])+0.114*P[1,1]
Y[0,0]=(0x4d*P[0,0]+ 0x96*((P[-1,0]+P[0,-1]+P[0,1]+P[1,0])/4) + 0x1d*((P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])/4))>>8
Y[0,1]=(0x96*P[0,1]+ 0x4d*((P[0,0]+P[0,2])/2)+ 0x1d*((P[-1,1]+P[1,1])/2))>>8
Y[1,0]=(0x96*P[1,0]+ 0x4d*((P[0,0]+P[2,0])/2)+ 0x1d*((P[1,-1]+P[1,1])/2))>>8
Y[1,1]=(0x1d*P[1,1]+ 0x96*((P[0,1]+P[1,0]+P[1,2]+P[2,1])/4) + 0x4d*((P[0,0]+P[0,2]+P[2,0]+P[2,2])/4)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[0,0]+0.587*(0.5*P[0,1]+P[1,0])+0.114*P[1,1] )
Cb=0.564*(P[1,1]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128
Cr=0.713*(P[0,0]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128
Cb=0.564*(P[1,1]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128=
(-0x55*((P[0,1]+P[1,0])/2) -2b*P[0,0] +P[1,1]<<7)>>8+ 0x80=
(-0x55*((P[0,1]+P[1,0])/2) -2b*P[0,0])>>8 +P[1,1]>>1 +0x80=
Cr=0.713*(P[0,0]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128=
(-0x6b*((P[0,1]+P[1,0])/2) +P[0,0]<<7 -0x15*P[1,1])>>8 +0x80=
(-0x6b*((P[0,1]+P[1,0])/2) -0x15*P[1,1])>>8 +P[0,0]>>1 +0x80=
----
*/ /*
For Bayer array (BG/GR)(bayer_phase[1:0]==2), and pixels P[Y,X]:
R[0,0]=0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
R[0,1]=0.5 *(P[-1,1] +P[1,1])
R[1,0]=0.5* (P[1,-1]+P[1,1])
R[1,1]= P[1,1]
G[0,0]=0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0])
G[0,1]= P[0,1]
G[1,0]= P[1,0]
G[1,1]=0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])
B[0,0]= P[0,0]
B[0,1]=0.5* (P[0,0]+P[0,2])
B[1,0]=0.5* (P[0,0]+P[2,0])
B[1,1]=0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
Y[0,0]=0.299*0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1]) + 0.587*0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0]) + 0.114* P[0,0]
Y[0,1]=0.299*0.5 *(P[-1,1] +P[1,1])+0.587*P[0,1]+0.114*0.5* (P[0,0]+P[0,2])
Y[1,0]=0.299*0.5* (P[1,-1]+P[1,1])+0.587*P[1,0]+0.114*0.5* (P[0,0]+P[2,0])
Y[1,1]=0.299*P[1,1]+0.587*0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])+0.114*0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
Y[0,0]=(0x1d*P[0,0]+ 0x96*((P[-1,0]+P[0,-1]+P[0,1]+P[1,0])/4)+ 0x4d*((P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])/4))>>8
Y[0,1]=(0x96*P[0,1]+ 0x4d*((P[-1,1] +P[1,1])/2)+ 0x1d*((P[0,0]+P[0,2])/2))>>8
Y[1,0]=(0x96*P[1,0]+ 0x4d*((P[1,-1]+P[1,1])/2)+ 0x1d*((P[0,0]+P[2,0])/2))>>8
Y[1,1]=(0x4d*P[1,1]+ 0x96*((P[0,1]+P[1,0]+P[1,2]+P[2,1])/4) + 0x1d*((P[0,0]+P[0,2]+P[2,0]+P[2,2])/4)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[1,1]+0.587*(0.5*P[1,0]+P[0,1])+0.114*P[0,0] )
Cb=0.564*(P[0,0]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128
Cr=0.713*(P[1,1]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128
Cb=0.564*(P[0,0]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128=
(-0x55*((P[1,0]+P[0,1])/2) -2b*P[1,1] +P[0,0]<<7)>>8+ 0x80=
(-0x55*((P[1,0]+P[0,1])/2) -2b*P[1,1])>>8 +P[0,0]>>1 +0x80=
Cr=0.713*(P[1,1]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128=
(-0x6b*((P[1,0]+P[0,1])/2) +P[1,1]<<7 -0x15*P[0,0])>>8 +0x80=
(-0x6b*((P[1,0]+P[0,1])/2) -0x15*P[0,0])>>8 +P[1,1]>>1 +0x80=
----
*/ /*
For Bayer array (GB/RG)(bayer_phase[1:0]==3), and pixels P[Y,X]:
R[0,0]=0.5 *(P[-1,0]+P[1,0])
R[0,1]=0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
R[1,0]= P[1,0]
R[1,1]=0.5 *(P[1,0]+P[1,2])
G[0,0]= P[0,0]
G[0,1]=0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])
G[1,0]=0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])
G[1,1]= P[1,1]
B[0,0]=0.5* (P[0,-1]+P[0,1])
B[0,1]= P[0,1]
B[1,0]=0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
B[1,1]=0.5* (P[0,1]+P[2,1])
Y[0,0]=0.299*0.5 *(P[-1,0]+P[1,0]) + 0.587*P[0,0] + 0.114*0.5* (P[0,-1]+P[0,1])
Y[0,1]=0.299*0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])+0.587*0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])+0.114*P[0,1]
Y[1,0]=0.299*P[1,0]+0.587*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])+0.114*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
Y[1,1]=0.299*0.5 *(P[1,0]+P[1,2])+0.587*P[1,1]+0.114*0.5* (P[0,1]+P[2,1])
Y[0,0]=(0x96*P[0,0]+ 0x4d*((P[-1,0]+P[1,0])/2) + 0x1d*((P[0,-1]+P[0,1])/2))>>8
Y[0,1]=(0x1d*P[0,1]+ 0x96*((P[-1,1]+P[0,0]+P[0,2]+P[1,1])/4)+ 0x4d*((P[-1,0]+P[-1,2]+P[1,0]+P[1,2])/4))>>8
Y[1,0]=(0x4d*P[1,0]+ 0x96*((P[0,0]+P[1,-1]+P[1,1]+P[2,0])/4)+ 0x1d*((P[0,-1]+P[0,1]+P[2,-1]+P[2,1])/4))>>8
Y[1,1]=(0x96*P[1,1]+ 0x4d*((P[1,0]+P[1,2])/2 + 0x1d*((P[0,1] +P[2,1])/2)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[1,0]+0.587*(0.5*P[1,1]+P[0,0])+0.114*P[0,1] )
Cb=0.564*(P[0,1]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128
Cr=0.713*(P[1,0]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128
Cb=0.564*(P[0,1]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128=
(-0x55*((P[1,1]+P[0,0])/2) -2b*P[1,0] +P[0,1]<<7)>>8+ 0x80=
(-0x55*((P[1,1]+P[0,0])/2) -2b*P[1,0])>>8 +P[0,1]>>1 +0x80=
Cr=0.713*(P[1,0]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128=
(-0x6b*((P[1,1]+P[0,0])/2) +P[1,0]<<7 -0x15*P[0,1])>>8 +0x80=
(-0x6b*((P[1,1]+P[0,0])/2) -0x15*P[0,1])>>8 +P[1,0]>>1 +0x80=
----
*/
/* 02/24/2003 - modified to include bypass for monochrome mode*/
/* 06/29/2004 - added counting of pixels with value of 0 and 255 (limited to 255 to use just 8 bits) */
//05.07.2008 - latency included here
module csconvert18(RST,
CLK,
mono,
limit_diff, // 1 - limit color outputs to -128/+127 range, 0 - let them be limited downstream
m_cb, // [9:0] scale for CB - default 0.564 (10'h90)
m_cr, // [9:0] scale for CB - default 0.713 (10'hb6)
din,
pre_first_in,
// strt,
signed_y, // - now signed char, -128(black) to +127 (white)
// q, // shifted by 'h80, so q=0 - is -128, q='h80 is 0, q='hff is +127
q, // new, q is just signed char
yaddr,
ywe,
caddr,
cwe,
pre_first_out,
bayer_phase,
n000,
n255);
input RST; // global reset
input CLK; // clock
input mono; // 1 - monochrome mode
input limit_diff; // 1 - limit color outputs to -128/+127 range, 0 - let them be limited downstream
input [ 9:0] m_cb; // [9:0] scale for CB - default 0.564 (10'h90)
input [ 9:0] m_cr; // [9:0] scale for CB - default 0.713 (10'hb6)
input [ 7:0] din; // input bayer data in scanline sequence, GR/BG sequence
// input strt; // marks the first input pixel - chaged to first in 3-rd row
input pre_first_in; // marks the first input pixel
output [7:0] signed_y; // output Y (16x16) in scanline sequence. Valid if ys active
// output [7:0] q; // output CbCr (8x8) each. Valid during cbs and crs
output [8:0] q; // output CbCr (8x8) each. Valid during cbs and crs
output [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
output ywe; // wrire enable of Y data
output [6:0] caddr; // address for the external buffer memory 2x8x8x8bit Cb+Cr data (MSB=0 - Cb, 1 - Cr)
output cwe; // write enable for CbCr data
output pre_first_out;
input [1:0] bayer_phase;
output [7:0] n000;
output [7:0] n255;
// synthesis attribute shreg_extract of csconvert18 is yes;
wire [7:0] din;
wire ystrt,nxtline;
wire [9:0] m_cb;
wire [9:0] m_cr;
reg [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
reg ywe; // wrire enable of Y data
reg [6:0] caddr; // address for the external buffer memory 2x8x8x8bit Cb+Cr data (MSB=0 - Cb, 1 - Cr)
reg cwe; // write enable for CbCr data
assign pre_first_out=ystrt;
reg odd_pix; // odd pixel (assumes even number of pixels in a line
reg odd_line; // odd line
reg pix_green;// (was "odd_pix==odd_line", now modified with bayer_phase[1:0]: bayer_phase[1]^bayer_phase[0]^(odd_pix==odd_line)
reg y_eq_0, y_eq_255;
reg [7:0] n000;
reg [7:0] n255;
wire [1:0] strt_dly;
wire strt;
reg [7:0] signed_y;
SRL16 i_strt_dly0 (.Q(strt_dly[0]), .D(pre_first_in), .CLK(CLK), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b1)); // dly=15+1
SRL16 i_strt_dly1 (.Q(strt_dly[1]), .D(strt_dly[0]), .CLK(CLK), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b1)); // dly=15+1
SRL16 i_strt (.Q(strt), .D(strt_dly[1]), .CLK(CLK), .A0(1'b0), .A1(1'b0), .A2(1'b1), .A3(1'b0)); // dly=4+1
SRL16 i_ystrt (.Q(ystrt), .D(strt), .CLK(CLK), .A0(1'b1), .A1(1'b0), .A2(1'b1), .A3(1'b0)); // dly=5+1
SRL16 i_nxtline(.Q(nxtline),.D(!RST && ywe && (yaddr[3:0]==4'hf) && (yaddr[7:4]!=4'hf)), .CLK(CLK), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0)); // dly=1+1
always @ (posedge CLK) begin
ywe <= !RST && (ystrt || nxtline || (ywe && (yaddr[3:0]!=4'hf)));
yaddr[7:4] <= (RST || strt)? 4'h0: (nxtline?(yaddr[7:4]+1):yaddr[7:4]);
yaddr[3:0] <= ywe? (yaddr[3:0]+1):4'h0;
odd_pix <= RST || strt || ~odd_pix;
if (RST || strt) odd_line <= 1'b0;
else if (yaddr[3:0]==4'hd) odd_line <= ~odd_line;
if (RST || strt) pix_green <=bayer_phase[1]^bayer_phase[0];
else pix_green <=~(yaddr[3:0]==4'hd)^pix_green;
end
// First block generates 2 8-bit values (latency=3)- pixel (p2) and average value of previous and next pixel in the same
// row (pa). For the first pixel that "average" equals to next pixel, for the last - previous
reg [7:0] p0;
reg [7:0] p1;
reg [7:0] pd0;
reg [7:0] pa0;
wire [8:0] ppa;
always @ (posedge CLK) p0 <= din[7:0];
always @ (posedge CLK) p1 <= p0[7:0];
// always @ (posedge CLK) pd0 <= p1[7:0];
always @ (posedge RST or posedge CLK) if (RST) pd0 <= 8'b0; else pd0 <= p1[7:0]; // generates more effective than with 2-bit SRs (line above)
assign ppa[8:0]={1'b0,pd0}+{1'b0,p0};
always @ (posedge CLK) pa0 <=ppa[8:1]; //loosing 1 bit here!
// next - 2 pairs of 8 bit wide 16-bit long serial-in, serial out shift registers. Verify implementation - Should use 32 LUTs
// update 06/10/2004 - make an output pd_c[7:0] 2 cycles after pd_1[7:0] for color processing without additional resources
reg [17:0] pd_10,pd_11,pd_12,pd_13,pd_14,pd_15,pd_16,pd_17;
// reg [17:0] pd_20,pd_21,pd_22,pd_23,pd_24,pd_25,pd_26,pd_27;
reg [7:0] pd1_dly;
reg [7:0] pdc;
reg [15:0] pd_20,pd_21,pd_22,pd_23,pd_24,pd_25,pd_26,pd_27;
reg [17:0] pa_10,pa_11,pa_12,pa_13,pa_14,pa_15,pa_16,pa_17;
reg [17:0] pa_20,pa_21,pa_22,pa_23,pa_24,pa_25,pa_26,pa_27;
wire [7:0] pd1;
wire [7:0] pd2;
wire [7:0] pa1;
wire [7:0] pa2;
assign pd1={pd_17[17],pd_16[17],pd_15[17],pd_14[17],pd_13[17],pd_12[17],pd_11[17],pd_10[17]};
assign pd2={pd_27[15],pd_26[15],pd_25[15],pd_24[15],pd_23[15],pd_22[15],pd_21[15],pd_20[15]};
assign pa1={pa_17[17],pa_16[17],pa_15[17],pa_14[17],pa_13[17],pa_12[17],pa_11[17],pa_10[17]};
assign pa2={pa_27[17],pa_26[17],pa_25[17],pa_24[17],pa_23[17],pa_22[17],pa_21[17],pa_20[17]};
always @ (posedge CLK) pd_10 <= {pd_10[16:0],pd0[0]};
always @ (posedge CLK) pd_11 <= {pd_11[16:0],pd0[1]};
always @ (posedge CLK) pd_12 <= {pd_12[16:0],pd0[2]};
always @ (posedge CLK) pd_13 <= {pd_13[16:0],pd0[3]};
always @ (posedge CLK) pd_14 <= {pd_14[16:0],pd0[4]};
always @ (posedge CLK) pd_15 <= {pd_15[16:0],pd0[5]};
always @ (posedge CLK) pd_16 <= {pd_16[16:0],pd0[6]};
always @ (posedge CLK) pd_17 <= {pd_17[16:0],pd0[7]};
always @ (posedge CLK) pd1_dly[7:0] <= pd1[7:0];
always @ (posedge CLK) pdc[7:0] <= pd1_dly[7:0];
always @ (posedge CLK) pd_20 <= {pd_20[14:0],pdc[0]};
always @ (posedge CLK) pd_21 <= {pd_21[14:0],pdc[1]};
always @ (posedge CLK) pd_22 <= {pd_22[14:0],pdc[2]};
always @ (posedge CLK) pd_23 <= {pd_23[14:0],pdc[3]};
always @ (posedge CLK) pd_24 <= {pd_24[14:0],pdc[4]};
always @ (posedge CLK) pd_25 <= {pd_25[14:0],pdc[5]};
always @ (posedge CLK) pd_26 <= {pd_26[14:0],pdc[6]};
always @ (posedge CLK) pd_27 <= {pd_27[14:0],pdc[7]};
always @ (posedge CLK) pa_10 <= {pa_10[16:0],pa0[0]};
always @ (posedge CLK) pa_11 <= {pa_11[16:0],pa0[1]};
always @ (posedge CLK) pa_12 <= {pa_12[16:0],pa0[2]};
always @ (posedge CLK) pa_13 <= {pa_13[16:0],pa0[3]};
always @ (posedge CLK) pa_14 <= {pa_14[16:0],pa0[4]};
always @ (posedge CLK) pa_15 <= {pa_15[16:0],pa0[5]};
always @ (posedge CLK) pa_16 <= {pa_16[16:0],pa0[6]};
always @ (posedge CLK) pa_17 <= {pa_17[16:0],pa0[7]};
always @ (posedge CLK) pa_20 <= {pa_20[16:0],pa_10[17]};
always @ (posedge CLK) pa_21 <= {pa_21[16:0],pa_11[17]};
always @ (posedge CLK) pa_22 <= {pa_22[16:0],pa_12[17]};
always @ (posedge CLK) pa_23 <= {pa_23[16:0],pa_13[17]};
always @ (posedge CLK) pa_24 <= {pa_24[16:0],pa_14[17]};
always @ (posedge CLK) pa_25 <= {pa_25[16:0],pa_15[17]};
always @ (posedge CLK) pa_26 <= {pa_26[16:0],pa_16[17]};
always @ (posedge CLK) pa_27 <= {pa_27[16:0],pa_17[17]};
wire [7:0] pd_prev= pd2[7:0];
wire [7:0] pd_next= pd0[7:0];
wire [7:0] pa_prev= pa2[7:0];
wire [7:0] pa_next= pa0[7:0];
// now the result Y calculation depends on the pixel position (bx,by). It consists of 3 terms, each with different coefficient.
// first term always includes pd1[7:0]
// if (bx[1]==by[1]) // 00 or 11
// second term is pa1, third - (pd0+pd2)/2
// else
// second term is (pa1 + (pd0+pd2)/2)/2, third - (pa0+pa2)/2
reg [7:0] m1;
reg [7:0] m2;
reg [7:0] m3;
wire [8:0] pd02s= {1'b0,pd_prev[7:0]}+{1'b0,pd_next[7:0]}; // will use pd02s[8:1]
wire [8:0] pa1pd02s={1'b0,pa1[7:0]}+{1'b0,pd02s[8:1]}; // will use pa1pd02s[8:1]
wire [8:0] pa02s= {1'b0,pa_prev[7:0]}+{1'b0,pa_next[7:0]}; // will use pa02s[8:1]
always @ (posedge CLK) m1 <= pd1[7:0];
// always @ (posedge CLK) m2 <= (odd_pix==odd_line)? pa1[7:0] : pa1pd02s[8:1];
// always @ (posedge CLK) m3 <= (odd_pix==odd_line)? pd02s[8:1] : pa02s[8:1];
always @ (posedge CLK) m2 <= pix_green? pa1[7:0] : pa1pd02s[8:1];
always @ (posedge CLK) m3 <= pix_green? pd02s[8:1] : pa02s[8:1];
/*
Y[0,0]=(0x96*P[0,0]+ 0x4d*((P[0,-1]+P[0,1])/2) + 0x1d*((P[-1,0]+P[1,0])/2))>>8
Y[0,1]=(0x4d*P[0,1]+ 0x96*((P[-1,1]+P[0,0]+P[0,2]+P[1,1])/4)+ 0x1d*((P[-1,0]+P[-1,2]+P[1,0]+P[1,2])/4))>>8
Y[1,0]=(0x1d*P[1,0]+ 0x96*((P[0,0]+P[1,-1]+P[1,1]+P[2,0])/4)+ 0x4d*((P[0,-1]+P[0,1]+P[2,-1]+P[2,1])/4))>>8
Y[1,1]=(0x96*P[1,1]+ 0x1d*((P[1,0]+P[1,2])/2 + 0x4d*((P[0,1] +P[2,1])/2)))>>8
+-----+--------+-------+-------+-------+-------+-------+
| | (0) | | | * | * | * * |
| | G R | * | * + * | + | * + * | + |
| | B G | | | * | * | * * |
+-----+--------+-------+-------+-------+-------+-------+
| 0 | P[0,0] | 0x96 | 0x4d | 0x1d | | |
| +--------+-------+-------+-------+-------+-------+
| G R | P[0,1] | 0x4d | | | 0x96 | 0x1d |
| +--------+-------+-------+-------+-------+-------+
| B G | P[1,0] | 0x1d | | | 0x96 | 0x4d |
| +--------+-------+-------+-------+-------+-------+
| | P[1,1] | 0x96 | 0x1d | 0x4d | | |
+-----+--------+-------+-------+-------+-------+-------+
| 1 | P[0,0] | 0x4d | | | 0x96 | 0x1d |
| +--------+-------+-------+-------+-------+-------+
| R G | P[0,1] | 0x96 | 0x4d | 0x1d | | |
| +--------+-------+-------+-------+-------+-------+
| G B | P[1,0] | 0x96 | 0x1d | 0x4d | | |
| +--------+-------+-------+-------+-------+-------+
| | P[1,1] | 0x1d | | | 0x96 | 0x4d |
+-----+--------+-------+-------+-------+-------+-------+
| 2 | P[0,0] | 0x1d | | | 0x96 | 0x4d |
| +--------+-------+-------+-------+-------+-------+
| B G | P[0,1] | 0x96 | 0x1d | 0x4d | | |
| +--------+-------+-------+-------+-------+-------+
| G R | P[1,0] | 0x96 | 0x4d | 0x1d | | |
| +--------+-------+-------+-------+-------+-------+
| | P[1,1] | 0x4d | | | 0x96 | 0x1d |
+-----+--------+-------+-------+-------+-------+-------+
| 3 | P[0,0] | 0x96 | 0x1d | 0x4d | | |
| +--------+-------+-------+-------+-------+-------+
| G B | P[0,1] | 0x1d | | | 0x96 | 0x4d |
| +--------+-------+-------+-------+-------+-------+
| R G | P[1,0] | 0x4d | | | 0x96 | 0x1d |
| +--------+-------+-------+-------+-------+-------+
| | P[1,1] | 0x96 | 0x4d | 0x1d | | |
+-----+--------+-------+-------+-------+-------+-------+
*/
reg [7:0] k1;
reg [7:0] k2;
reg [7:0] k3;
always @ (posedge CLK) case ({bayer_phase[1:0],odd_line,odd_pix})
// 0 - GR/BG
4'b0000: begin
k1<=8'h96;
k2<=8'h4d;
k3<=8'h1d;
end
4'b0001: begin
k1<=8'h4d;
k2<=8'h96;
k3<=8'h1d;
end
4'b0010: begin
k1<=8'h1d;
k2<=8'h96;
k3<=8'h4d;
end
4'b0011: begin
k1<=8'h96;
k2<=8'h1d;
k3<=8'h4d;
end
// 1 - RG/GB
4'b0100: begin
k1<=8'h4d;
k2<=8'h96;
k3<=8'h1d;
end
4'b0101: begin
k1<=8'h96;
k2<=8'h4d;
k3<=8'h1d;
end
4'b0110: begin
k1<=8'h96;
k2<=8'h1d;
k3<=8'h4d;
end
4'b0111: begin
k1<=8'h1d;
k2<=8'h96;
k3<=8'h4d;
end
// 2 - BG/GR
4'b1000: begin
k1<=8'h1d;
k2<=8'h96;
k3<=8'h4d;
end
4'b1001: begin
k1<=8'h96;
k2<=8'h1d;
k3<=8'h4d;
end
4'b1010: begin
k1<=8'h96;
k2<=8'h4d;
k3<=8'h1d;
end
4'b1011: begin
k1<=8'h4d;
k2<=8'h96;
k3<=8'h1d;
end
// 3 - GB/RG
4'b1100: begin
k1<=8'h96;
k2<=8'h1d;
k3<=8'h4d;
end
4'b1101: begin
k1<=8'h1d;
k2<=8'h96;
k3<=8'h4d;
end
4'b1110: begin
k1<=8'h4d;
k2<=8'h96;
k3<=8'h1d;
end
4'b1111: begin
k1<=8'h96;
k2<=8'h4d;
k3<=8'h1d;
end
endcase
wire [15:0] mm1=m1[7:0]*k1[7:0];
wire [15:0] mm2=m2[7:0]*k2[7:0];
wire [15:0] mm3=m3[7:0]*k3[7:0];
reg [7:0] y;
reg [7:0] y0; // bypass in monochrome mode
// wire [7:0] y0; // bypass in monochrome mode
reg [15:0] y1,y2,y3;
wire [15:0] y_sum =y1+y2+y3;
always @ (posedge CLK) y0 <= m1;
always @ (posedge CLK) y1 <= mm1;
always @ (posedge CLK) y2 <= mm2;
always @ (posedge CLK) y3 <= mm3;
// 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[7:0] <= {~pre_y[7], pre_y[6:0]};
// Try easier and hope better algorithm of color extractions that should perform better on gradients.
// It will rely on the fact that Y is already calculated, so instead of processing 4 pixels it will
// calculate Cb for "B" pixel, and Cr - for "R", subtracting calculated "Y" for that pixel.
//Cb = 0.564*(B-Y)+128
//Cr = 0.713*(R-Y)+128
// First - delay pd1[7:0] by 2 clock periods - to match "Y" output (one ahead, actually)
// It is better to implement it earlier - while calculating pd2 - anyway it had to be delayed by 18 (16+2) form pd1 - make it in 2 stages 2 +16
// pdc[7:0] - one cycle ahead of the "Y" for each pixel
// Try multiplication by constant without the register for that constant, just 2:1 mux. Still use aregister for the other operand (is it needed?)
reg [7:0] cbcrmult1;
//wire [7:0] cbcrmult2; // 1 of 2 constants - should be valid during ywe and 1 more cycle ("use_cr"
wire [9:0] cbcrmult2; // 1 of 2 constants - should be valid during ywe and 1 more cycle ("use_cr"
//wire [15:0] cbcrmulto; // output of 8x8 multiplier
wire [17:0] cbcrmulto; // output of 8x8 multiplier
// ignoring overflow we do not need extra bits
// high saturation can cause overflow, but we have very limited resources in model 313 to port back to
//reg [8:0] cbcrmultr; // 1 extra bit for precision (before subtraction)
reg [10:0] cbcrmultr; // 1 extra bit for precision (before subtraction)
//reg [8:0] cbcr; // after subraction (with extra bit preserved)
reg [10:0] cbcr; // after subraction (with extra bit preserved)
reg sel_cbcrmult1; // 0 - use pdc[7:0], 1 - use y[7:0]. Should be valid 1 cycle ahead of ywe!
reg use_cr; // in this line cr is calculated. Valid during ywe and 1 cycle after
reg sub_y; // output accumulator/subtractor. 0 - load new data, 1 - subtract. Walid 2 cycles after ywe
wire cwe0; // preliminary cwe (to be modulated by odd/even pixels)
reg cstrt; //ystrt dealyed by 1
reg cnxt; // nxtline delayed by 1
always @ (posedge CLK) begin
if (~(ywe || ystrt || nxtline)) sel_cbcrmult1 <= ~(bayer_phase[1] ^ bayer_phase[0] ^ odd_line);
else sel_cbcrmult1 <= ~sel_cbcrmult1;
sub_y <= ~sel_cbcrmult1;
cbcrmult1 <= sel_cbcrmult1?y[7:0]:pdc[7:0];
cbcrmult1 <= sel_cbcrmult1?y[7:0]:pdc[7:0];
if (~ywe) 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;
// 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
// cbcrmultr[8:0] <= cbcrmulto[15:7];
cbcrmultr[10:0] <= cbcrmulto[17:7];
// cbcr[8:0] <= sub_y? (cbcr[8:0]-cbcrmultr[8:0]+ 1'b1):cbcrmultr[8:0];
cbcr[10:0] <= sub_y? (cbcr[10:0]-cbcrmultr[10:0]+ 1'b1):cbcrmultr[10:0];
end
// assign q[7:0]= {~cbcr[8],cbcr[7:1]}; // -128, discarded extra bit (need truncating?)
//limit_diff
// Here 0 is shifted to 0x80
/*
assign q[7:0]= cbcr[10]? ((cbcr[9:8]==2'h3)?{1'b0,cbcr[7:1]}:8'h00):
((cbcr[9:8]==2'h0)?{1'b1,cbcr[7:1]}:8'hff);
*/
// new, q is signed char
assign q[8:0]= ((cbcr[10]==cbcr[9]) && (!limit_diff || (cbcr[10]==cbcr[8])))? cbcr[9:1]: {cbcr[10],limit_diff?cbcr[10]:(~cbcr[10]),{7{~cbcr[10]}}};
SRL16 i_cwe0 (.D(ywe ), .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 <= cwe0 && sub_y;
caddr[2:0]<= cwe0?(caddr[2:0]+cwe):3'b0;
// if (cstrt) caddr[6:3] <={~bayer_phase[1],3'b0};
// else if (cnxt) caddr[6:3] <={~caddr[6],caddr[5:3]+(bayer_phase[1]^caddr[6])};
if (cstrt) caddr[6] <= ~bayer_phase[1];
else if (cnxt) caddr[6] <= ~caddr[6];
if (cstrt) caddr[5:3] <=3'b0;
else if (cnxt) caddr[5:3] <=(bayer_phase[1]^caddr[6])? caddr[5:3]:(caddr[5:3]+1);
end
always @ (posedge CLK) begin
y_eq_0 <= (y0[7:0] == 8'h0);
y_eq_255 <= (y0[7:0] == 8'hff);
if (strt) n000[7:0] <= 8'h0;
else if ((n000[7:0]!=8'hff) && y_eq_0 && ywe) n000[7:0] <= n000[7:0]+1;
if (strt) n255[7:0] <= 8'h0;
else if ((n255[7:0]!=8'hff) && y_eq_255 && ywe) n255[7:0] <= n255[7:0]+1;
end
endmodule
/*
** -----------------------------------------------------------------------------**
** csconvert_mono.v
**
** Monochrome and JP4 modules inplace of color converter ones
**
** Copyright (C) 2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 csconvert_mono (en,
clk,
din,
pre_first_in,
y_out,
yaddr,
ywe,
pre_first_out);
input en;
input clk; // clock
input [7:0] din; // input data in scanline sequence
input pre_first_in; // marks the first input pixel
output [7:0] y_out; // output Y (16x16) in scanline sequence. Valid if ys active
output [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
output ywe; // wrire enable of Y data
output pre_first_out;
wire pre_first_out= pre_first_in;
// wire [7:0] y_out= din[7:0];
wire [7:0] y_out= {~din[7],din[6:0]};
reg [7:0] yaddr;
reg ywe;
always @ (posedge clk) begin
ywe <= en & (pre_first_in || (ywe && (yaddr[7:0] !=8'hff)));
if (!en || pre_first_in) yaddr[7:0] <= 8'h0;
else if (ywe) yaddr[7:0] <= yaddr[7:0] + 1;
end
endmodule
module csconvert_jp4 (en,
clk,
din,
pre_first_in,
y_out,
yaddr,
ywe,
pre_first_out);
input en;
input clk; // clock
input [7:0] din; // input data in scanline sequence
input pre_first_in; // marks the first input pixel
output [7:0] y_out; // output Y (16x16) in scanline sequence. Valid if ys active
output [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
output ywe; // wrire enable of Y data
output pre_first_out;
wire pre_first_out= pre_first_in;
// wire [7:0] y_out= din[7:0];
wire [7:0] y_out= {~din[7],din[6:0]};
reg [7:0] yaddr_cntr;
reg ywe;
wire [7:0] yaddr= {yaddr_cntr[4],yaddr_cntr[7:5],yaddr_cntr[0],yaddr_cntr[3:1]};
always @ (posedge clk) begin
ywe <= en & (pre_first_in || (ywe && (yaddr[7:0] !=8'hff)));
if (!en || pre_first_in) yaddr_cntr[7:0] <= 8'h0;
else if (ywe) yaddr_cntr[7:0] <= yaddr_cntr[7:0] + 1;
end
endmodule
module csconvert_jp4diff (en,
clk,
scale_diff, // divide differences by 2 (to fit in 8-bit range)
hdr, // second green absolute, not difference
din,
pre_first_in,
y_out,
yaddr,
ywe,
pre_first_out,
bayer_phase);
// synthesis attribute shreg_extract of csconvert_jp4diff is yes;
input en;
input clk; // clock
input scale_diff;
input hdr;
input [7:0] din; // input data in scanline sequence
input pre_first_in; // marks the first input pixel
output [8:0] y_out; // output Y (16x16) in scanline sequence. Valid if ys active
output [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
output ywe; // wrire enable of Y data
output pre_first_out;
input [1:0] bayer_phase; // selected pixel will be absolute, others - difference
reg pre_first_out;
reg [2:0] pre2_first_out;
reg [8:0] y_out;
reg [8:0] pre_y_out;
reg [7:0] yaddr_cntr;
reg [7:0] pre_yaddr_cntr;
reg [7:0] pre2_yaddr_cntr;
// reg [7:0] icntr;
reg ywe;
reg [2:0] pre_ywe;
reg [7:0] yaddr;
// reg [4:0] out_dly;
reg dly_1;
reg [14:0] dly_16;
reg dly_17;
wire start_out=bayer_phase[1]?(bayer_phase[0]?dly_17:dly_16):(bayer_phase[0]?dly_1:pre_first_in);
reg [7:0] iadr;
reg iadr_run;
reg [1:0] mux_plus_sel;
reg [2:0] mux_minus_sel;
reg hdr_bit;
reg [1:0] scale_color;
reg [1:0] is_color;
reg [7:0] mux_plus;
reg [7:0] mux_minus;
reg [7:0] dd0;
reg [7:0] dd1;
wire [7:0] dd16;
reg [7:0] dd17;
reg [14:0] ddsr0,ddsr1,ddsr2,ddsr3,ddsr4,ddsr5,ddsr6,ddsr7;
wire [8:0] scaled_pre_y_out= (scale_color[1])? +{pre_y_out[8],pre_y_out[8:1]}: pre_y_out[8:0];
assign dd16[7:0]={ddsr7[14],ddsr6[14],ddsr5[14],ddsr4[14],ddsr3[14],ddsr2[14],ddsr1[14],ddsr0[14]};
always @ (posedge clk) begin
dly_1 <= pre_first_in;
dly_17 <= dly_16[14];
dly_16[14:0] <= {dly_16[13:0],dly_1};
pre2_first_out[2:0]<= {pre2_first_out[1:0], start_out};
pre_first_out<= pre2_first_out[2];
iadr_run <= en & (start_out || (iadr_run && (iadr[7:0]!=8'hff)));
pre_ywe[2:0] <= {pre_ywe[1:0],iadr_run};
ywe <= pre_ywe[2];
if (!en || start_out) iadr[7:0] <= 8'h0;
else if (iadr_run) iadr[7:0] <= iadr[7:0] + 1;
pre2_yaddr_cntr[7:0] <= iadr[7:0];
pre_yaddr_cntr [7:0] <= pre2_yaddr_cntr[7:0];
yaddr_cntr[7:0] <= pre_yaddr_cntr[7:0];
yaddr[7:0] <= {yaddr_cntr[4],yaddr_cntr[7:5],yaddr_cntr[0],yaddr_cntr[3:1]};
case ({bayer_phase[1:0],iadr[4],iadr[0]} )
4'b0000: begin mux_plus_sel <= 2'h0; mux_minus_sel <= 3'h4; hdr_bit <=1'h0; end
4'b0001: begin mux_plus_sel <= 2'h0; mux_minus_sel <= 3'h1; hdr_bit <=1'h0; end
4'b0010: begin mux_plus_sel <= 2'h0; mux_minus_sel <= 3'h2; hdr_bit <=1'h0; end
4'b0011: begin mux_plus_sel <= 2'h0; mux_minus_sel <= 3'h3; hdr_bit <=1'h1; end
4'b0100: begin mux_plus_sel <= 2'h1; mux_minus_sel <= 3'h0; hdr_bit <=1'h0; end
4'b0101: begin mux_plus_sel <= 2'h1; mux_minus_sel <= 3'h4; hdr_bit <=1'h0; end
4'b0110: begin mux_plus_sel <= 2'h1; mux_minus_sel <= 3'h2; hdr_bit <=1'h1; end
4'b0111: begin mux_plus_sel <= 2'h1; mux_minus_sel <= 3'h3; hdr_bit <=1'h0; end
4'b1000: begin mux_plus_sel <= 2'h2; mux_minus_sel <= 3'h0; hdr_bit <=1'h0; end
4'b1001: begin mux_plus_sel <= 2'h2; mux_minus_sel <= 3'h1; hdr_bit <=1'h1; end
4'b1010: begin mux_plus_sel <= 2'h2; mux_minus_sel <= 3'h4; hdr_bit <=1'h0; end
4'b1011: begin mux_plus_sel <= 2'h2; mux_minus_sel <= 3'h3; hdr_bit <=1'h0; end
4'b1100: begin mux_plus_sel <= 2'h3; mux_minus_sel <= 3'h0; hdr_bit <=1'h1; end
4'b1101: begin mux_plus_sel <= 2'h3; mux_minus_sel <= 3'h1; hdr_bit <=1'h0; end
4'b1110: begin mux_plus_sel <= 2'h3; mux_minus_sel <= 3'h2; hdr_bit <=1'h0; end
4'b1111: begin mux_plus_sel <= 2'h3; mux_minus_sel <= 3'h4; hdr_bit <=1'h0; end
endcase
/*
if (pre_ywe[0]) case (mux_plus_sel[1:0])
2'h0: mux_plus[7:0] <= dd17[7:0];
2'h1: mux_plus[7:0] <= dd16[7:0];
2'h2: mux_plus[7:0] <= dd1 [7:0];
2'h3: mux_plus[7:0] <= dd0 [7:0];
endcase
if (pre_ywe[0]) casex ({mux_minus_sel[2] | (hdr_bit & hdr), mux_minus_sel[1:0]})
3'h0: mux_minus[7:0] <= dd17[7:0];
3'h1: mux_minus[7:0] <= dd16[7:0];
3'h2: mux_minus[7:0] <= dd1 [7:0];
3'h3: mux_minus[7:0] <= dd0 [7:0];
3'b1xx: mux_minus[7:0] <= 8'h0;
endcase
*/
if (pre_ywe[0]) case (mux_plus_sel[1:0])
2'h0: mux_plus[7:0] <= dd0 [7:0];
2'h1: mux_plus[7:0] <= dd1 [7:0];
2'h2: mux_plus[7:0] <= dd16[7:0];
2'h3: mux_plus[7:0] <= dd17[7:0];
endcase
if (pre_ywe[0]) casex ({mux_minus_sel[2] | (hdr_bit & hdr), mux_minus_sel[1:0]})
3'h0: mux_minus[7:0] <= dd0 [7:0];
3'h1: mux_minus[7:0] <= dd1 [7:0];
3'h2: mux_minus[7:0] <= dd16[7:0];
3'h3: mux_minus[7:0] <= dd17[7:0];
3'b1xx: mux_minus[7:0] <= 8'h0;
endcase
is_color[1:0] <= {is_color[0], ~(mux_minus_sel[2] | (hdr_bit & hdr))}; // 1 for color components (diffs) ([0] valid at pre_ywe[1])
scale_color[1:0] <= {scale_color[0], ~(mux_minus_sel[2] | (hdr_bit & hdr)) & scale_diff}; // 1 for color components (diffs) ([0] valid at pre_ywe[1])
if (pre_ywe[1]) pre_y_out[8:0] <= {1'b0,mux_plus[7:0]} - {1'b0,mux_minus[7:0]};
// if (scaled_pre_y_out[8]==scaled_pre_y_out[7]) y_out[7:0] <= (scaled_pre_y_out[7:0]^ 8'h80); // limit differences by 0/ff
// else y_out[7:0] <= scaled_pre_y_out[8]?8'h0:8'hff;
y_out[8:0] <= scaled_pre_y_out[8:0] - {1'h0, ~is_color[1],7'h0}; // subtract 0x80 from Y components (make them -128+127)
dd0[7:0] <= din [7:0];
dd1[7:0] <= dd0 [7:0];
ddsr0[14:0] <= {ddsr0[13:0],dd1[0]};
ddsr1[14:0] <= {ddsr1[13:0],dd1[1]};
ddsr2[14:0] <= {ddsr2[13:0],dd1[2]};
ddsr3[14:0] <= {ddsr3[13:0],dd1[3]};
ddsr4[14:0] <= {ddsr4[13:0],dd1[4]};
ddsr5[14:0] <= {ddsr5[13:0],dd1[5]};
ddsr6[14:0] <= {ddsr6[13:0],dd1[6]};
ddsr7[14:0] <= {ddsr7[13:0],dd1[7]};
dd17[7:0] <= dd16 [7:0];
end
endmodule
/****************************************************************************************
*
* File Name: ddr.v
* Version: 5.7
* Model: BUS Functional
*
* Dependencies: ddr_parameters.v
*
* Description: Micron SDRAM DDR (Double Data Rate)
*
* Limitation: - Doesn't check for 8K-cycle refresh.
* - Doesn't check power-down entry/exit
* - Doesn't check self-refresh entry/exit.
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
* - Model assume Clk and Clk# crossing at both edge
*
* Disclaimer This software code and all associated documentation, comments or other
* of Warranty: information (collectively "Software") is provided "AS IS" without
* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY
* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES
* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE
* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR
* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI,
* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT,
* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING,
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION,
* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE
* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGES. Because some jurisdictions prohibit the exclusion or
* limitation of liability for consequential or incidental damages, the
* above limitation may not apply to you.
*
* Copyright 2003 Micron Technology, Inc. All rights reserved.
*
* Rev Author Date Changes
* --- ------ ---------- ---------------------------------------
* 2.1 SPH 03/19/2002 - Second Release
* - Fix tWR and several incompatability
* between different simulators
* 3.0 TFK 02/18/2003 - Added tDSS and tDSH timing checks.
* - Added tDQSH and tDQSL timing checks.
* 3.1 CAH 05/28/2003 - update all models to release version 3.1
* (no changes to this model)
* 3.2 JMK 06/16/2003 - updated all DDR400 models to support CAS Latency 3
* 3.3 JMK 09/11/2003 - Added initialization sequence checks.
* 4.0 JMK 12/01/2003 - Grouped parameters into "ddr_parameters.v"
* - Fixed tWTR check
* 4.1 JMK 01/14/2004 - Grouped specify parameters by speed grade
* - Fixed mem_sizes parameter
* 4.2 JMK 03/19/2004 - Fixed pulse width checking on Dqs
* 4.3 JMK 04/27/2004 - Changed BL wire size in tb module
* - Changed Dq_buf size to [15:0]
* 5.0 JMK 06/16/2004 - Added read to write checking.
* - Added read with precharge truncation to write checking.
* - Added associative memory array to reduce memory consumption.
* - Added checking for required DQS edges during write.
* 5.1 JMK 08/16/2004 - Fixed checking for required DQS edges during write.
* - Fixed wdqs_valid window.
* 5.2 JMK 09/24/2004 - Read or Write without activate will be ignored.
* 5.3 JMK 10/27/2004 - Added tMRD checking during Auto Refresh and Activate.
* - Added tRFC checking during Load Mode and Precharge.
* 5.4 JMK 12/13/2004 - The model will not respond to illegal command sequences.
* 5.5 SPH 01/13/2005 - The model will issue a halt on illegal command sequences.
* JMK 02/11/2005 - Changed the display format for numbers to hex.
* 5.6 JMK 04/22/2005 - Fixed Write with auto precharge calculation.
* 5.7 JMK 08/05/2005 - Changed conditions for read with precharge truncation error.
* - Renamed parameters file with .vh extension.
****************************************************************************************/
// DO NOT CHANGE THE TIMESCALE
// MAKE SURE YOUR SIMULATOR USE "PS" RESOLUTION
`timescale 1ns / 1ps
module ddr (Dq, Dqs, Addr, Ba, Clk, Clk_n, Cke, Cs_n, Ras_n, Cas_n, We_n, Dm);
`define sg6
`include "ddr_parameters.v"
// Port Declarations
inout [DQ_BITS - 1 : 0] Dq;
inout [DQS_BITS - 1 : 0] Dqs;
input [ADDR_BITS - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Clk_n;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [DM_BITS - 1 : 0] Dm;
// Internal Wires (fixed width)
wire [15 : 0] Dq_in;
wire [1 : 0] Dqs_in;
wire [1 : 0] Dm_in;
assign Dq_in [DQ_BITS - 1 : 0] = Dq;
assign Dqs_in [DQS_BITS - 1 : 0] = Dqs;
assign Dm_in [DM_BITS - 1 : 0] = Dm;
// Data pair
reg [15 : 0] dq_rise;
reg [1 : 0] dm_rise;
reg [15 : 0] dq_fall;
reg [1 : 0] dm_fall;
reg [3 : 0] dm_pair;
reg [15 : 0] Dq_buf;
// Mode Register
reg [ADDR_BITS - 1 : 0] Mode_reg;
// Internal System Clock
reg CkeZ, Sys_clk;
// Internal Dqs initialize
reg Dqs_int;
// Dqs buffer
reg [DQS_BITS - 1 : 0] Dqs_out;
// Dq buffer
reg [DQ_BITS - 1 : 0] Dq_out;
// Read pipeline variables
reg Read_cmnd [0 : 6];
reg [1 : 0] Read_bank [0 : 6];
reg [COL_BITS - 1 : 0] Read_cols [0 : 6];
// Write pipeline variables
reg Write_cmnd [0 : 3];
reg [1 : 0] Write_bank [0 : 3];
reg [COL_BITS - 1 : 0] Write_cols [0 : 3];
// Auto precharge variables
reg Read_precharge [0 : 3];
reg Write_precharge [0 : 3];
integer Count_precharge [0 : 3];
// Manual precharge variables
reg A10_precharge [0 : 6];
reg [1 : 0] Bank_precharge [0 : 6];
reg Cmnd_precharge [0 : 6];
// Burst terminate variables
reg Cmnd_bst [0 : 6];
// Memory Banks
`ifdef FULL_MEM
reg [DQ_BITS - 1 : 0] mem_array [0 : (1<<full_mem_bits)-1];
`else
reg [DQ_BITS - 1 : 0] mem_array [0 : (1<<part_mem_bits)-1];
reg [full_mem_bits - 1 : 0] addr_array [0 : (1<<part_mem_bits)-1];
reg [part_mem_bits : 0] mem_used;
initial mem_used = 0;
`endif
// Dqs edge checking
integer i;
reg [1:0] expect_pos_dqs;
reg [1:0] expect_neg_dqs;
// Burst counter
reg [COL_BITS - 1 : 0] Burst_counter;
// Precharge variables
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3;
// Activate variables
reg Act_b0, Act_b1, Act_b2, Act_b3;
// Data IO variables
reg Data_in_enable;
reg Data_out_enable;
// Internal address mux variables
reg [1 : 0] Prev_bank;
reg [1 : 0] Bank_addr;
reg [COL_BITS - 1 : 0] Cols_addr, Cols_brst, Cols_temp;
reg [ADDR_BITS - 1 : 0] Rows_addr;
reg [ADDR_BITS - 1 : 0] B0_row_addr;
reg [ADDR_BITS - 1 : 0] B1_row_addr;
reg [ADDR_BITS - 1 : 0] B2_row_addr;
reg [ADDR_BITS - 1 : 0] B3_row_addr;
// DLL Reset variable
reg DLL_enable;
reg DLL_reset;
reg DLL_done;
integer DLL_count;
integer aref_count;
integer Prech_count;
reg power_up_done;
// Write DQS for tDSS, tDSH, tDQSH, tDQSL checks
wire wdqs_valid = Write_cmnd[2] || Write_cmnd[1] || Data_in_enable;
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Ext_mode_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & Ba[0] & ~Ba[1];
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & ~Ba[0] & ~Ba[1];
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
// Burst Length Decode
wire [3:0] burst_length = 1 << (Mode_reg[2:0]);
reg [3:0] read_precharge_truncation;
// CAS Latency Decode
wire [2:0] cas_latency_x2 = (Mode_reg[6:4] === 3'o6) ? 5 : 2*Mode_reg[6:4];
// DQS Buffer
assign Dqs = Dqs_out;
// DQ Buffer
assign Dq = Dq_out;
// Debug message
wire Debug = 1'b1;
// Timing Check
time MRD_chk;
time RFC_chk;
time RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3;
time RC_chk0, RC_chk1, RC_chk2, RC_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
time WR_chk0, WR_chk1, WR_chk2, WR_chk3;
initial begin
CkeZ = 1'b0;
Sys_clk = 1'b0;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b1111;
Dqs_int = 1'b0;
Dqs_out = {DQS_BITS{1'bz}};
Dq_out = {DQ_BITS{1'bz}};
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
DLL_enable = 1'b0;
DLL_reset = 1'b0;
DLL_done = 1'b0;
DLL_count = 0;
aref_count = 0;
Prech_count = 0;
power_up_done = 0;
MRD_chk = 0;
RFC_chk = 0;
RRD_chk = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3} = 0;
{RC_chk0, RC_chk1, RC_chk2, RC_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
{WR_chk0, WR_chk1, WR_chk2, WR_chk3} = 0;
$timeformat (-9, 3, " ns", 12);
end
// System Clock
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
// Check to make sure that we have a Deselect or NOP command on the bus when CKE is brought high
always @(Cke) begin
if (Cke === 1'b1) begin
if (!((Cs_n) || (~Cs_n & Ras_n & Cas_n & We_n))) begin
$display ("%m: at time %t MEMORY ERROR: You must have a Deselect or NOP command applied", $time);
$display ("%m: when the Clock Enable is brought High.");
end
end
end
// Check the initialization sequence
initial begin
@ (posedge Cke) begin
@ (posedge DLL_enable) begin
aref_count = 0;
@ (posedge DLL_reset) begin
@ (Prech_count) begin
if (aref_count >= 2) begin
if (Debug) $display ("%m: at time %t MEMORY: Power Up and Initialization Sequence is complete", $time);
power_up_done = 1;
end else begin
aref_count = 0;
@ (aref_count >= 2) begin
if (Debug) $display ("%m: at time %t MEMORY: Power Up and Initialization Sequence is complete", $time);
power_up_done = 1;
end
end
end
end
end
end
end
// Write Memory
task write_mem;
input [full_mem_bits - 1 : 0] addr;
input [DQ_BITS - 1 : 0] data;
reg [part_mem_bits : 0] i;
begin
`ifdef FULL_MEM
mem_array[addr] = data;
`else
begin : loop
for (i = 0; i < mem_used; i = i + 1) begin
if (addr_array[i] === addr) begin
disable loop;
end
end
end
if (i === mem_used) begin
if (i === (1<<part_mem_bits)) begin
$display ("At time %t ERROR: Memory overflow.\n Write to Address %x with Data %x will be lost.\n You must increase the part_mem_bits parameter or define FULL_MEM.", $time, addr, data);
end else begin
mem_used = mem_used + 1;
addr_array[i] = addr;
end
end
mem_array[i] = data;
`endif
end
endtask
// Read Memory
task read_mem;
input [full_mem_bits - 1 : 0] addr;
output [DQ_BITS - 1 : 0] data;
reg [part_mem_bits : 0] i;
begin
`ifdef FULL_MEM
data = mem_array[addr];
`else
begin : loop
for (i = 0; i < mem_used; i = i + 1) begin
if (addr_array[i] === addr) begin
disable loop;
end
end
end
if (i <= mem_used) begin
data = mem_array[i];
end
`endif
end
endtask
// Burst Decode
task Burst_Decode;
begin
// Advance Burst Counter
if (Burst_counter < burst_length) begin
Burst_counter = Burst_counter + 1;
end
// Burst Type
if (Mode_reg[3] === 1'b0) begin // Sequential Burst
Cols_temp = Cols_addr + 1;
end else if (Mode_reg[3] === 1'b1) begin // Interleaved Burst
Cols_temp[2] = Burst_counter[2] ^ Cols_brst[2];
Cols_temp[1] = Burst_counter[1] ^ Cols_brst[1];
Cols_temp[0] = Burst_counter[0] ^ Cols_brst[0];
end
// Burst Length
if (burst_length === 2) begin
Cols_addr [0] = Cols_temp [0];
end else if (burst_length === 4) begin
Cols_addr [1 : 0] = Cols_temp [1 : 0];
end else if (burst_length === 8) begin
Cols_addr [2 : 0] = Cols_temp [2 : 0];
end else begin
Cols_addr = Cols_temp;
end
// Data Counter
if (Burst_counter >= burst_length) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
read_precharge_truncation = 4'h0;
end
end
endtask
// Manual Precharge Pipeline
task Manual_Precharge_Pipeline;
begin
// A10 Precharge Pipeline
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = A10_precharge[4];
A10_precharge[4] = A10_precharge[5];
A10_precharge[5] = A10_precharge[6];
A10_precharge[6] = 1'b0;
// Bank Precharge Pipeline
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = Bank_precharge[4];
Bank_precharge[4] = Bank_precharge[5];
Bank_precharge[5] = Bank_precharge[6];
Bank_precharge[6] = 2'b0;
// Command Precharge Pipeline
Cmnd_precharge[0] = Cmnd_precharge[1];
Cmnd_precharge[1] = Cmnd_precharge[2];
Cmnd_precharge[2] = Cmnd_precharge[3];
Cmnd_precharge[3] = Cmnd_precharge[4];
Cmnd_precharge[4] = Cmnd_precharge[5];
Cmnd_precharge[5] = Cmnd_precharge[6];
Cmnd_precharge[6] = 1'b0;
// Terminate a Read if same bank or all banks
if (Cmnd_precharge[0] === 1'b1) begin
if (Bank_precharge[0] === Bank_addr || A10_precharge[0] === 1'b1) begin
if (Data_out_enable === 1'b1) begin
Data_out_enable = 1'b0;
read_precharge_truncation = 4'hF;
end
end
end
end
endtask
// Burst Terminate Pipeline
task Burst_Terminate_Pipeline;
begin
// Command Precharge Pipeline
Cmnd_bst[0] = Cmnd_bst[1];
Cmnd_bst[1] = Cmnd_bst[2];
Cmnd_bst[2] = Cmnd_bst[3];
Cmnd_bst[3] = Cmnd_bst[4];
Cmnd_bst[4] = Cmnd_bst[5];
Cmnd_bst[5] = Cmnd_bst[6];
Cmnd_bst[6] = 1'b0;
// Terminate a Read regardless of banks
if (Cmnd_bst[0] === 1'b1 && Data_out_enable === 1'b1) begin
Data_out_enable = 1'b0;
end
end
endtask
// Dq and Dqs Drivers
task Dq_Dqs_Drivers;
begin
// read command pipeline
Read_cmnd [0] = Read_cmnd [1];
Read_cmnd [1] = Read_cmnd [2];
Read_cmnd [2] = Read_cmnd [3];
Read_cmnd [3] = Read_cmnd [4];
Read_cmnd [4] = Read_cmnd [5];
Read_cmnd [5] = Read_cmnd [6];
Read_cmnd [6] = 1'b0;
// read bank pipeline
Read_bank [0] = Read_bank [1];
Read_bank [1] = Read_bank [2];
Read_bank [2] = Read_bank [3];
Read_bank [3] = Read_bank [4];
Read_bank [4] = Read_bank [5];
Read_bank [5] = Read_bank [6];
Read_bank [6] = 2'b0;
// read column pipeline
Read_cols [0] = Read_cols [1];
Read_cols [1] = Read_cols [2];
Read_cols [2] = Read_cols [3];
Read_cols [3] = Read_cols [4];
Read_cols [4] = Read_cols [5];
Read_cols [5] = Read_cols [6];
Read_cols [6] = 0;
// Initialize Read command
if (Read_cmnd [0] === 1'b1) begin
Data_out_enable = 1'b1;
Bank_addr = Read_bank [0];
Cols_addr = Read_cols [0];
Cols_brst = Cols_addr [2 : 0];
Burst_counter = 0;
// Row Address Mux
case (Bank_addr)
2'd0 : Rows_addr = B0_row_addr;
2'd1 : Rows_addr = B1_row_addr;
2'd2 : Rows_addr = B2_row_addr;
2'd3 : Rows_addr = B3_row_addr;
default : $display ("At time %t ERROR: Invalid Bank Address", $time);
endcase
end
// Toggle Dqs during Read command
if (Data_out_enable === 1'b1) begin
Dqs_int = 1'b0;
if (Dqs_out === {DQS_BITS{1'b0}}) begin
Dqs_out = {DQS_BITS{1'b1}};
end else if (Dqs_out === {DQS_BITS{1'b1}}) begin
Dqs_out = {DQS_BITS{1'b0}};
end else begin
Dqs_out = {DQS_BITS{1'b0}};
end
end else if (Data_out_enable === 1'b0 && Dqs_int === 1'b0) begin
Dqs_out = {DQS_BITS{1'bz}};
end
// Initialize dqs for Read command
if (Read_cmnd [2] === 1'b1) begin
if (Data_out_enable === 1'b0) begin
Dqs_int = 1'b1;
Dqs_out = {DQS_BITS{1'b0}};
end
end
// Read latch
if (Data_out_enable === 1'b1) begin
// output data
read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_out);
if (Debug) begin
$display ("At time %t READ : Bank = %x, Row = %x, Col = %x, Data = %x", $time, Bank_addr, Rows_addr, Cols_addr, Dq_out);
end
end else begin
Dq_out = {DQ_BITS{1'bz}};
end
end
endtask
// Write FIFO and DM Mask Logic
task Write_FIFO_DM_Mask_Logic;
begin
// Write command pipeline
Write_cmnd [0] = Write_cmnd [1];
Write_cmnd [1] = Write_cmnd [2];
Write_cmnd [2] = Write_cmnd [3];
Write_cmnd [3] = 1'b0;
// Write command pipeline
Write_bank [0] = Write_bank [1];
Write_bank [1] = Write_bank [2];
Write_bank [2] = Write_bank [3];
Write_bank [3] = 2'b0;
// Write column pipeline
Write_cols [0] = Write_cols [1];
Write_cols [1] = Write_cols [2];
Write_cols [2] = Write_cols [3];
Write_cols [3] = {COL_BITS{1'b0}};
// Initialize Write command
if (Write_cmnd [0] === 1'b1) begin
Data_in_enable = 1'b1;
Bank_addr = Write_bank [0];
Cols_addr = Write_cols [0];
Cols_brst = Cols_addr [2 : 0];
Burst_counter = 0;
// Row address mux
case (Bank_addr)
2'd0 : Rows_addr = B0_row_addr;
2'd1 : Rows_addr = B1_row_addr;
2'd2 : Rows_addr = B2_row_addr;
2'd3 : Rows_addr = B3_row_addr;
default : $display ("At time %t ERROR: Invalid Row Address", $time);
endcase
end
// Write data
if (Data_in_enable === 1'b1) begin
// Data Buffer
read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf);
// write negedge Dqs on posedge Sys_clk
if (Sys_clk) begin
if (!dm_fall[0]) begin
Dq_buf [ 7 : 0] = dq_fall [ 7 : 0];
end
if (!dm_fall[1]) begin
Dq_buf [15 : 8] = dq_fall [15 : 8];
end
if (~&dm_fall) begin
if (Debug) begin
$display ("At time %t WRITE: Bank = %x, Row = %x, Col = %x, Data = %x", $time, Bank_addr, Rows_addr, Cols_addr, Dq_buf[DQ_BITS-1:0]);
end
end
// write posedge Dqs on negedge Sys_clk
end else begin
if (!dm_rise[0]) begin
Dq_buf [ 7 : 0] = dq_rise [ 7 : 0];
end
if (!dm_rise[1]) begin
Dq_buf [15 : 8] = dq_rise [15 : 8];
end
if (~&dm_rise) begin
if (Debug) begin
$display ("At time %t WRITE: Bank = %x, Row = %x, Col = %x, Data = %x", $time, Bank_addr, Rows_addr, Cols_addr, Dq_buf[DQ_BITS-1:0]);
end
end
end
// Write Data
write_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf);
// tWR start and tWTR check
if (Sys_clk && &dm_pair === 1'b0) begin
case (Bank_addr)
2'd0 : WR_chk0 = $time;
2'd1 : WR_chk1 = $time;
2'd2 : WR_chk2 = $time;
2'd3 : WR_chk3 = $time;
default : $display ("At time %t ERROR: Invalid Bank Address (tWR)", $time);
endcase
// tWTR check
if (Read_enable === 1'b1) begin
$display ("At time %t ERROR: tWTR violation during Read", $time);
end
end
end
end
endtask
// Auto Precharge Calculation
task Auto_Precharge_Calculation;
begin
// Precharge counter
if (Read_precharge [0] === 1'b1 || Write_precharge [0] === 1'b1) begin
Count_precharge [0] = Count_precharge [0] + 1;
end
if (Read_precharge [1] === 1'b1 || Write_precharge [1] === 1'b1) begin
Count_precharge [1] = Count_precharge [1] + 1;
end
if (Read_precharge [2] === 1'b1 || Write_precharge [2] === 1'b1) begin
Count_precharge [2] = Count_precharge [2] + 1;
end
if (Read_precharge [3] === 1'b1 || Write_precharge [3] === 1'b1) begin
Count_precharge [3] = Count_precharge [3] + 1;
end
// Read with AutoPrecharge Calculation
// The device start internal precharge when:
// 1. Meet tRAS requirement
// 2. BL/2 cycles after command
if ((Read_precharge[0] === 1'b1) && ($time - RAS_chk0 >= tRAS)) begin
if (Count_precharge[0] >= burst_length/2) begin
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Read_precharge[0] = 1'b0;
end
end
if ((Read_precharge[1] === 1'b1) && ($time - RAS_chk1 >= tRAS)) begin
if (Count_precharge[1] >= burst_length/2) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Read_precharge[1] = 1'b0;
end
end
if ((Read_precharge[2] === 1'b1) && ($time - RAS_chk2 >= tRAS)) begin
if (Count_precharge[2] >= burst_length/2) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Read_precharge[2] = 1'b0;
end
end
if ((Read_precharge[3] === 1'b1) && ($time - RAS_chk3 >= tRAS)) begin
if (Count_precharge[3] >= burst_length/2) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Read_precharge[3] = 1'b0;
end
end
// Write with AutoPrecharge Calculation
// The device start internal precharge when:
// 1. Meet tRAS requirement
// 2. Write Latency PLUS BL/2 cycles PLUS tWR after Write command
if ((Write_precharge[0] === 1'b1) && ($time - RAS_chk0 >= tRAS)) begin
if ((Count_precharge[0] >= burst_length/2+1) && ($time - WR_chk0 >= tWR)) begin
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Write_precharge[0] = 1'b0;
end
end
if ((Write_precharge[1] === 1'b1) && ($time - RAS_chk1 >= tRAS)) begin
if ((Count_precharge[1] >= burst_length/2+1) && ($time - WR_chk1 >= tWR)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Write_precharge[1] = 1'b0;
end
end
if ((Write_precharge[2] === 1'b1) && ($time - RAS_chk2 >= tRAS)) begin
if ((Count_precharge[2] >= burst_length/2+1) && ($time - WR_chk2 >= tWR)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Write_precharge[2] = 1'b0;
end
end
if ((Write_precharge[3] === 1'b1) && ($time - RAS_chk3 >= tRAS)) begin
if ((Count_precharge[3] >= burst_length/2+1) && ($time - WR_chk3 >= tWR)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Write_precharge[3] = 1'b0;
end
end
end
endtask
// DLL Counter
task DLL_Counter;
begin
if (DLL_reset === 1'b1 && DLL_done === 1'b0) begin
DLL_count = DLL_count + 1;
if (DLL_count >= 200) begin
DLL_done = 1'b1;
end
end
end
endtask
// Control Logic
task Control_Logic;
begin
// Auto Refresh
if (Aref_enable === 1'b1) begin
// Display Debug Message
if (Debug) begin
$display ("At time %t AREF : Auto Refresh", $time);
end
// Precharge to Auto Refresh
if (($time - RP_chk0 < tRP) || ($time - RP_chk1 < tRP) ||
($time - RP_chk2 < tRP) || ($time - RP_chk3 < tRP)) begin
$display ("At time %t ERROR: tRP violation during Auto Refresh", $time);
end
// LMR/EMR to Auto Refresh
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Auto Refresh", $time);
end
// Auto Refresh to Auto Refresh
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Auto Refresh", $time);
end
// Precharge to Auto Refresh
if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin
$display ("At time %t ERROR: All banks must be Precharged before Auto Refresh", $time);
if (!no_halt) $stop (0);
end else begin
aref_count = aref_count + 1;
RFC_chk = $time;
end
end
// Extended Mode Register
if (Ext_mode_enable === 1'b1) begin
if (Debug) begin
$display ("At time %t EMR : Extended Mode Register", $time);
end
// Precharge to LMR/EMR
if (($time - RP_chk0 < tRP) || ($time - RP_chk1 < tRP) ||
($time - RP_chk2 < tRP) || ($time - RP_chk3 < tRP)) begin
$display ("At time %t ERROR: tRP violation during Extended Mode Register", $time);
end
// LMR/EMR to LMR/EMR
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Extended Mode Register", $time);
end
// Auto Refresh to LMR/EMR
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Extended Mode Register", $time);
end
// Precharge to LMR/EMR
if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin
$display ("At time %t ERROR: all banks must be Precharged before Extended Mode Register", $time);
if (!no_halt) $stop (0);
end else begin
if (Addr[0] === 1'b0) begin
DLL_enable = 1'b1;
if (Debug) begin
$display ("At time %t EMR : Enable DLL", $time);
end
end else begin
DLL_enable = 1'b0;
if (Debug) begin
$display ("At time %t EMR : Disable DLL", $time);
end
end
MRD_chk = $time;
end
end
// Load Mode Register
if (Mode_reg_enable === 1'b1) begin
if (Debug) begin
$display ("At time %t LMR : Load Mode Register", $time);
end
// Precharge to LMR/EMR
if (($time - RP_chk0 < tRP) || ($time - RP_chk1 < tRP) ||
($time - RP_chk2 < tRP) || ($time - RP_chk3 < tRP)) begin
$display ("At time %t ERROR: tRP violation during Load Mode Register", $time);
end
// LMR/EMR to LMR/EMR
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Load Mode Register", $time);
end
// Auto Refresh to LMR/EMR
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Load Mode Register", $time);
end
// Precharge to LMR/EMR
if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin
$display ("At time %t ERROR: all banks must be Precharged before Load Mode Register", $time);
end else begin
// Register Mode
Mode_reg = Addr;
// DLL Reset
if (DLL_enable === 1'b1 && Addr [8] === 1'b1) begin
DLL_reset = 1'b1;
DLL_done = 1'b0;
DLL_count = 0;
end else if (DLL_enable === 1'b1 && DLL_reset === 1'b0 && Addr [8] === 1'b0) begin
$display ("At time %t ERROR: DLL is ENABLE: DLL RESET is required.", $time);
end else if (DLL_enable === 1'b0 && Addr [8] === 1'b1) begin
$display ("At time %t ERROR: DLL is DISABLE: DLL RESET will be ignored.", $time);
end
// Burst Length
case (Addr [2 : 0])
3'b001 : $display ("At time %t LMR : Burst Length = 2", $time);
3'b010 : $display ("At time %t LMR : Burst Length = 4", $time);
3'b011 : $display ("At time %t LMR : Burst Length = 8", $time);
default : $display ("At time %t ERROR: Burst Length not supported", $time);
endcase
// CAS Latency
case (Addr [6 : 4])
3'b010 : $display ("At time %t LMR : CAS Latency = 2", $time);
3'b110 : $display ("At time %t LMR : CAS Latency = 2.5", $time);
3'b011 : $display ("At time %t LMR : CAS Latency = 3", $time);
default : $display ("At time %t ERROR: CAS Latency not supported", $time);
endcase
// Record current tMRD time
MRD_chk = $time;
end
end
// Activate Block
if (Active_enable === 1'b1) begin
if (!(power_up_done)) begin
$display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Activate command", $time);
end
// Display Debug Message
if (Debug) begin
$display ("At time %t ACT : Bank = %x, Row = %x", $time, Ba, Addr);
end
// Activate to Activate (different bank)
if ((Prev_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("At time %t ERROR: tRRD violation during Activate bank %h", $time, Ba);
end
// LMR/EMR to Activate
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Activate bank %h", $time, Ba);
end
// AutoRefresh to Activate
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Activate bank %h", $time, Ba);
end
// Precharge to Activate
if ((Ba === 2'b00 && Pc_b0 === 1'b0) || (Ba === 2'b01 && Pc_b1 === 1'b0) ||
(Ba === 2'b10 && Pc_b2 === 1'b0) || (Ba === 2'b11 && Pc_b3 === 1'b0)) begin
$display ("At time %t ERROR: Bank = %h is already activated - Command Ignored", $time, Ba);
if (!no_halt) $stop (0);
end else begin
// Activate Bank 0
if (Ba === 2'b00 && Pc_b0 === 1'b1) begin
// Activate to Activate (same bank)
if ($time - RC_chk0 < tRC) begin
$display ("At time %t ERROR: tRC violation during Activate bank %x", $time, Ba);
end
// Precharge to Activate
if ($time - RP_chk0 < tRP) begin
$display ("At time %t ERROR: tRP violation during Activate bank %x", $time, Ba);
end
// Record variables for checking violation
Act_b0 = 1'b1;
Pc_b0 = 1'b0;
B0_row_addr = Addr;
RC_chk0 = $time;
RCD_chk0 = $time;
RAS_chk0 = $time;
RAP_chk0 = $time;
end
// Activate Bank 1
if (Ba === 2'b01 && Pc_b1 === 1'b1) begin
// Activate to Activate (same bank)
if ($time - RC_chk1 < tRC) begin
$display ("At time %t ERROR: tRC violation during Activate bank %x", $time, Ba);
end
// Precharge to Activate
if ($time - RP_chk1 < tRP) begin
$display ("At time %t ERROR: tRP violation during Activate bank %x", $time, Ba);
end
// Record variables for checking violation
Act_b1 = 1'b1;
Pc_b1 = 1'b0;
B1_row_addr = Addr;
RC_chk1 = $time;
RCD_chk1 = $time;
RAS_chk1 = $time;
RAP_chk1 = $time;
end
// Activate Bank 2
if (Ba === 2'b10 && Pc_b2 === 1'b1) begin
// Activate to Activate (same bank)
if ($time - RC_chk2 < tRC) begin
$display ("At time %t ERROR: tRC violation during Activate bank %x", $time, Ba);
end
// Precharge to Activate
if ($time - RP_chk2 < tRP) begin
$display ("At time %t ERROR: tRP violation during Activate bank %x", $time, Ba);
end
// Record variables for checking violation
Act_b2 = 1'b1;
Pc_b2 = 1'b0;
B2_row_addr = Addr;
RC_chk2 = $time;
RCD_chk2 = $time;
RAS_chk2 = $time;
RAP_chk2 = $time;
end
// Activate Bank 3
if (Ba === 2'b11 && Pc_b3 === 1'b1) begin
// Activate to Activate (same bank)
if ($time - RC_chk3 < tRC) begin
$display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba);
end
// Precharge to Activate
if ($time - RP_chk3 < tRP) begin
$display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba);
end
// Record variables for checking violation
Act_b3 = 1'b1;
Pc_b3 = 1'b0;
B3_row_addr = Addr;
RC_chk3 = $time;
RCD_chk3 = $time;
RAS_chk3 = $time;
RAP_chk3 = $time;
end
// Record variable for checking violation
RRD_chk = $time;
Prev_bank = Ba;
read_precharge_truncation[Ba] = 1'b0;
end
end
// Precharge Block - consider NOP if bank already precharged or in process of precharging
if (Prech_enable === 1'b1) begin
// Display Debug Message
if (Debug) begin
$display ("At time %t PRE : Addr[10] = %b, Bank = %b", $time, Addr[10], Ba);
end
// LMR/EMR to Precharge
if ($time - MRD_chk < tMRD) begin
$display ("At time %t ERROR: tMRD violation during Precharge", $time);
end
// AutoRefresh to Precharge
if ($time - RFC_chk < tRFC) begin
$display ("At time %t ERROR: tRFC violation during Precharge", $time);
end
// Precharge bank 0
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b00)) && Act_b0 === 1'b1) begin
Act_b0 = 1'b0;
Pc_b0 = 1'b1;
RP_chk0 = $time;
// Activate to Precharge Bank
if ($time - RAS_chk0 < tRAS) begin
$display ("At time %t ERROR: tRAS violation during Precharge", $time);
end
// tWR violation check for Write
if ($time - WR_chk0 < tWR) begin
$display ("At time %t ERROR: tWR violation during Precharge", $time);
end
end
// Precharge bank 1
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b01)) && Act_b1 === 1'b1) begin
Act_b1 = 1'b0;
Pc_b1 = 1'b1;
RP_chk1 = $time;
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("At time %t ERROR: tRAS violation during Precharge", $time);
end
// tWR violation check for Write
if ($time - WR_chk1 < tWR) begin
$display ("At time %t ERROR: tWR violation during Precharge", $time);
end
end
// Precharge bank 2
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b10)) && Act_b2 === 1'b1) begin
Act_b2 = 1'b0;
Pc_b2 = 1'b1;
RP_chk2 = $time;
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("At time %t ERROR: tRAS violation during Precharge", $time);
end
// tWR violation check for Write
if ($time - WR_chk2 < tWR) begin
$display ("At time %t ERROR: tWR violation during Precharge", $time);
end
end
// Precharge bank 3
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b11)) && Act_b3 === 1'b1) begin
Act_b3 = 1'b0;
Pc_b3 = 1'b1;
RP_chk3 = $time;
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("At time %t ERROR: tRAS violation during Precharge", $time);
end
// tWR violation check for Write
if ($time - WR_chk3 < tWR) begin
$display ("At time %t ERROR: tWR violation during Precharge", $time);
end
end
// Prech_count is to make sure we have met part of the initialization sequence
Prech_count = Prech_count + 1;
// Pipeline for READ
A10_precharge [cas_latency_x2] = Addr[10];
Bank_precharge[cas_latency_x2] = Ba;
Cmnd_precharge[cas_latency_x2] = 1'b1;
end
// Burst terminate
if (Burst_term === 1'b1) begin
// Display Debug Message
if (Debug) begin
$display ("At time %t BST : Burst Terminate",$time);
end
if (Data_in_enable === 1'b1) begin
// Illegal to burst terminate a Write
$display ("At time %t ERROR: It's illegal to burst terminate a Write", $time);
if (!no_halt) $stop (0);
end else if (Read_precharge[0] === 1'b1 || Read_precharge[1] === 1'b1 ||
// Illegal to burst terminate a Read with Auto Precharge
Read_precharge[2] === 1'b1 || Read_precharge[3] === 1'b1) begin
$display ("At time %t ERROR: It's illegal to burst terminate a Read with Auto Precharge", $time);
if (!no_halt) $stop (0);
end else begin
// Burst Terminate Command Pipeline for Read
Cmnd_bst[cas_latency_x2] = 1'b1;
end
end
// Read Command
if (Read_enable === 1'b1) begin
if (!(power_up_done)) begin
$display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Read Command", $time);
end
// Check for DLL reset before Read
if (DLL_reset === 1 && DLL_done === 0) begin
$display ("%m: at time %t ERROR: You need to wait 200 tCK after DLL Reset Enable to Read, Not %0d clocks.", $time, DLL_count);
end
// Display Debug Message
if (Debug) begin
$display ("At time %t READ : Bank = %x, Col = %x", $time, Ba, {Addr [11], Addr [9 : 0]});
end
// Terminate a Write
if (Data_in_enable === 1'b1) begin
Data_in_enable = 1'b0;
end
// Activate to Read without Auto Precharge
if ((Addr [10] === 1'b0 && Ba === 2'b00 && $time - RCD_chk0 < tRCD) ||
(Addr [10] === 1'b0 && Ba === 2'b01 && $time - RCD_chk1 < tRCD) ||
(Addr [10] === 1'b0 && Ba === 2'b10 && $time - RCD_chk2 < tRCD) ||
(Addr [10] === 1'b0 && Ba === 2'b11 && $time - RCD_chk3 < tRCD)) begin
$display("At time %t ERROR: tRCD violation during Read", $time);
end
// Activate to Read with Auto Precharge
if ((Addr [10] === 1'b1 && Ba === 2'b00 && $time - RAP_chk0 < tRAP) ||
(Addr [10] === 1'b1 && Ba === 2'b01 && $time - RAP_chk1 < tRAP) ||
(Addr [10] === 1'b1 && Ba === 2'b10 && $time - RAP_chk2 < tRAP) ||
(Addr [10] === 1'b1 && Ba === 2'b11 && $time - RAP_chk3 < tRAP)) begin
$display ("At time %t ERROR: tRAP violation during Read", $time);
end
// Interrupt a Read with Auto Precharge (same bank only)
if (Read_precharge [Ba] === 1'b1) begin
$display ("At time %t ERROR: It's illegal to interrupt a Read with Auto Precharge", $time);
if (!no_halt) $stop (0);
// Cancel Auto Precharge
if (Addr[10] === 1'b0) begin
Read_precharge [Ba]= 1'b0;
end
end
// Activate to Read
if ((Ba === 2'b00 && Pc_b0 === 1'b1) || (Ba === 2'b01 && Pc_b1 === 1'b1) ||
(Ba === 2'b10 && Pc_b2 === 1'b1) || (Ba === 2'b11 && Pc_b3 === 1'b1)) begin
$display("At time %t ERROR: Bank is not Activated for Read", $time);
if (!no_halt) $stop (0);
end else begin
// CAS Latency pipeline
Read_cmnd[cas_latency_x2] = 1'b1;
Read_bank[cas_latency_x2] = Ba;
Read_cols[cas_latency_x2] = {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]};
// Auto Precharge
if (Addr[10] === 1'b1) begin
Read_precharge [Ba]= 1'b1;
Count_precharge [Ba]= 0;
end
end
end
// Write Command
if (Write_enable === 1'b1) begin
if (!(power_up_done)) begin
$display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Write Command", $time);
if (!no_halt) $stop (0);
end
// display debug message
if (Debug) begin
$display ("At time %t WRITE: Bank = %h, Col = %h", $time, Ba, {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]});
end
// Activate to Write
if ((Ba === 2'b00 && $time - RCD_chk0 < tRCD) ||
(Ba === 2'b01 && $time - RCD_chk1 < tRCD) ||
(Ba === 2'b10 && $time - RCD_chk2 < tRCD) ||
(Ba === 2'b11 && $time - RCD_chk3 < tRCD)) begin
$display("At time %t ERROR: tRCD violation during Write to Bank %x", $time, Ba);
end
// Read to Write
if (Read_cmnd[0] || Read_cmnd[1] || Read_cmnd[2] || Read_cmnd[3] ||
Read_cmnd[4] || Read_cmnd[5] || Read_cmnd[6] || (Burst_counter < burst_length)) begin
if (Data_out_enable || read_precharge_truncation) begin
$display("At time %t ERROR: Read to Write violation", $time);
end
end
// Interrupt a Write with Auto Precharge (same bank only)
if (Write_precharge [Ba] === 1'b1) begin
$display ("At time %t ERROR: it's illegal to interrupt a Write with Auto Precharge", $time);
if (!no_halt) $stop (0);
// Cancel Auto Precharge
if (Addr[10] === 1'b0) begin
Write_precharge [Ba]= 1'b0;
end
end
// Activate to Write
if ((Ba === 2'b00 && Pc_b0 === 1'b1) || (Ba === 2'b01 && Pc_b1 === 1'b1) ||
(Ba === 2'b10 && Pc_b2 === 1'b1) || (Ba === 2'b11 && Pc_b3 === 1'b1)) begin
$display("At time %t ERROR: Bank is not Activated for Write", $time);
if (!no_halt) $stop (0);
end else begin
// Pipeline for Write
Write_cmnd [3] = 1'b1;
Write_bank [3] = Ba;
Write_cols [3] = {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]};
// Auto Precharge
if (Addr[10] === 1'b1) begin
Write_precharge [Ba]= 1'b1;
Count_precharge [Ba]= 0;
end
end
end
end
endtask
task check_neg_dqs;
begin
if (Write_cmnd[2] || Write_cmnd[1] || Data_in_enable) begin
for (i=0; i<DQS_BITS; i=i+1) begin
if (expect_neg_dqs[i]) begin
$display ("At time %t ERROR: Negative DQS[%1d] transition required.", $time, i);
end
expect_neg_dqs[i] = 1'b1;
end
end else begin
expect_pos_dqs = 0;
expect_neg_dqs = 0;
end
end
endtask
task check_pos_dqs;
begin
if (Write_cmnd[2] || Write_cmnd[1] || Data_in_enable) begin
for (i=0; i<DQS_BITS; i=i+1) begin
if (expect_pos_dqs[i]) begin
$display ("At time %t ERROR: Positive DQS[%1d] transition required.", $time, i);
end
expect_pos_dqs[i] = 1'b1;
end
end else begin
expect_pos_dqs = 0;
expect_neg_dqs = 0;
end
end
endtask
// Main Logic
always @ (posedge Sys_clk) begin
Manual_Precharge_Pipeline;
Burst_Terminate_Pipeline;
Dq_Dqs_Drivers;
Write_FIFO_DM_Mask_Logic;
Burst_Decode;
check_neg_dqs;
Auto_Precharge_Calculation;
DLL_Counter;
Control_Logic;
end
always @ (negedge Sys_clk) begin
Manual_Precharge_Pipeline;
Burst_Terminate_Pipeline;
Dq_Dqs_Drivers;
Write_FIFO_DM_Mask_Logic;
Burst_Decode;
check_pos_dqs;
end
// Dqs Receiver
always @ (posedge Dqs_in[0]) begin
// Latch data at posedge Dqs
dq_rise[7 : 0] = Dq_in[7 : 0];
dm_rise[0] = Dm_in[0];
expect_pos_dqs[0] = 0;
end
always @ (posedge Dqs_in[1]) begin
// Latch data at posedge Dqs
dq_rise[15 : 8] = Dq_in[15 : 8];
dm_rise[1] = Dm_in [1];
expect_pos_dqs[1] = 0;
end
always @ (negedge Dqs_in[0]) begin
// Latch data at negedge Dqs
dq_fall[7 : 0] = Dq_in[7 : 0];
dm_fall[0] = Dm_in[0];
dm_pair[1:0] = {dm_rise[0], dm_fall[0]};
expect_neg_dqs[0] = 0;
end
always @ (negedge Dqs_in[1]) begin
// Latch data at negedge Dqs
dq_fall[15: 8] = Dq_in[15 : 8];
dm_fall[1] = Dm_in[1];
dm_pair[3:2] = {dm_rise[1], dm_fall[1]};
expect_neg_dqs[1] = 0;
end
specify
// SYMBOL UNITS DESCRIPTION
// ------ ----- -----------
`ifdef sg5B // specparams for -5B (CL = 3)
specparam tDSS = 1.0; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK
specparam tDSH = 1.0; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK
specparam tIH = 0.600; // tIH ns Input Hold Time
specparam tIS = 0.600; // tIS ns Input Setup Time
specparam tDQSH = 1.75; // tDQSH ns DQS input High Pulse Width = 0.35*tCK
specparam tDQSL = 1.75; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK
`else
`ifdef sg6 // specparams for -6 (CL = 2.5)
specparam tDSS = 1.2; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK
specparam tDSH = 1.2; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK
specparam tIH = 0.750; // tIH ns Input Hold Time
specparam tIS = 0.750; // tIS ns Input Setup Time
specparam tDQSH = 2.1; // tDQSH ns DQS input High Pulse Width = 0.35*tCK
specparam tDQSL = 2.1; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK
`else
`ifdef sg75E // specparams for -75E (CL = 2)
specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK
specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK
specparam tIH = 0.900; // tIH ns Input Hold Time
specparam tIS = 0.900; // tIS ns Input Setup Time
specparam tDQSH = 2.625; // tDQSH ns DQS input High Pulse Width = 0.35*tCK
specparam tDQSL = 2.625; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK
`else
`define sg75Z // specparams for -75Z (CL = 2)
specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK
specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK
specparam tIH = 0.900; // tIH ns Input Hold Time
specparam tIS = 0.900; // tIS ns Input Setup Time
specparam tDQSH = 2.625; // tDQSH ns DQS input High Pulse Width = 0.35*tCK
specparam tDQSL = 2.625; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK
`endif
`endif
`endif
$width (posedge Dqs_in[0] &&& wdqs_valid, tDQSH);
$width (posedge Dqs_in[1] &&& wdqs_valid, tDQSH);
$width (negedge Dqs_in[0] &&& wdqs_valid, tDQSL);
$width (negedge Dqs_in[1] &&& wdqs_valid, tDQSL);
$setuphold(posedge Clk, Cke, tIS, tIH);
$setuphold(posedge Clk, Cs_n, tIS, tIH);
$setuphold(posedge Clk, Cas_n, tIS, tIH);
$setuphold(posedge Clk, Ras_n, tIS, tIH);
$setuphold(posedge Clk, We_n, tIS, tIH);
$setuphold(posedge Clk, Addr, tIS, tIH);
$setuphold(posedge Clk, Ba, tIS, tIH);
// $setuphold(posedge Clk, negedge Dqs &&& wdqs_valid, tDSS, tDSH);
endspecify
endmodule
/****************************************************************************************
*
* Disclaimer This software code and all associated documentation, comments or other
* of Warranty: information (collectively "Software") is provided "AS IS" without
* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY
* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES
* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT
* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE
* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE.
* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR
* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI,
* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT,
* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING,
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION,
* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE
* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGES. Because some jurisdictions prohibit the exclusion or
* limitation of liability for consequential or incidental damages, the
* above limitation may not apply to you.
*
* Copyright 2003 Micron Technology, Inc. All rights reserved.
*
****************************************************************************************/
// Timing parameters based on Speed Grade
// SYMBOL UNITS DESCRIPTION
// ------ ----- -----------
`ifdef sg5B // Timing Parameters for -5B (CL = 3)
parameter tCK = 5.0; // tCK ns Nominal Clock Cycle Time
parameter tDQSQ = 0.4; // tDQSS ns DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter tMRD = 10.0; // tMRD ns Load Mode Register command cycle time
parameter tRAP = 15.0; // tRAP ns ACTIVE to READ with Auto precharge command
parameter tRAS = 40.0; // tRAS ns Active to Precharge command time
parameter tRC = 55.0; // tRC ns Active to Active/Auto Refresh command time
parameter tRFC = 70.0; // tRFC ns Refresh to Refresh Command interval time
parameter tRCD = 15.0; // tRCD ns Active to Read/Write command time
parameter tRP = 15.0; // tRP ns Precharge command period
parameter tRRD = 10.0; // tRRD ns Active bank a to Active bank b command time
parameter tWR = 15.0; // tWR ns Write recovery time
`else
`ifdef sg6 // Timing Parameters for -6 (CL = 2.5)
parameter tCK = 6.0; // tCK ns Nominal Clock Cycle Time
parameter tDQSQ = 0.4; // tDQSS ns DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter tMRD = 12.0; // tMRD ns Load Mode Register command cycle time
parameter tRAP = 15.0; // tRAP ns ACTIVE to READ with Auto precharge command
parameter tRAS = 42.0; // tRAS ns Active to Precharge command time
parameter tRC = 60.0; // tRC ns Active to Active/Auto Refresh command time
parameter tRFC = 72.0; // tRFC ns Refresh to Refresh Command interval time
parameter tRCD = 15.0; // tRCD ns Active to Read/Write command time
parameter tRP = 15.0; // tRP ns Precharge command period
parameter tRRD = 12.0; // tRRD ns Active bank a to Active bank b command time
parameter tWR = 15.0; // tWR ns Write recovery time
`else
`ifdef sg75E // Timing Parameters for -75E (CL = 2)
parameter tCK = 7.5; // tCK ns Nominal Clock Cycle Time
parameter tDQSQ = 0.5; // tDQSS ns DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter tMRD = 15.0; // tMRD ns Load Mode Register command cycle time
parameter tRAP = 15.0; // tRAP ns ACTIVE to READ with Auto precharge command
parameter tRAS = 40.0; // tRAS ns Active to Precharge command time
parameter tRC = 60.0; // tRC ns Active to Active/Auto Refresh command time
parameter tRFC = 75.0; // tRFC ns Refresh to Refresh Command interval time
parameter tRCD = 15.0; // tRCD ns Active to Read/Write command time
parameter tRP = 15.0; // tRP ns Precharge command period
parameter tRRD = 15.0; // tRRD ns Active bank a to Active bank b command time
parameter tWR = 15.0; // tWR ns Write recovery time
`else
`define sg75Z // Timing Parameters for -75Z (CL = 2)
parameter tCK = 7.5; // tCK ns Nominal Clock Cycle Time
parameter tDQSQ = 0.5; // tDQSS ns DQS-DQ skew, DQS to last DQ valid, per group, per access
parameter tMRD = 15.0; // tMRD ns Load Mode Register command cycle time
parameter tRAP = 20.0; // tRAP ns ACTIVE to READ with Auto precharge command
parameter tRAS = 40.0; // tRAS ns Active to Precharge command time
// parameter tRC = 65.0; // tRC ns Active to Active/Auto Refresh command time
parameter tRC = 63.0; // tRC ns Active to Active/Auto Refresh command time
parameter tRFC = 75.0; // tRFC ns Refresh to Refresh Command interval time
parameter tRCD = 20.0; // tRCD ns Active to Read/Write command time
parameter tRP = 20.0; // tRP ns Precharge command period
parameter tRRD = 15.0; // tRRD ns Active bank a to Active bank b command time
parameter tWR = 15.0; // tWR ns Write recovery time
`endif
`endif
`endif
// Size Parameters based on Part Width
`ifdef x4
parameter ADDR_BITS = 13; // Set this parameter to control how many Address bits are used
parameter DQ_BITS = 4; // Set this parameter to control how many Data bits are used
parameter DQS_BITS = 1; // Set this parameter to control how many DQS bits are used
parameter DM_BITS = 1; // Set this parameter to control how many DM bits are used
parameter COL_BITS = 12; // Set this parameter to control how many Column bits are used
`else
`ifdef x8
parameter ADDR_BITS = 13; // Set this parameter to control how many Address bits are used
parameter DQ_BITS = 8; // Set this parameter to control how many Data bits are used
parameter DQS_BITS = 1; // Set this parameter to control how many DQS bits are used
parameter DM_BITS = 1; // Set this parameter to control how many DM bits are used
parameter COL_BITS = 11; // Set this parameter to control how many Column bits are used
`else
`define x16
parameter ADDR_BITS = 13; // Set this parameter to control how many Address bits are used
parameter DQ_BITS = 16; // Set this parameter to control how many Data bits are used
parameter DQS_BITS = 2; // Set this parameter to control how many DQS bits are used
parameter DM_BITS = 2; // Set this parameter to control how many DM bits are used
parameter COL_BITS = 10; // Set this parameter to control how many Column bits are used
`endif
`endif
parameter full_mem_bits = 2+ADDR_BITS+COL_BITS; // Set this parameter to control how many unique addresses are used
// parameter part_mem_bits = 10; // Set this parameter to control how many unique addresses are used
parameter part_mem_bits = 12; // Set this parameter to control how many unique addresses are used
parameter no_halt = 1; // If set to 1, the model won't halt on command sequence/major errors
parameter Debug = 1; // Turn on debug message
/*
** -----------------------------------------------------------------------------**
** descrproc353.v
**
**
** Copyright (C) 2002-2010 Elphel, Inc.
** Author: Andrey Filippov
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 descrproc (clk, // SDRAM clock (120MHz?) phase0
ia, // internal 4-bit address bus (fast - directly from I/O pads)
as, // 4 bit address to select descriptor address and data word (3 bits)
am, // switching between ia (async read) and as (sync write)
mcs, // (decoded address) - write to one of 16 loc in descriptor memory (from CPU) and some extra commands
mdi, // 18-bit data from CPU to descriptor memory
mdo, // 32-bit data from descriptor memory to CPU (lower 16 - same as written, high 16 - readonly current state
// now - overlapping as state needs 20 bits.
chStIn, // data channel start (generated by arbiter)
chInit, // will be generated by arbiter, arbiter will not wait for confiramtion
chNum, // 2-bit channel number. Is set by arbiter at chStIn or chInit (is zero when SDRAM is disabled)
chStOut, // channel start output (to sequencer). Delayed by 6 tacts from chStIn
sa, // start address of the block
sfa, // start address of a frame - ugly hack to roll over the last (extra) 4 lines of a frame
// to the beginning of a frame - used in photofinish mode.
rovr, // roll over mode (photofinish, (cntrl0[13]==1) && (mode== 1, last line of tiles)
mode, // mode (0 - 256x1, 1 - 18x9)
WnR, // write /not read
nBuf, // buffer page to use (now - 2 bits)
seq_par, // [5:0] sequencer parameters
// dual-purpose parameter. In 256x1 mode specifies (5 LSBs) number of 8-word long groups to r/w (0- all 32),
// actually for all but 0 (when exactly 256 words are xfered) will transfer one word more
// In 18x9 mode specifies bits 13:8 of address increment between lines
mancmd, // 18-bit manual command for SDRAM (when writig data to RO location 4'h3
enSDRAM, // output that enables SDRAM auto access. When 0 - only manual commands are allowed. Written at address 0'h7, bit 0
enRefresh,// written at address 0'h7, bit 1
enXfer, // enable trasfer through channel
chReqInit,// request (to arbiter) init channel
nextFrame,// (level) generated before actual block is filled - needed to be combined with the pulse from buffer control
confirmRead, // confirm channel read (level OK), needed after start or roll over, FIFO will not be filled otherwise - should be sync to clk
bonded, //[3:0] - channel bonded with the other (just for channel 2), make it TIG
restart_en, // enable restarting selected channels
restart, // reinitialize channels (posedge-sensitive, masked by enXfer0
nextBlocksEn //[3:0] // enable read blocks to FIFO. disabled when init or roll over, enable by confirmRead
); // data to descriptor memory bit matching wnr (write-not-read)
input clk;//,wclk;
input [ 3:0] ia;
input [ 3:0] as;
input [ 3:0] am;
input mcs;
input [17:0] mdi;
output [31:0] mdo;
input chStIn;
input chInit;
input [ 1:0] chNum;
output chStOut;
output [24:3] sa;
output [24:8] sfa; // start frame address - photofinish hack
output rovr; // roll over mode (photofinish, cntrl0[12]==1, last line of tiles)
output mode;
output WnR;
output [ 1:0] nBuf;
output [ 5:0] seq_par;
output [17:0] mancmd;
output enSDRAM;
output enRefresh;
output [ 3:0] enXfer;
output [ 3:0] chReqInit;
output [ 3:0] nextFrame;
input [ 3:0] confirmRead; // confirm channel read (level OK), needed after start or roll over, FIFO will not be filled otherwise
output [ 3:0] bonded; //[3:0] - channel bonded with the other (just for channel 2), make it TIG
input restart_en; // enable restarting selected channels
input [ 3:0] restart; // reinitialize channels (posedge-sensitive, masked by enXfer0
output [3:0] nextBlocksEn; // enable read blocks to FIFO. disabled when init or roll over, enable by confirmRead
reg [3:0] nextBlocksEn; // enable read blocks to FIFO. disabled when init or roll over, enable by confirmRead (always enabled for write channels)
reg [3:0] channelIsRead=4'hf; // channel is programmed in read mode
reg [3:0] bonded; //[3:0] - channel bonded with the other (just for channel 2), make it TIG
wire chStOut;
wire enSDRAM;
wire enSDRAM0;
reg enRefresh;
wire enRefresh0;
reg [ 3:0] enXfer;
wire [ 3:0] enXfer0;
reg [ 3:0] steps; // one-hot states (2 SDclk each) - will switch MUXes
reg [ 3:0] stepsEn; // active during the second- enable registers
assign chStOut=stepsEn[2];
reg stepsI; // 2 cycles after stepsInit
reg stepsIe; // 1 cycle
reg stepsDwe; // enable write to nBuf/tileY/tileX descriptor memory
reg stepsEn012; // == |stepEn[2:0]
reg [ 1:0] rNum; // 2 LSBs of (internal) address of descriptor memory
wire [ 2:0] mancmdRqS;
wire [17:0] mancmd;
reg [ 1:0] chInitNum; // number of channel to request init
reg rqInit;
reg rqInitS;
reg [ 3:0] chReqInit;
reg depend;
reg WnR; // 0 - read from SDRAM, 1 - write to SDRAM
reg mode; // 0 - 128x16bits, 1 - 16x8x16bits
reg [1:0] nBuf;
reg [5:0] seq_par;
reg [24:3] sa; // start SDRAM address
reg [24:8] sfa; // start frame address - photofinish hack
reg rovr, pre_rovr; // roll over mode (photofinish, cntrl0[12]==1
reg [ 9:0] tileX;
reg [13:0] tileY;
reg nxtTL; // next tile line
wire nxtTLw; // will be next tile line
wire last_line; //valid @ Steps[2]
wire last_lines; // valid @ Steps[2] Currnetly - 4 last (input) lines are too late to start compressing
// improve - set a threshold (programmed/calculated)
reg last_lines_reg; //valid from Steps[3]
reg last_lines_source;
// wire first_line; //valid @ Steps[2]
// reg first_line_reg; //valid from Steps[3]
// reg first_line_dest;
wire first_tile; //valid @ Steps[2] - first (destinaltion) tile being processing - to prevent too late start
reg first_tile_reg; //valid from Steps[3]
reg first_tile_dest;
wire nxtTFw; // will be next tile frame (will be used to generate channel done frame)
reg nxtTFr; // registered, same as |nextFrame[3:0]
reg [3:0] nextFrame;
reg srcAtStart; // Source channel is ready fro the first data, but not started yet
wire [17:0] descr_stat; // internal output of 16x18 descriptor memory (ext - rw, int -ro)
wire [21:0] descr_dyn; // internal output of 4x22 descriptor memory (nBuf/tileY/tileX)
wire rst=!enSDRAM;
// for binding of data source with data reciever
// save resources later by making source - always 0, dest - always 2??
reg [13:0] lineNumSource;
reg [13:4] prevStripSource; // number of source strip (line>>4) minus 1 - for faster comaprison w/o addition
reg [13:0] lineNumDest;
reg destBond; // desination channel bonded (should be set before writing to source channel)
reg [ 1:0] destChNum; // channel number for data receiver
reg [ 3:0] suspXfer; // block channel transfer till data source will provide data
reg setLineNumSource;
reg setLineNumDest;
reg [3:0] dest_bond_en; // new fix
reg dest_mode; // new fix
wire resetDestBond= (chNum[1:0]==destChNum[1:0]); //lower priority than set
// wire setDestBond= descr_stat[13]&&!descr_stat[14]; // (depend, read) overwrites resetDestBond
wire setDestBond= descr_stat[13]&&(!descr_stat[14] || descr_stat[15]); // mode=1-> read! (depend, read) overwrites resetDestBond
wire setSourceBond= descr_stat[13] && descr_stat[14] && !descr_stat[15]; // (depend, write, not mode1)
wire updSuspXfer;
wire notEnoughData;
/// wire initChannelAsRead=!descr_stat[14] ;
wire initChannelAsRead=!descr_stat[14] || descr_stat[15] ; /// Was wrong for PF mode
wire [17:0] mdo1;
wire [21:0] mdo2;
reg [13:0] rnTilesY;
reg lastLineDest;
wire [3:0] chNumOneHot={chNum[1] & chNum[0],chNum[1] & ~chNum[0],~chNum[1] & chNum[0],~chNum[1] & ~chNum[0]};
assign notEnoughData= ((lineNumSource[13:4]==lineNumDest[13:4]) && // same 16-tile row
(dest_mode || (lineNumSource[3:0]==lineNumDest[3:0])) && // if destination is line-mode (never used)
(!srcAtStart || first_tile_dest ) ) || /// Just rolled over and image is just 32+4 pixels high
// (dest_mode && (lineNumSource[13:4]==(lineNumDest[13:4]+1'b1)) &&
(dest_mode && (prevStripSource[13:4]==lineNumDest[13:4]) &&
(lineNumSource[3:2]==2'b0)) || // additional 4 line for 20 lines
// (first_line_dest && last_lines_source) || // too late to start compression during last 4 input lines
(first_tile_dest && last_lines_source) || // too late to start compression during last 4 input lines
(lastLineDest && !(|lineNumSource[13:2]) && (dest_mode || !(|lineNumSource[1:0]) )); // roll over
//srcAtStart
always @(negedge clk)
if (stepsIe && setDestBond) dest_mode <= descr_stat[15]; // same as mode <=
always @(negedge clk or posedge rst)
if (rst) destBond <= 1'b0;
else if (stepsIe) destBond <= setDestBond || (destBond && !resetDestBond);
always @(negedge clk)
if (stepsIe && setDestBond) destChNum[1:0] <= chNum[1:0];
always @(negedge clk) begin
setLineNumSource <= steps[3] && WnR && depend && destBond && ~setLineNumSource;
setLineNumDest <= steps[3] && !WnR && depend && ~setLineNumDest;
end
always @(negedge clk) if (stepsIe) begin
if (chNum[1:0]==2'b00) begin
dest_bond_en[0] <= setDestBond;
channelIsRead[0] <= initChannelAsRead;
end
if (chNum[1:0]==2'b01) begin
dest_bond_en[1] <= setDestBond;
channelIsRead[1] <= initChannelAsRead;
end
if (chNum[1:0]==2'b10) begin
dest_bond_en[2] <= setDestBond;
channelIsRead[2] <= initChannelAsRead;
end
if (chNum[1:0]==2'b11) begin
dest_bond_en[3] <= setDestBond;
channelIsRead[3] <= initChannelAsRead;
end
end
always @(negedge clk) bonded[3:0] <= dest_bond_en[3:0]; //[3:0] - channel bonded with the other (just for channel 2), make it TIG
// reg nxtTL_r;
reg [2:0] nxtTF_p;
wire nxtTf_d= &nxtTF_p; // valid @ stepsEn[3]
always @ (negedge clk) begin
nextBlocksEn[3:0] <= ~channelIsRead[3:0] | //always enabled for write channels
confirmRead[3:0] | // confirmed read, may continue (level "1" if not needed)
(nextBlocksEn[3:0] &
~({4{stepsIe}} & chNumOneHot[3:0] ) & // turn off after programming (write mode is excluded above)
~({4{stepsEn[3] & nxtTf_d} } & chNumOneHot[3:0])); // turn off at next frame
end
always @(negedge clk) begin
if (stepsIe && setSourceBond) lineNumSource[13:0] <= 14'h0;
else if (setLineNumSource) lineNumSource[13:0] <= {tileY[13:4],mode?4'b0:tileY[3:0]};
if (stepsIe && setSourceBond) srcAtStart<=1'b1; // just initialized
else if (setLineNumSource) srcAtStart<=nxtTFr; // just rolled over
// reg srcAtStart; // Source channel is ready fro the first data, but not started yet
prevStripSource[13:4] <= lineNumSource[13:4]-1;
if (stepsIe && setDestBond) lineNumDest[13:0] <= 14'h0;
else if (setLineNumDest) lineNumDest[13:0] <= {tileY[13:4],mode?4'b0:tileY[3:0]};
if (stepsIe && setDestBond) lastLineDest <= 1'b0;
else if (setLineNumDest)
lastLineDest <= pre_rovr && (tileY[13:4]==rnTilesY[13:4]) && (mode || (tileY[3:0]==rnTilesY[3:0]));
if (stepsIe && setSourceBond) last_lines_source <= 1'b0;
else if (setLineNumSource) last_lines_source <= last_lines_reg;
// if (stepsIe && setDestBond) first_line_dest <= 1'b1;
// else if (setLineNumDest) first_line_dest <= first_line_reg;
if (stepsIe && setDestBond) first_tile_dest <= 1'b1;
else if (setLineNumDest) first_tile_dest <= first_tile_reg;
end
reg restart_en_sync;
reg [3:0] enRestart;
wire [3:0] extRestartRq0;
reg [3:0] extRestartRq1;
reg [3:0] extRestartRq2;
reg [3:0] extRestartRq;
always @(negedge clk) begin
restart_en_sync <= restart_en;
enRestart[3:0] <= enXfer0[3:0] & {4{restart_en_sync}};
extRestartRq1[3:0] <= extRestartRq0[3:0];
extRestartRq2[3:0] <= extRestartRq1[3:0];
extRestartRq[3:0] <= extRestartRq1[3:0] & (~extRestartRq2[3:0]);
end
FDCE i_extRestartRq0_0 (.C(restart[0]),.CLR(!enRestart[0] || extRestartRq[0] ),.CE(1'b1),.D(enRestart[0]),.Q(extRestartRq0[0]));
FDCE i_extRestartRq0_1 (.C(restart[1]),.CLR(!enRestart[1] || extRestartRq[1] ),.CE(1'b1),.D(enRestart[1]),.Q(extRestartRq0[1]));
FDCE i_extRestartRq0_2 (.C(restart[2]),.CLR(!enRestart[2] || extRestartRq[2] ),.CE(1'b1),.D(enRestart[2]),.Q(extRestartRq0[2]));
FDCE i_extRestartRq0_3 (.C(restart[3]),.CLR(!enRestart[3] || extRestartRq[3] ),.CE(1'b1),.D(enRestart[3]),.Q(extRestartRq0[3]));
/*
input restart_en; // enable restarting seslcted channels
input [ 3:0] restart; // reinitialize channles (posedge-sensitive, masked by enXfer0
// FDCE i_mancmdRq (.C(wclk),.CLR(mancmdRqS[1]),.CE(mcs),.D(mancmdRq | (maddr[3:0] == 4'h3)),.Q(mancmdRq));
*/
// MSRL16_1 i_updSuspXfer (.Q(updSuspXfer), .A(4'h1), .CLK(clk), .D(setLineNumSource || setLineNumDest));// dly=1+1
// after registering prevStripSource need 2 more cycles. Should not break anything if the suspXfer signal
// is delayed by 2 clock cycles - all decisions are already made (some 10-20 cycles earlier)
MSRL16_1 i_updSuspXfer (.Q(updSuspXfer), .A(4'h3), .CLK(clk), .D(setLineNumSource || setLineNumDest));// dly=1+3
//suspXfer (all 4) will at stepsIe will be set/reset to setDestBond (only selected, others - reset)
//suspXfer (selected) will be updated both at write to source and read from dest
always @(negedge clk)
if (stepsIe && setDestBond) suspXfer[0] <= (chNum[1:0]==2'b00);
else if (updSuspXfer && (destChNum[1:0]==2'b00)) suspXfer[0] <= notEnoughData;
always @(negedge clk)
if (stepsIe && setDestBond) suspXfer[1] <= (chNum[1:0]==2'b01);
else if (updSuspXfer && (destChNum[1:0]==2'b01)) suspXfer[1] <= notEnoughData;
always @(negedge clk)
if (stepsIe && setDestBond) suspXfer[2] <= (chNum[1:0]==2'b10);
else if (updSuspXfer && (destChNum[1:0]==2'b10)) suspXfer[2] <= notEnoughData;
always @(negedge clk)
if (stepsIe && setDestBond) suspXfer[3] <= (chNum[1:0]==2'b11);
else if (updSuspXfer && (destChNum[1:0]==2'b11)) suspXfer[3] <= notEnoughData;
// refresh and SDRAM automatic access control
// always @ (posedge wclk) if (mcs && (maddr[3:0]==4'h7)) {enXfer0[3:0],enRefresh0} <= mdi[5:1];
// use to initialize by glbl.GSR = 1'b1;
// simplify here?
// always @ (negedge clk) if (mcs && (as[3:0]==4'h7)) {enXfer0[3:0],enRefresh0} <= mdi[5:1];
// FDE_1 i_enSDRAM0 (.C(clk),.CE(mcs && (as[3:0]==4'h7)),.D(mdi[0]),.Q(enSDRAM0));
/// Modified to enable selective set/reset bits, without changing others
FDE_1 i_enSDRAM0 (.C(clk),.CE(mcs && (as[3:0]==4'h7) && mdi[ 1]),.D(mdi[ 0]),.Q(enSDRAM0));
FDE_1 i_enRefresh0 (.C(clk),.CE(mcs && (as[3:0]==4'h7) && mdi[ 3]),.D(mdi[ 2]),.Q(enRefresh0));
FDE_1 i_enXfer00 (.C(clk),.CE(mcs && (as[3:0]==4'h7) && mdi[ 5]),.D(mdi[ 4]),.Q(enXfer0[0]));
FDE_1 i_enXfer01 (.C(clk),.CE(mcs && (as[3:0]==4'h7) && mdi[ 7]),.D(mdi[ 6]),.Q(enXfer0[1]));
FDE_1 i_enXfer02 (.C(clk),.CE(mcs && (as[3:0]==4'h7) && mdi[ 9]),.D(mdi[ 8]),.Q(enXfer0[2]));
FDE_1 i_enXfer03 (.C(clk),.CE(mcs && (as[3:0]==4'h7) && mdi[11]),.D(mdi[10]),.Q(enXfer0[3]));
// always @ (negedge clk) {enXfer[3:0],enRefresh} <= {(enXfer0[3:0] & ~(suspXfer[3:0] & dest_bond_en[3:0])),enRefresh0}; // synchronize
always @ (negedge clk) {enXfer[3:0],enRefresh} <= {(enXfer0[3:0] & nextBlocksEn[3:0] & ~(suspXfer[3:0] & dest_bond_en[3:0])),enRefresh0}; // synchronize
FD_1 i_enSDRAM (.C(clk),.D(enSDRAM0),.Q(enSDRAM));
// FDCE i_mancmdRq (.C(wclk),.CLR(mancmdRqS[1]),.CE(mcs),.D(mancmdRq | (maddr[3:0] == 4'h3)),.Q(mancmdRq));
FD_1 i_mancmdRqS_0 (.C(clk),.D((mcs && (as[3:0] == 4'h3)) || (mancmdRqS[0] && !mancmdRqS[1]) ),.Q(mancmdRqS[0]));
FD_1 i_mancmdRqS_1 (.C(clk),.D(mancmdRqS[0]),.Q(mancmdRqS[1]));
FD_1 i_mancmdRqS_2 (.C(clk),.D(mancmdRqS[0] && mancmdRqS[1]),.Q(mancmdRqS[2]));
// generate address - will be 0 for init
always @ (negedge clk) rNum[1:0] <= {mancmdRqS[0] || stepsEn[1] || (steps[2] && !stepsEn[2]),
mancmdRqS[0] || stepsEn[0] || (steps[1] && !stepsEn[1])};
FD_1 i_mancmd_00 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 0]),.Q(mancmd[ 0]));
FD_1 i_mancmd_01 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 1]),.Q(mancmd[ 1]));
FD_1 i_mancmd_02 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 2]),.Q(mancmd[ 2]));
FD_1 i_mancmd_03 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 3]),.Q(mancmd[ 3]));
FD_1 i_mancmd_04 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 4]),.Q(mancmd[ 4]));
FD_1 i_mancmd_05 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 5]),.Q(mancmd[ 5]));
FD_1 i_mancmd_06 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 6]),.Q(mancmd[ 6]));
FD_1 i_mancmd_07 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 7]),.Q(mancmd[ 7]));
FD_1 i_mancmd_08 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 8]),.Q(mancmd[ 8]));
FD_1 i_mancmd_09 (.C(clk),.D(!mancmdRqS[2] | descr_stat[ 9]),.Q(mancmd[ 9]));
FD_1 i_mancmd_10 (.C(clk),.D(!mancmdRqS[2] | descr_stat[10]),.Q(mancmd[10]));
FD_1 i_mancmd_11 (.C(clk),.D(!mancmdRqS[2] | descr_stat[11]),.Q(mancmd[11]));
FD_1 i_mancmd_12 (.C(clk),.D(!mancmdRqS[2] | descr_stat[12]),.Q(mancmd[12]));
FD_1 i_mancmd_13 (.C(clk),.D(!mancmdRqS[2] | descr_stat[13]),.Q(mancmd[13]));
FD_1 i_mancmd_14 (.C(clk),.D(!mancmdRqS[2] | descr_stat[14]),.Q(mancmd[14]));
FD_1 i_mancmd_15 (.C(clk),.D(!mancmdRqS[2] | descr_stat[15]),.Q(mancmd[15]));
FD_1 i_mancmd_16 (.C(clk),.D(!mancmdRqS[2] | descr_stat[16]),.Q(mancmd[16]));
FD_1 i_mancmd_17 (.C(clk),.D(!mancmdRqS[2] | descr_stat[17]),.Q(mancmd[17]));
//synthesis translate_off
defparam i_mancmd_00.INIT = 1'b1;
defparam i_mancmd_01.INIT = 1'b1;
defparam i_mancmd_02.INIT = 1'b1;
defparam i_mancmd_03.INIT = 1'b1;
defparam i_mancmd_04.INIT = 1'b1;
defparam i_mancmd_05.INIT = 1'b1;
defparam i_mancmd_06.INIT = 1'b1;
defparam i_mancmd_07.INIT = 1'b1;
defparam i_mancmd_08.INIT = 1'b1;
defparam i_mancmd_09.INIT = 1'b1;
defparam i_mancmd_10.INIT = 1'b1;
defparam i_mancmd_11.INIT = 1'b1;
defparam i_mancmd_12.INIT = 1'b1;
defparam i_mancmd_13.INIT = 1'b1;
defparam i_mancmd_14.INIT = 1'b1;
defparam i_mancmd_15.INIT = 1'b1;
defparam i_mancmd_16.INIT = 1'b1;
defparam i_mancmd_17.INIT = 1'b1;
//synthesis translate_on
//synthesis attribute INIT of i_mancmd_00 is "1"
//synthesis attribute INIT of i_mancmd_01 is "1"
//synthesis attribute INIT of i_mancmd_02 is "1"
//synthesis attribute INIT of i_mancmd_03 is "1"
//synthesis attribute INIT of i_mancmd_04 is "1"
//synthesis attribute INIT of i_mancmd_05 is "1"
//synthesis attribute INIT of i_mancmd_06 is "1"
//synthesis attribute INIT of i_mancmd_07 is "1"
//synthesis attribute INIT of i_mancmd_08 is "1"
//synthesis attribute INIT of i_mancmd_09 is "1"
//synthesis attribute INIT of i_mancmd_10 is "1"
//synthesis attribute INIT of i_mancmd_11 is "1"
//synthesis attribute INIT of i_mancmd_12 is "1"
//synthesis attribute INIT of i_mancmd_13 is "1"
//synthesis attribute INIT of i_mancmd_14 is "1"
//synthesis attribute INIT of i_mancmd_15 is "1"
//synthesis attribute INIT of i_mancmd_16 is "1"
//synthesis attribute INIT of i_mancmd_17 is "1"
// always @ (posedge wclk) if (mcs && (maddr[1:0] == 2'h0)) chInitNum[1:0] <= maddr[3:2];
always @ (negedge clk) if (mcs && (as[1:0] == 2'h0)) chInitNum[1:0] <= as[3:2];
always @ (negedge clk) begin
rqInit <= mcs && (as[1:0] == 2'h0);
rqInitS <= rqInit;
chReqInit <= extRestartRq[3:0] | {rqInitS && (chInitNum[1:0]==2'b11),
rqInitS && (chInitNum[1:0]==2'b10),
rqInitS && (chInitNum[1:0]==2'b01),
rqInitS && (chInitNum[1:0]==2'b00)};
end
// sequence of address calculation
// adding reset (simulation only)?
always @ (negedge clk or posedge rst)
if (rst) begin
steps[3:0] <= 4'b0;
stepsI <= 1'b0;
end else begin
steps[3:0] <= {stepsEn[2:0],(chStIn & !chInit)} | (steps[3:0] &~stepsEn[3:0]);
stepsI <= chInit || (stepsI && ~stepsIe);
end
always @ (negedge clk) begin
stepsEn[3:0] <= (steps[3:0] & ~stepsEn[3:0]);
stepsEn012 <= |steps[2:0] && ~(|stepsEn[2:0]);
stepsIe <= stepsI && ~stepsIe;
stepsDwe <= (stepsI || steps[3]) && ~stepsDwe;
end
// to fit 18-bit memory, 2 bits are overlapped:
// assign mdo[31:0]={mdo2[19:4],(ia[1:0]==2'b10)?mdo2mdo2[3:0]:mdo1[17:12],mdo1[11:0]};
// read actual SDRAM enable register (masked in bits 11:6, unmasked (as written) in bits 5:0
assign mdo[31:0]={mdo2[21:20], //nBuf[1:0]
(ia[1:0]==2'h2)?
mdo2[13:0]: //some tileY, all tileX
mdo2[19:6], // all tile Y (in mode 1 - some tile X also)
(ia[3:0]==4'h7)?
// {4'h0,enXfer[3:0],enRefresh,enSDRAM,enXfer0[3:0],enRefresh0,enSDRAM0}:
{nextBlocksEn[3:0],enXfer[3:0],enRefresh,enSDRAM,enXfer0[3:0],enRefresh0,enSDRAM0}:
mdo1[15:0]}; ///mdo1[17:16] are not read back - these bits are used only in mancmd
myRAM_WxD_D #( .DATA_WIDTH(18),.DATA_DEPTH(4))
i_descr_stat(.D(mdi[17:0]),
.WE(mcs),
.clk(~clk),
.AW(am[3:0]),
.AR({chNum[1:0],rNum[1:0]}),
.QW(mdo1[17:0]), ///NOTE: 2 MSBs not used
.QR(descr_stat[17:0]));
// nBuf[1:0] will start with 2'b00 (after first read from memory)
myRAM_WxD_D #( .DATA_WIDTH(22),.DATA_DEPTH(2))
i_descr_dyn(.D(stepsI?22'h300000:{nBuf[1:0],tileY[13:4],(mode?tileX[9:5]:{tileY[3:0],1'b0}),tileX[4:0]}),
.WE(stepsDwe),
.clk(~clk),
.AW(chNum[1:0]),
.AR(ia[3:2]),
.QW(descr_dyn[21:0]),
.QR(mdo2[21:0]));
assign nxtTLw= mode?(descr_dyn[9:0]==descr_stat[13:4]):(descr_dyn[4:0]==descr_stat[13:9]); // step[1]
assign last_line= (descr_dyn[19:10]==descr_stat[13:4]) && (mode || (descr_dyn[9:6]==descr_stat[3:0])); // step[2]
assign last_lines= (descr_dyn[19:10]==descr_stat[13:4]) && (mode || (descr_dyn[9:8]==descr_stat[3:2])); // step[2]
// assign first_line= (descr_dyn[19:10]==10'h0) && (mode || (descr_dyn[9:6]==4'h0)); // step[2]
assign first_tile= (descr_dyn[19:0]==20'h0); // step[2]
assign nxtTFw= nxtTL && last_line; // step[2]
always @ (negedge clk) if (stepsEn[0] || stepsIe) begin // address should be 0
mode <=descr_stat[15]; // address should be 0
WnR <= descr_stat[14] && !descr_stat[15]; // address should be 0 (mask WnR by mode, use descr_stat[15:14]==2'b11 as PF-mode
pre_rovr <= descr_stat[14] && descr_stat[15] ; //
depend<= descr_stat[13];
// pre_rovr <= descr_stat[12]; // roll over mode (photofinish, cntrl0[12]==1 /// NOTE:Does it need to be fixed??
end
always @ (negedge clk) if (stepsEn[2]) rovr <= last_line && pre_rovr; //last_line valid at stepsEn[2] only
//TODO: set first/last at channel init
always @ (negedge clk) if (stepsEn[2]) last_lines_reg <= last_lines ; //last_lines valid at stepsEn[2] only
// always @ (negedge clk) if (stepsEn[2]) first_line_reg <= first_line ; //first_line valid at stepsEn[2] only
always @ (negedge clk) if (stepsEn[2]) first_tile_reg <= first_tile ; //first_line valid at stepsEn[2] only
always @ (negedge clk) if (stepsEn[0]) begin // address should be 0
nBuf[1:0] <=descr_dyn[21:20]+1;
end
wire [4:0] padlen;
assign padlen=((mode && (descr_stat[8:4]==5'h1f))?(descr_stat[13:9]+1'b1):descr_stat[13:9])+1;
reg [15:0] linAddr;
// wire [15:0] linAddr; //replacing with latches to ease timing
wire [15:0] linAddr_input;
// assign linAddr_input[15:0] = (padlen[4:0]*{descr_dyn[19:10],mode?4'b0:descr_dyn[9:6]}) +{descr_dyn[19:10],mode?4'b0:descr_dyn[9:6]}; // Result MSB not used
assign linAddr_input[15:0] = padlen[4:0]*{descr_dyn[19:10],mode?4'b0:descr_dyn[9:6]};
always @ (negedge clk) if (stepsEn[1]) begin // address should be 1
seq_par[5:0] <= mode?({1'b0,descr_stat[13:9]}+((descr_stat[8:4]==5'h1f)?2'h2:2'h1)): //fixed bug with pages where number of hor. tiles is multiple of 0x10
({1'b0,(descr_dyn[4:0]==descr_stat[13:9])?(descr_stat[8:4]+1):5'b0});
sa[7:3] <= mode?descr_dyn[4:0]:5'b0;
linAddr[15:0] <= linAddr_input[15:0];
// linAddr[15:0] <= (padlen[4:0]*{descr_dyn[19:10],mode?4'b0:descr_dyn[9:6]})+{descr_dyn[19:10],mode?4'b0:descr_dyn[9:6]}; // Result MSB not used
nxtTL <= nxtTLw;
tileX[ 9:0] <= nxtTLw? 10'b0 : (descr_dyn[9:0]+1); // bits [9:5] are garbage if (mode==0)
end
/*
reg linAddr_en;
always @ (negedge clk) linAddr_en <= (stepsEn[1]);
LDCPE i_linAddr_0 (.Q(linAddr[ 0]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_1 (.Q(linAddr[ 1]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_2 (.Q(linAddr[ 2]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_3 (.Q(linAddr[ 3]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_4 (.Q(linAddr[ 4]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_5 (.Q(linAddr[ 5]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_6 (.Q(linAddr[ 6]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_7 (.Q(linAddr[ 7]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_8 (.Q(linAddr[ 8]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_9 (.Q(linAddr[ 9]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_10 (.Q(linAddr[10]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_11 (.Q(linAddr[11]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_12 (.Q(linAddr[12]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_13 (.Q(linAddr[13]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_14 (.Q(linAddr[14]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
LDCPE i_linAddr_15 (.Q(linAddr[15]), .D(linAddr_input[ 0]), .G(clk), .GE(linAddr_en), .CLR(1'b0),.PRE(1'b0));
*/
/*
wire [15:0] linAddr; //replacing with latches to ease timing
wire [15:0] linAddr_input;
LDCPE #(
.INIT(1'b0) // Initial value of latch (1'b0 or 1'b1)
) LDCPE_inst (
.Q(Q), // Data output
.CLR(CLR), // Asynchronous clear/reset input
.D(D), // Data input
.G(G), // Gate input
.GE(GE), // Gate enable input
.PRE(PRE) // Asynchronous preset/set input
);
*/
always @ (negedge clk) if (stepsEn[2]) begin // address should be 2
tileY[13:0] <= nxtTFw? 14'b0 : (descr_dyn[19:6]+{9'b0,(nxtTL && mode),3'b0,(nxtTL && !mode)});
rnTilesY[13:0] <= descr_stat[13:0];
nxtTF_p[2:0] <={nxtTL, (descr_dyn[19:10]==descr_stat[13:4])?1'b1:1'b0, (mode || (descr_dyn[9:6]==descr_stat[3:0]))?1'b1:1'b0};
end
always @ (negedge clk) if (stepsEn012) begin
sa[24:8] <= steps[0]?
{4'b0,descr_stat[12:0]}:
(sa[24:8]+
(steps[1]?
{descr_stat[3:0],8'b0,mode?
descr_dyn[9:5]:
descr_dyn[4:0]}:
{linAddr[15:0]}));
end
//photofinish hack
always @ (negedge clk) if (stepsEn[1]) begin
sfa[24:8] <= {descr_stat[3:0], sa[20:8]};
end
always @ (negedge clk) begin
if (stepsEn[2] && (chNum[1:0]==2'b00)) nextFrame[0] <= nxtTFw;
if (stepsEn[2] && (chNum[1:0]==2'b01)) nextFrame[1] <= nxtTFw;
if (stepsEn[2] && (chNum[1:0]==2'b10)) nextFrame[2] <= nxtTFw;
if (stepsEn[2] && (chNum[1:0]==2'b11)) nextFrame[3] <= nxtTFw;
if (stepsEn[2] ) nxtTFr <= nxtTFw;
end
endmodule
/*
** -----------------------------------------------------------------------------**
** dma_fifosync353.v
**
** DMA controller/fifo
**
** Copyright (C) 2002-2007 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// with long 8-cycle bursts it makes sense to move everything to internal clock domain (no need fro Gray counters)
// uses GCLK buffer (so 2 for 2 DMA channels)
module dma_fifo_sync ( clk, // system clock, 120MHz? (currentle negedge used)
pre_wen, // decoded addresses (valid @ negedge clk)
wd, // {enable update, pio_mode, enable channel}
dreq, // DREQ output to CPU
dack, // DACK input from CPU
// re, // read enable (CE | OE)
oe, // just OE
pioinc, // increment buffer address in PIO mode
d, // [31:0] - data to cpu
we, // write enable (sync to posedge clk)
di, // 16-bit data to write (sync to posedge clk)
enabled, // channel enabled
real_empty
,test1,
test2
); // pessimistic, with several clk delay
input clk;
input pre_wen;
input [2:0] wd; // bit2 - enable update of bits [1:0], bit 0 - enable channel, bit 1 - PIO mode
output dreq;
input dack;
// input re;
input oe;
input pioinc;
output [31:0] d;
input we;
input [15:0] di;
output enabled;
output real_empty;
output [7:0] test1;
output [7:0] test2;
reg wen;
wire en;
reg [9:0] wab; // binary write counter
reg [8:0] rab; // binary read counter
wire rst;
reg [3:0] empties;
wire en0;
wire pio, pio0; //enable pio read mode
reg [2:0] di_d;
assign rst=!en;
assign enabled=en;
assign real_empty=empties[3];
assign test1=rab[7:0];
assign test2=wab[7:0];
wire swclk; // global clock, switched between OE (when DACK active) and extra pulse generated to read first word from FIFO.
reg firstclk; // generated 1-clk_long pulse as a source for swclk
reg written_burst; // 16 of 16-bit words are just written to FIFO
wire mem_re; // memory RE signal (alo increments counters)
reg dreq;
reg [1:0] burst_start_sync; // 1 clk long pulse (clk-sync) after start of the DMA burst
reg [1:0] dack_r; // synchronize to clk, dual to prevent metastability
reg [9:0] infifo; // number of words in FIFO (10 bits, to implement overflow)
reg first_four; // sync to OE
reg [2:0] first_four_r; // sync to clk
reg nempty; // registered fifo_not_empty
reg lessthan2; // registered fifo has less than 2 words
assign mem_re= dreq || !dack_r[1] || (rab[2:0]!=3'b0);
always @ (negedge clk) begin
wen <= pre_wen;
di_d[2:0] <= wd[2:0];
end
FDE_1 i_en0 (.C(clk), .D(di_d[0]), .CE(wen & di_d[2]), .Q(en0));
FD i_en_tig_ (.C(clk), .D(en0), .Q(en));
FDE_1 i_pio0 (.C(clk), .D(di_d[1]), .CE(wen & di_d[2]), .Q(pio0));
FD i_pio_tig_ (.C(clk), .D(pio0), .Q(pio));
BUFG i_swclk (.O(swclk),.I(dack?oe:(!firstclk && !(pio && pioinc))));
always @ (posedge clk) begin
if (rst) wab[9:0] <= 10'b0;
else if ( we) wab[9:0] <= wab[9:0] + 1;
written_burst <= we && (wab[3:0]==4'hf);
nempty <= (infifo[9:0]!=10'h0);
lessthan2 <= (infifo[9:1]== 9'h0);
if (!en) infifo[9:0] <= 10'h0;
else if ( written_burst && !burst_start_sync[0]) infifo[9:0] <= infifo[9:0]+1;
else if (!written_burst && burst_start_sync[0]) infifo[9:0] <= infifo[9:0]-1;
dack_r[1:0] <= {dack_r[0], dack};
if (rst || firstclk) firstclk <= 1'b0;
// else if (!pio && written_burst && !dreq && !dack_r[1]) firstclk <= 1'b1; //dreq & dack_r1[1] overlap
// don't need to add &&!burst_start_sync[1] as burst_start_sync[1] overlaps with dack_r[1]
else if (!pio && nempty && !dreq && !dack_r[1]) firstclk <= 1'b1; //dreq & dack_r1[1] overlap
// if (rst || ((infifo[9:0]==10'h0) && burst_start_sync[1])) dreq <= 1'b0;
// changed to faster (registered) version. burst_start_sync[1] happens just first cycle after infifo[9:0] was decremented
// so we need that a cycle it was >1, not !=0. We can miss increment count (written_burst), but don't bother
// adding condition - not a great loss.
if (rst || (lessthan2 && burst_start_sync[1])) dreq <= 1'b0;
else if (firstclk) dreq <= 1'b1;
burst_start_sync[1:0] <= {burst_start_sync[0],~first_four_r[2] & first_four_r[1]};
first_four_r[2:0]={first_four_r[1:0],first_four};
empties[3:0] <= {4{!rst && (infifo[9:0]==10'h0) && !dreq && !dack_r[1]}} & {empties[2:0],1'b1};
end
always @ (posedge rst or posedge swclk) begin
if (rst) rab[8:0] <= 9'h0;
else if (mem_re) rab[8:0] <= rab[8:0] + 1;
if (rst) first_four <= 1'b0;
else if (rab[1:0]==2'h1) first_four <= ~rab[2];
end
RAMB16_S18_S36 i_dmafifobuff (
.DOA(), // Port A 16-bit Data Output - FPN (sensor) side
.DOPA(), // Port A 2-bit Parity Output
.ADDRA(wab[9:0]), // Port A 10-bit Address Input
// .CLKA(!clk), // Port A Clock
.CLKA(clk), // Port A Clock
.DIA(di[15:0]), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(we), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b1), // Port A Write Enable Input
.DOB(d), // Port B 32-bit Data Output - SDRAM side
.DOPB(), // Port B 4-bit Parity Output
.ADDRB(rab[8:0]), // Port B 9-bit Address Input
.CLKB(swclk), // Port B Clock
.DIB(32'b0), // Port B 32-bit Data Input
.DIPB(4'b0), // Port-B 4-bit parity Input
.ENB(mem_re), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
endmodule
/*
** -----------------------------------------------------------------------------**
** encoderDCAC353.v
**
** RLL encoder for JPEG compressor
**
** Copyright (C) 2002-2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// Accepts 13-bits signed data (only 12-bit can be ecoded), so DC difference (to be encoded) is limited (saturated) to 12 bits, not the value itself
// AC - always limited to 800 .. 7ff
module encoderDCAC(clk,
en,
// firsti, // was "first MCU in a frame" (@ stb)
lasti, // was "last MCU in a frame" (@ stb)
first_blocki, // first block in frame - save fifo write address (@ stb)
comp_numberi, // [2:0] component number 0..2 in color, 0..3 - in jp4diff, >= 4 - don't use (@ stb)
comp_firsti, // fitst this component in a frame (reset DC) (@ stb)
comp_colori, // use color - huffman? (@ stb)
comp_lastinmbi, // last component in a macroblock (@ stb) is it needed?
stb, // strobe that writes firsti, lasti, tni,average
zdi, // [11:0] zigzag-reordered data input
first_blockz, // first block input (@zds)
zds, // strobe - one ahead of the DC component output
last, //
do,
dv
);
input clk;
input en;
// input firsti;
input lasti;
input first_blocki; // first block in frame - save fifo write address (@ stb)
input [2:0] comp_numberi; // [2:0] component number 0..2 in color, 0..3 - in jp4diff, >= 4 - don't use (@ stb)
input comp_firsti; // fitst this component in a frame (reset DC) (@ stb)
input comp_colori; // use color - huffman? (@ stb)
input comp_lastinmbi; // last component in a macroblock (@ stb)
input stb;
input [12:0] zdi;
input first_blockz; // first block input (@zds)
input zds;
output last;
output [15:0] do;
output dv;
// reg [2:0] ic;
// reg [2:0] oc;
reg last;
// 8x13 DC storage memory
reg [12:0] dc_mem[7:0];
reg [12:0] dc_diff0, dc_diff;
wire [11:0] dc_diff_limited= (dc_diff[12]==dc_diff[11])? dc_diff[11:0] : {~dc_diff[11],{11{dc_diff[11]}}}; // difference (to be encoded) limited to fit 12 bits
reg [12:0] dc_restored; // corrected DC value of the current block, compensated to fit difference to 12 bits
reg [5:0] rll_cntr;
reg [15:0] do;
// reg dv0;
reg dv;
//
reg [5:0] cntr;
// reg ac_on;
reg [11:0] ac_in;
wire izero=(ac_in[11:0]==12'b0);
reg [14:0] val_r; // DC diff/AC values to be sent out, registered
reg DCACen; // enable DC/AC (2 cycles ahead of do
wire rll_out;
// wire eob_out;
wire pre_dv;
reg was_nonzero_AC;
reg [12:0] zdi_d;
reg [3:0] zds_d;
// wire dc_mem_we= zds_d[3]; // not needed
wire DC_tosend= zds_d[2];
wire pre_DCACen= zds_d[1];
wire [2:0] comp_numbero; // [2:0] component number 0..2 in color, 0..3 - in jp4diff, >= 4 - don't use
wire comp_firsto; // first this component in a frame (reset DC)
wire comp_coloro; // use color - huffman?
// wire first_blocko; // first block in frame - save fifo write address
wire comp_lastinmbo; // last component in a macroblock
wire lasto; // last macroblock in a frame
reg [2:0] block_mem_ra;
reg [2:0] block_mem_wa;
reg [2:0] block_mem_wa_save;
reg [6:0] block_mem[0:7];
wire [6:0] block_mem_o=block_mem[block_mem_ra[2:0]];
assign comp_numbero[2:0]= block_mem_o[2:0];
assign comp_firsto= block_mem_o[3];
assign comp_coloro= block_mem_o[4];
// assign first_blocko= block_mem_o[5];
assign comp_lastinmbo= block_mem_o[5];
assign lasto= block_mem_o[6];
always @ (posedge clk) begin
if (stb) block_mem[block_mem_wa[2:0]] <= {lasti, comp_lastinmbi, /*first_blocki,*/ comp_colori,comp_firsti,comp_numberi[2:0]};
if (!en) block_mem_wa[2:0] <= 3'h0;
else if (stb) block_mem_wa[2:0] <= block_mem_wa[2:0] +1;
if (stb && first_blocki) block_mem_wa_save[2:0] <= block_mem_wa[2:0];
if (!en) block_mem_ra[2:0] <= 3'h0;
else if (zds) block_mem_ra[2:0] <= first_blockz?block_mem_wa_save[2:0]:(block_mem_ra[2:0] +1);
end
assign rll_out= ((val_r[12] && !val_r[14]) || (ac_in[11:0]!=12'b0)) && (rll_cntr[5:0]!=6'b0);
assign pre_dv=rll_out || val_r[14] || was_nonzero_AC;
always @ (posedge clk) begin
val_r[14:0] <={ DC_tosend?
{en,
comp_coloro,
comp_lastinmbo && lasto, // last component's in a frame DC coefficient
dc_diff_limited[11:0]}:
{2'b0,
(cntr[5:0]==6'h3f),
ac_in[11:0]}};
was_nonzero_AC <= en && (ac_in[11:0]!=12'b0) && DCACen;
if (pre_dv) do <= rll_out? {3'b0,val_r[12],6'b0,rll_cntr[5:0]}:{1'b1,val_r[14:0]};
dv <= pre_dv;
DCACen <= en && (pre_DCACen || (DCACen && (cntr[5:0]!=6'h3f))); // adjust
if (!DCACen) cntr[5:0] <=6'b0;
else cntr[5:0] <=cntr[5:0]+1;
end
always @ (posedge clk) begin
zdi_d[12:0] <= zdi[12:0];
ac_in[11:0] <= (zdi_d[12]==zdi_d[11])? zdi_d[11:0]:{~zdi_d[11],{11{zdi_d[11]}}}; // always // delay + saturation
if (DC_tosend || !izero || !DCACen) rll_cntr[5:0] <= 6'h0;
else if (DCACen) rll_cntr[5:0] <= rll_cntr[5:0] +1 ;
if (DC_tosend) last <= lasto;
end
// DC components
always @ (posedge clk) begin
zds_d[3:0] <= {zds_d[2:0], zds};
if (zds_d[0]) dc_diff0[12:0] <= comp_firsto?13'b0:dc_mem[comp_numbero[2:0]];
if (zds_d[1]) dc_diff [12:0] <= zdi_d[12:0]-dc_diff0[12:0];
if (zds_d[2]) dc_restored[12:0] <= dc_diff0[12:0] + {dc_diff_limited[11],dc_diff_limited[11:0]};
if (zds_d[3]) dc_mem[comp_numbero[2:0]] <= dc_restored[12:0];
end
// Generate output stream to facilitate huffman encoding. The data will go to FIFO (16x) to compensate for possible long Huffman codes
// and/or zero-byte insertions
// format:
// {2'b11, color,last block, dc[11:0]} - DC data
// {2'b10, 1'b0, last coeff, ac[11:0]} - AC data (last coeff is set if it is last- 63-rd AC coefficient)
// {2'h00, 2'b00, 6'b0,rll[ 5:0]} - RLL zeroes.
// {2'h00, 2'b01, 6'b0,rll[ 5:0]} - end of block. lower 6 bits will have length that should be ignored
endmodule
/*
** -----------------------------------------------------------------------------**
** extjtag.v
**
** GPIO control
**
** Copyright (C) 2007 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
/*
Control programming of external FPGA on the sensor/sensor multiplexor board
Mulptiplex status signals into a single line
bits:
31:20 - not used
19:16 - 0xb..0xf - no changes
- 0xa - select xfpgadone
- 0x9 - select xfpgatdo
- 0x8 - select senspgmin (default)
- 0x0..0x7 - no changes
15:10 - not used
9: 8 - 3 - set xpgmen,
- 2 - reset xpgmen,
- 0, 1 - no changes to xpgmen
7: 6 - 3 - set xfpgaprog,
- 2 - reset xfpgaprog,
- 0, 1 - no changes to xfpgaprog
5: 4 - 3 - set xfpgatck,
- 2 - reset xfpgatck,
- 0, 1 - no changes to xfpgatck
3: 2 - 3 - set xfpgatms,
- 2 - reset xfpgatms,
- 0, 1 - no changes to xfpgatms
1: 0 - 3 - set xfpgatdi,
- 2 - reset xfpgatdi,
- 0, 1 - no changes to xfpgatdi
*/
module extjtag (sclk, // @negedge
pre_wen, // 1 cycle ahead of write data
di, // [31:0] data in (only some bits are used)
xpgmen, // enable programming mode for an external FPGA
xfpgaprog, // PROG_B to be sent to an external FPGA
xfpgatck, // TCK to be sent to an external FPGA
xfpgatms, // TMS to be sent to an external FPGA
xfpgatdi, // TDI to be sent to an external FPGA
senspgmin, // state of the SENSPGM I/O pin (read)
xfpgadone, // state of the MRST pin ("DONE" pin on an external FPGA)
xfpgatdo, // TDO read from an external FPGA
state); // multiplexed state (one of 3 inputs)
input sclk;
input pre_wen;
input [31:0] di;
output xpgmen; // enable programming mode for an external FPGA
output xfpgaprog; // PROG_B to be sent to an external FPGA
output xfpgatck; // TCK to be sent to an external FPGA
output xfpgatms; // TMS to be sent to an external FPGA
output xfpgatdi;
input senspgmin;
input xfpgadone;
input xfpgatdo; // TDO read from an external FPGA
output state;
// reg wen;
wire wen= pre_wen;
wire [1:0] mux; // select source for state, initilaized to
wire xpgmen;
wire xfpgaprog;
wire xfpgatck;
wire xfpgatms;
wire xfpgatdi;
wire state=mux[1]?(mux[0]?1'b0:xfpgadone):(mux[0]?xfpgatdo:senspgmin);
/*
always @ (negedge sclk) begin
wen <= pre_wen;
end
*/
FDE_1 i_mux_0 (.C(sclk), .CE(wen & di[19]), .D(di[16]), .Q(mux[0]));
FDE_1 i_mux_1 (.C(sclk), .CE(wen & di[19]), .D(di[17]), .Q(mux[1]));
FDE_1 i_xpgmen (.C(sclk), .CE(wen & di[9]), .D(di[8]), .Q(xpgmen));
FDE_1 i_xfpgaprog (.C(sclk), .CE(wen & di[7]), .D(di[6]), .Q(xfpgaprog));
FDE_1 i_xfpgatck (.C(sclk), .CE(wen & di[5]), .D(di[4]), .Q(xfpgatck));
FDE_1 i_xfpgatms (.C(sclk), .CE(wen & di[3]), .D(di[2]), .Q(xfpgatms));
FDE_1 i_xfpgatdi (.C(sclk), .CE(wen & di[1]), .D(di[0]), .Q(xfpgatdi));
endmodule
camsync.v
clkios353.v
cmd_sequencer.v
color_proc353.v
compressor333.v
csconvert18.v
csconvert_mono.v
ddr_parameters.v
ddr.v
descrproc353.v
dma_fifo353.v
encoderDCAC353.v
extjtag.v
files.list
focus_sharp.v
glbl.v
histogram353.v
huffman333.v
huffman.dat
i2c_writeonly.v
imu_logger.v
interrupts_vector333.v
ioports353.v
irq_smart.v
linear1028rgb.dat
macros353.v
mcontr353.v
quantization_100.dat
quantizator353.v
rtc353.v
sdram_phase.v
sdseq353.v
sensdcclk333.v
sensor12bits.v
sensor.dat
sensorpads353.v
sensor_phase.v
sensorpix353.v
stuffer333.v
twelve_ios.v
x353_1.sav
x353_1.tf
x353.bit
x353_map.mrp
x353_pad.txt
x353.par
x353_sim.sh
x353.syr
x353.ucf
x353.v
xdct353.v
0000 0111 0444 0888 0fff 0fff 0888 0000
0111 0111 0444 0888 0fff 0fff 0888 0000
0444 0444 0888 0fff 0fff 0888 0444 0000
0888 0888 0fff 0fff 0888 0444 0222 0000
0fff 0fff 0fff 0888 0444 0222 0111 0000
0fff 0fff 0888 0444 0222 0111 0000 0000
0888 0888 0444 0222 0111 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
0000 1111 4444 8888 ffff ffff 8888 0000
1111 1111 4444 8888 ffff ffff 8888 0000
4444 4444 8888 ffff ffff 8888 4444 0000
8888 8888 ffff ffff 8888 4444 2222 0000
ffff ffff ffff 8888 4444 2222 1111 0000
ffff ffff 8888 4444 2222 1111 0000 0000
8888 8888 4444 2222 1111 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000
/*
** -----------------------------------------------------------------------------**
** focus_sharp.v
**
** Module to determine focus sharpness on by integrating
** DCT coefficient, multiplied my 8x8 array and squared
**
** Copyright (C) 2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
`timescale 1ns/1ps
//TODO: Modify to work with other modes (now only on color)
module focus_sharp(clk, // pixel clock
en, // enable (0 resets counter)
sclk, // system clock, twe, ta,tdi - valid @negedge (ra, tdi - 2 cycles ahead
twe, // enable write to a table
ta, // [9:0] table address
tdi, // [15:0] table data in (8 LSBs - quantization data)
mode, // focus mode (combine image with focus info) - 0 - none, 1 - replace, 2 - combine all, 3 - combine woi
firsti, // first macroblock
lasti, // last macroblock
tni, // block number in a macronblock - 0..3 - Y, >=4 - color (sync to stb)
stb, // strobe that writes ctypei, dci
start,// marks first input pixel (needs 1 cycle delay from previous DCT stage)
di, // [11:0] pixel data in (signed)
quant_ds, //quantizator ds
quant_d, //[11:0]quantizator data output
quant_dc_tdo, //[15:0], MSB aligned coefficient for the DC component (used in focus module)
// quant_dc_tdo_stb,
do, // [11:0] pixel data out, make timing ignore (valid 1.5 clk earlier that Quantizer output)
ds, // data out strobe (one ahead of the start of dv)
hifreq //[31:0]) // accumulated high frequency components in a frame sub-window
);
input clk;
input en;
input sclk;
input twe;
input [ 9:0] ta;
input [15:0] tdi;
input [ 1:0] mode;
input firsti; // first macroblock (sync to stb)
input lasti; // last macroblock (sync to stb)
input [ 2:0] tni; // block number in a macronblock - 0..3 - Y, >=4 - color (sync to stb)
input stb; // strobe that writes ctypei, dci
input start;
input [12:0] di;
input quant_ds;
input [12:0] quant_d;
input [15:0] quant_dc_tdo; // MSB aligned coefficient for the DC component (used in focus module)
// input quant_dc_tdo_stb;
output[12:0] do;
output ds;
output [31:0] hifreq;
wire [15:0] tdo;
reg [ 5:0] tba;
reg [11:0] wnd_reg; // intermediate register
reg wnd_wr; // writing window
reg [ 2:0] wnd_a; // window register address
// next measured in 8x8 blocks, totalwidth - write one less than needed (i.e. 511 fro the 512-wide window)
// blocks on the border are included
reg [ 8:0] wnd_left;
reg [ 8:0] wnd_right;
reg [ 8:0] wnd_top;
reg [ 8:0] wnd_bottom;
reg [ 8:1] wnd_totalwidth;
reg [ 3:0] filt_sel0; // select filter number, 0..14 (15 used for window parameters)
reg [ 3:0] filt_sel; // select filter number, 0..14 (15 used for window parameters)
reg stren; // strength (visualization)
// if (dcc_stb) dcc_first <= color_first && dcc_run && dcc_stb && ctype && !ctype_prev[0];
reg [ 2:0] ic;
reg [ 2:0] oc;
wire first,last; //valid at start (with first di word), switches immediately after
wire [ 2:0] tn;
reg [31:0] hifreq;
reg [39:0] acc_frame;
// reg [11:0] do; // combined quantizator/focus output
reg [12:0] do; // combined quantizator/focus output
reg [12:0] pre_do;
reg pre_ds;
reg need_corr_max; // limit output by quant_dc_tdo
reg [11:0] fdo; // focus data output
reg ds;
reg start_d; //start delayed by 1
reg [ 2:0] tn_d; //tn delayed by 1
wire out_mono;
wire out_window;
wire [12:0] combined_qf;
wire [12:0] next_do;
wire [12:0] fdo_minus_max;
reg [11:0] di_d;
reg [11:0] d1;
// reg [9:0] start2;
reg [8:0] start2;
// reg [8:0] finish2;
reg [7:0] finish2;
reg [5:0] use_k_dly;
reg [23:0] acc_blk; // accumulator for the sum ((a[i]*d[i])^2)
reg [22:0] sum_blk; // accumulator for the sum ((a[i]*d[i])^2), copied at block end
reg acc_ldval; // value to load to acc_blk: 0 - 24'h0, 1 - 24'h7fffff
wire acc_clear=start2[8];
wire acc_add=use_k_dly[4];
wire acc_corr=use_k_dly[5];
// wire use_prod=use_k_dly[2] ;// feed multiplier input regs with the delayed product
wire acc_to_out=finish2[6];
wire [17:0] mult_a;
wire [17:0] mult_b;
wire [35:0] mult_p;
reg [17:0] mult_s; //truncated and saturated (always positive) multiplier result (before calculating squared)
reg next_ac; // next will be AC component
reg use_coef; // use multiplier for the first operation - DCT coeff. by table elements
reg started_luma;// started Luma block
reg luma_dc_out; // 1 cycle ahead of the luma DC component out (optionally combined with the WOI (mode=3))
reg luma_dc_acc; // 1 cycle ahead of the luma DC component out (always combined with the WOI)
reg was_last_luma;
reg copy_acc_frame;
assign fdo_minus_max[12:0]= {1'b0,fdo[11:0]}-{1'b0,quant_dc_tdo[15:5]};
/*
assign combined_qf[12:0]=stren?({quant_d[11],quant_d[11:0]}+{1'b0,fdo[11:0]}): //original image plus positive
({quant_d[11],quant_d[11],quant_d[11:1]}+ // half original
{fdo_minus_max[12],fdo_minus_max[12:1]}); // plus half signed
assign next_do[12:0] = (mode[1:0]==2'h1)?(luma_dc_out?fdo_minus_max[12:0]:13'h0):
((mode[1] && luma_dc_out )? combined_qf[12:0]: {1'b0,quant_d[11:0]} );
*/
assign combined_qf[12:0]=stren?({quant_d[12:0]}+{1'b0,fdo[11:0]}): //original image plus positive
({quant_d[12],quant_d[12:1]}+ // half original
{fdo_minus_max[12],fdo_minus_max[12:1]}); // plus half signed
assign next_do[12:0] = (mode[1:0]==2'h1)?(luma_dc_out?fdo_minus_max[12:0]:13'h0):
((mode[1] && luma_dc_out )? combined_qf[12:0]: {quant_d[12:0]} );
always @ (posedge clk) begin
if (!en) ic[2:0] <= 3'b0;
else if (stb) ic[2:0] <= ic[2:0]+1;
if (!en) oc[2:0] <= 3'b0;
else if (start) oc[2:0] <= oc[2:0]+1;
end
// writing window parameters in the last bank of a table
always @ (negedge sclk) begin
if (twe) begin
wnd_reg[11:0] <= tdi[11:0] ;
wnd_a <= ta[2:0];
end
wnd_wr <= twe && (ta[9:3]==7'h78) ; // first 8 location in the last 64-word bank
if (wnd_wr) begin
case (wnd_a[2:0])
3'h0: wnd_left[8:0] <= wnd_reg[11:3] ;
3'h1: wnd_right[8:0] <= wnd_reg[11:3] ;
3'h2: wnd_top[8:0] <= wnd_reg[11:3] ;
3'h3: wnd_bottom[8:0] <= wnd_reg[11:3] ;
3'h4: wnd_totalwidth[8:1] <= wnd_reg[11:4] ;
3'h5: filt_sel0[3:0] <= wnd_reg[3:0] ;
3'h6: stren <= wnd_reg[0] ;
endcase
end
end
// determine if this block needs to be processed (Y, inside WOI)
reg [ 7:0] mblk_hor; //horizontal macroblock (2x2 blocks) counter
reg [ 7:0] mblk_vert; //vertical macroblock (2x2 blocks) counter
wire start_of_line= (first || (mblk_hor[7:0] == wnd_totalwidth[8:1]));
wire first_in_macro= (tn[2:0]==3'h0);
reg in_woi; // maybe specified as slow
always @(posedge clk) begin
if (first_in_macro && start) mblk_hor[7:0] <= start_of_line? 8'h0:(mblk_hor[7:0]+1);
if (first_in_macro && start && start_of_line) mblk_vert[7:0] <= first? 8'h0:(mblk_vert[7:0]+1);
start_d <= start;
tn_d[2:0] <= tn[2:0];
if (start_d) in_woi <= !tn_d[2] &&
({mblk_hor [7:0],tn_d[0]} >= wnd_left[8:0]) &&
({mblk_hor [7:0],tn_d[0]} <= wnd_right[8:0]) &&
({mblk_vert[7:0],tn_d[1]} >= wnd_top[8:0]) &&
({mblk_vert[7:0],tn_d[1]} <= wnd_bottom[8:0]);
end
//Will use posedge sclk to balance huffman and system
wire clkdiv2;
FD i_clkdiv2(.C(clk), .D(!clkdiv2), .Q(clkdiv2));
reg [2:0] clksync;
wire csync=clksync[2];
always @ (posedge sclk) begin
clksync[2:0] <= {(clksync[1]==clksync[0]),clksync[0],clkdiv2};
end
always @ (posedge clk) begin
if (di[11]==di[12]) di_d[11:0] <=di[11:0];
else di_d[11:0] <= {~di[11],{11{di[11]}}}; //saturate
end
assign mult_a[17:0] = use_coef ? {1'b0,tdo[15:0],1'b0}: mult_s[17:0];
assign mult_b[17:0] = use_coef ? {d1[10:0],{7{d1[0]}}}: mult_s[17:0];
always @ (posedge sclk) begin
filt_sel[3:0] <= filt_sel0[3:0];
if (clksync[2]) d1[11:0]<=di_d[11:0];
// start2[9:0] <= {start2[8:0], start && csync};
start2[8:0] <= {start2[7:0], start && csync};
// finish2[8:0]<= {finish2[7:0],use_coef && !next_ac};
finish2[7:0]<= {finish2[6:0],use_coef && !next_ac};
if (!en || start2[0]) tba[5:0] <= 6'h0;
else if (!csync && (tba[5:0] != 6'h3f)) tba[5:0] <= tba[5:0] + 1;
mult_s[17:0] <= (&mult_p[35:31] || !(&mult_p[35:31]))?mult_p[31:14]:18'h1ffff;
next_ac <= en && (start2[3] || (next_ac && ((tba[5:0] != 6'h3f) || csync )));
use_coef <= next_ac && !csync;
use_k_dly[5:0]<={use_k_dly[4:0],use_coef};
acc_ldval <= !(|start2[7:6]);
if (acc_clear || (acc_corr && acc_blk[23])) acc_blk[23:0] <= {1'b0,{23{acc_ldval}}};
else if (acc_add) acc_blk[23:0] <= acc_blk[23:0]+mult_p[35:8];
if (acc_to_out) fdo[11:0] <= (|acc_blk[23:20])?12'hfff:acc_blk[19:8]; // positive, 0..0xfff
if (acc_to_out) sum_blk[22:0] <= acc_blk[22:0]; // accumulator for the sum ((a[i]*d[i])^2), copied at block end
end
// acc_blk will (after corr) be always with MSB=0 - max 24'h7fffff
// for image output - max 24'h0fffff->12 bit signed, shifted
// combining output
//assign combined_qf[12:0]={quant_d[11],quant_d[11:0]}+{fdo[11],fdo[11:0]};
SRL16 i_out_mono (.Q(out_mono), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b1), .CLK(clk), .D(started_luma)); // timing not critical
SRL16 i_out_window (.Q(out_window), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b1), .CLK(clk), .D(in_woi)); // timing not critical
always @ (posedge clk) begin
if (start) started_luma <= !tn[2];
luma_dc_out <= quant_ds && out_mono && ((mode[1:0]!=3) || out_window);
luma_dc_acc <= quant_ds && out_mono && out_window;
was_last_luma <= en && last && out_mono;
copy_acc_frame <= was_last_luma && !out_mono;
if (first && first_in_macro) acc_frame[39:0] <= 40'h0;
else if (luma_dc_acc) acc_frame[39:0] <= acc_frame[39:0] + sum_blk[22:0];
if (copy_acc_frame) hifreq[31:0] <= acc_frame[39:8];
pre_ds <= quant_ds;
ds <= pre_ds;
pre_do[12:0] <= next_do[12:0];
need_corr_max <=luma_dc_out && (mode[1:0]!=2'h0);
/* do[11:0] <= (need_corr_max && !pre_do[12] && (pre_do[11] || (pre_do[10:0]>quant_dc_tdo[15:5])) )?
{1'b0,quant_dc_tdo[15:5]} :
pre_do[11:0];
*/
do[12:0] <= (need_corr_max && !pre_do[12] && (pre_do[11] || (pre_do[10:0]>quant_dc_tdo[15:5])) )?
{2'b0,quant_dc_tdo[15:5]} :
pre_do[12:0];
end
MULT18X18SIO #(
.AREG(1), // Enable the input registers on the A port (1=on, 0=off)
.BREG(1), // Enable the input registers on the B port (1=on, 0=off)
.B_INPUT("DIRECT"), // B cascade input "DIRECT" or "CASCADE"
.PREG(1) // Enable the input registers on the P port (1=on, 0=off)
) i_focus_mult (
.BCOUT(), // 18-bit cascade output
.P(mult_p), // 36-bit multiplier output
.A(mult_a), // 18-bit multiplier input
.B(mult_b), // 18-bit multiplier input
.BCIN(18'h0), // 18-bit cascade input
.CEA(en), // Clock enable input for the A port
.CEB(en), // Clock enable input for the B port
.CEP(en), // Clock enable input for the P port
.CLK(sclk), // Clock input
.RSTA(1'b0), // Synchronous reset input for the A port
.RSTB(1'b0), // Synchronous reset input for the B port
.RSTP(1'b0) // Synchronous reset input for the P port
);
RAM16X1D i_tn0 (.D(tni[0]),.DPO(tn[0]),.A0(ic[0]),.A1(ic[1]),.A2(1'b0),.A3(1'b0),.DPRA0(oc[0]),.DPRA1(oc[1]),.DPRA2(1'b0),.DPRA3(1'b0),.WCLK(clk),.WE(stb));
RAM16X1D i_tn1 (.D(tni[1]),.DPO(tn[1]),.A0(ic[0]),.A1(ic[1]),.A2(1'b0),.A3(1'b0),.DPRA0(oc[0]),.DPRA1(oc[1]),.DPRA2(1'b0),.DPRA3(1'b0),.WCLK(clk),.WE(stb));
RAM16X1D i_tn2 (.D(tni[2]),.DPO(tn[2]),.A0(ic[0]),.A1(ic[1]),.A2(1'b0),.A3(1'b0),.DPRA0(oc[0]),.DPRA1(oc[1]),.DPRA2(1'b0),.DPRA3(1'b0),.WCLK(clk),.WE(stb));
RAM16X1D i_first (.D(firsti),.DPO(first),.A0(ic[0]),.A1(ic[1]),.A2(1'b0),.A3(1'b0),.DPRA0(oc[0]),.DPRA1(oc[1]),.DPRA2(1'b0),.DPRA3(1'b0),.WCLK(clk),.WE(stb));
RAM16X1D i_last (.D(lasti), .DPO(last), .A0(ic[0]),.A1(ic[1]),.A2(1'b0),.A3(1'b0),.DPRA0(oc[0]),.DPRA1(oc[1]),.DPRA2(1'b0),.DPRA3(1'b0),.WCLK(clk),.WE(stb));
RAMB16_S18_S18 i_focus_dct_tab (
.DOA(tdo[15:0]), // Port A 16-bit Data Output
.DOPA(), // Port A 2-bit Parity Output
.ADDRA({filt_sel[3:0],tba[2:0],tba[5:3]}), // Port A 10-bit Address Input
.CLKA(sclk), // Port A Clock
.DIA(16'b0), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.DOB(), // Port B 16-bit Data Output
.DOPB(), // Port B 4-bit Parity Output
.ADDRB({ta[9:0]}), // Port B 2-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB(tdi[15:0]), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(1'b1), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(twe) // Port B Write Enable Input
);
endmodule
// $Header: /cvsroot/elphel/elphel353-8.0/fpga/x3x3/glbl.v,v 1.1.1.1 2008/11/27 20:04:02 elphel Exp $
`timescale 1 ps / 1 ps
module glbl ();
parameter ROC_WIDTH = 100000;
parameter TOC_WIDTH = 0;
wire GSR;
wire GTS;
wire PRLD;
reg GSR_int;
reg GTS_int;
reg PRLD_int;
assign (weak1, weak0) GSR = GSR_int;
assign (weak1, weak0) GTS = GTS_int;
assign (weak1, weak0) PRLD = PRLD_int;
initial begin
GSR_int = 1'b1;
PRLD_int = 1'b1;
#(ROC_WIDTH)
GSR_int = 1'b0;
PRLD_int = 1'b0;
end
initial begin
GTS_int = 1'b1;
#(TOC_WIDTH)
GTS_int = 1'b0;
end
endmodule
$GPRMC,042931.0,A,4043.39929,N,11155.92706,W,000.00,283.8,250411,013.2,E*45
$GPGGA,042931.0,4043.39929,N,11155.92706,W,1,09,0.8,1280.5,M,-13.8,M,,*5B
$GPGSA,A,3,04,07,08,11,15,17,24,26,27,,,,1.7,0.8,1.5*36
$GPVTG,283.8,T,270.5,M,000.00,N,0000.00,K*7F
$GPRMC,042931.2,A,4043.39929,N,11155.92705,W,000.01,283.8,250411,013.2,E*45
$GPGGA,042931.2,4043.39929,N,11155.92705,W,1,09,0.8,1280.5,M,-13.8,M,,*5A
$GPGSA,A,3,04,07,08,11,15,17,24,26,27,,,,1.7,0.8,1.5*36
$GPVTG,283.8,T,270.5,M,000.01,N,0000.01,K*7F
$GPRMC,042931.4,A,4043.39929,N,11155.92705,W,000.01,283.8,250411,013.2,E*43
$GPGGA,042931.4,4043.39929,N,11155.92705,W,1,09,0.8,1280.5,M,-13.8,M,,*5C
$GPGSA,A,3,04,07,08,11,15,17,24,26,27,,,,1.7,0.8,1.5*36
$GPVTG,283.8,T,270.5,M,000.01,N,0000.02,K*7C
$GPRMC,042931.6,A,4043.39929,N,11155.92705,W,000.00,283.8,250411,013.2,E*40
$GPGGA,042931.6,4043.39929,N,11155.92705,W,1,09,0.8,1280.5,M,-13.8,M,,*5E
$GPGSA,A,3,04,07,08,11,15,17,24,26,27,,,,1.7,0.8,1.5*36
$GPVTG,283.8,T,270.5,M,000.00,N,0000.00,K*7F
$GPRMC,042931.8,A,4043.39929,N,11155.92705,W,000.01,283.8,250411,013.2,E*4F
$GPGGA,042931.8,4043.39929,N,11155.92705,W,1,09,0.8,1280.5,M,-13.8,M,,*50
$GPGSA,A,3,04,07,08,11,15,17,24,26,27,,,,1.7,0.8,1.5*36
$GPVTG,283.8,T,270.5,M,000.01,N,0000.01,K*7F
/*
** -----------------------------------------------------------------------------**
** histogram.v
**
** Calculation of image histograms
**
** Copyright (C) 2005-2010 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 histogram (pclk, // pixel clock (posedge, only some input signals
pclk2x, // pclk multiplied by 2
sclk, // global (commands @negedge)
wen, // @negedge sclk, 1 ahead of write enable/read enable
rnext, // read histogram, increment address
wa, // [2:0] register address:
// old - 00 - {top, left}
// old - 01 - {height-1, width-1}
// old - 02 - hist. data start address (will also read pointed word to output word
// 00 - left
// 01 - top
// 02 - width-1
// 03 - height-1
// 04 - hist. data start address (will also read pointed word to output word
hist_do, // [31:0] histogram data (actually now just [17:0])
// 256*R, 256*Gr, 256*Gb, 256*B
wd, // [31:0] PIO data to write
frame_run, // frame active - @posedge pclk
line_run_a, // hact_out @posedge pclk
di_a, // [15:0] @posedge pclk
di_vld_a, // di[15:0] valid @posedge pclk
bayer_phase // [1:0]
);
input pclk;
input pclk2x;
input sclk;
input wen;
input rnext;
input [ 2:0] wa;
output [31:0] hist_do;
// input [15:0] wd;
input [15:0] wd;
input frame_run;
input line_run_a;
input [15:0] di_a;
input di_vld_a;
input [ 1:0] bayer_phase;
wire [17:0] hist_do0;
// extra layer of registers
reg line_run;
reg [15:0] di;
reg pre_di_vld, di_vld;
always @(posedge pclk) begin
line_run <= line_run_a;
di[15:0] <= di_a[15:0];
// di_vld <= di_vld_a;
end
always @ (posedge pclk2x) begin
pre_di_vld <= di_vld_a;
di_vld <= pre_di_vld; // so di_vld can be duplicated
end
// In Model 353 switching to 2x multipled pixel clock without it did not work when sclk < 2 * pclk
// pixels always go in pairs (low/high byte of di)
reg [15:0] di2x;
reg [ 3:0] dvld2x; // dvld2x[0] is valid second half di_vld, dvld2x[1] - 1 pclk2x cycle later, dvld2x[2] - 2 cycles
reg [ 1:0] bayer;
reg [ 1:0] bayer_phase_latched;
reg [ 9:0] hist_waddr; // histogram memory address (write side) - {color,pixel_value}
reg [ 9:0] hist_waddr_hold1; // hist_waddr - first hold register (latency read-increment-write)
reg [ 9:0] hist_waddr_hold2; // hist_waddr - second hold register (latency read-increment-write)
reg same_waddr; // same pixel value (use previous result instead of memory as it is not written yet)
reg pre_same_addr;
reg [ 2:0] frame_run_s;
reg [ 2:0] line_run_s;
reg line_start,line_end;
reg frame_start;
// reg frame_end;
reg [ 5:0] hist_seq; // delay line for the histogram calculation sequencer (each other bit can be active)
reg [ 9:0] hist_init_cntr;
reg end_hist_init;
reg [17:0] hist_pre; // previous value of the histogram - before increment
reg [17:0] hist_post; // new value of the histogram - after increment
wire hist_bank; // use FD so it will be reset at power up for simulation
reg odd_line;
reg [13:1] pix_cntr;
reg [13:1] line_cntr;
reg line_started, // left margin over
line_ended; // right margin
reg frame_started;// top margin over
reg frame_ended; // bottom margin
// reg frame_ended_d;
reg init_hist; // write zeros to all hist elements.
reg init_hist_d;
reg window_on; // window active
// increased dimesions to 8K
reg [13:1] pos_left; // all dimensions will be even (to simplify processing pixel data packed in pairs)
reg [13:1] pos_top;
reg [13:1] size_width;
reg [13:1] size_height;
reg [1:0] we_pos;
reg [1:0] we_size;
reg we_addr;
reg we_addr_d;
// reg rd_hist;
wire rd_hist;
reg [ 9:0] hist_raddr; // histogram memory address (read side) - {color,pixel_value}
reg hist_wea;
reg hist_ena;
reg bayer_en; // enable latching bayer
reg last_line;
wire [17:0] hist_doa; // RAM output
wire [17:0] hist_dia= hist_post[17:0]; // RAM input
reg [15:0] wdd; // wd[15:0] delayed by 1 clock
reg [13:1] minus_pos_left; // TIG
reg pos_left_is_zero; // TIG
reg line_start_posl_zero; // start with pos_left_is_zero
reg line_start_posl_nzero; // start with !pos_left_is_zero
assign rd_hist = rnext || we_addr_d;
assign hist_do[31:0]={14'h0,hist_do0[17:0]};
/*
//debug
reg [9:0] test_cntr;
always @ (posedge pclk2x) if (frame_run_s[1] && !frame_run_s[2]) begin
test_cntr[9:0] <= test_cntr[9:0]+1;
end
assign hist_do[31:0]={1'h0,frame_run_s[1],hist_bank,test_cntr[9:0],frame_run,hist_do0[17:0]}; /// Temporary testing !!!
// assign hist_do[31:0]={1'h0,hist_bank,hist_raddr[9:0],2'h0,hist_do0[17:0]}; /// Temporary testing !!!
*/
// FDE i_hist_bank (.C(pclk2x), .CE(frame_end), .D(~hist_bank), .Q(hist_bank));
// switch bank at the start of frame
FDE i_hist_bank (.C(pclk2x), .CE(init_hist & ~init_hist_d), .D(~hist_bank), .Q(hist_bank));
always @ (posedge pclk2x) begin
frame_run_s[2:0] <= {frame_run_s[1:0],frame_run};
line_run_s[2:0] <= {line_run_s[1:0], line_run};
line_start <= line_run_s[1] && !line_run_s[2];
line_start_posl_zero <= line_run_s[1] && !line_run_s[2] && pos_left_is_zero;
line_start_posl_nzero <= line_run_s[1] && !line_run_s[2] && !pos_left_is_zero;
line_end <= line_run_s[2] && !line_run_s[1];
frame_start <= frame_run_s[1] && !frame_run_s[2];
// frame_end <= (frame_ended && !frame_ended_d);
bayer_en <= frame_start || (bayer_en && !line_start);
if (bayer_en) bayer_phase_latched[1:0] <=bayer_phase[1:0];
if (!frame_run_s[2]) hist_init_cntr[9:0] <= 10'b0;
else if (init_hist) hist_init_cntr[9:0] <= hist_init_cntr[9:0] + 1;
end_hist_init <= (hist_init_cntr[9:1]==9'h1ff);
init_hist <= frame_run_s[1] && (init_hist?(~end_hist_init):~frame_run_s[2]);
init_hist_d <= init_hist;
if (!init_hist) hist_init_cntr[9:0] <= 10'h0;
else hist_init_cntr[9:0] <= hist_init_cntr[9:0] + 1;
dvld2x[3:0] <= {dvld2x[2:0], ~(|dvld2x[2:0]) & di_vld };
// include window_on (don't start if not)
// hist_seq[5:0] <= {hist_seq[4:0], dvld2x[1] | dvld2x[3]};
hist_seq[5:0] <= {hist_seq[4:0], window_on && (dvld2x[1] | dvld2x[3])};
hist_ena <= hist_seq[0] || hist_seq[5] || init_hist; // read, write, clear
hist_wea <= hist_seq[5] || init_hist; // write, clear
// get 8-bit pixels from 16-bit packed words
if (dvld2x[0]) di2x[15:8] <= di[15:8];
if (dvld2x[0]) di2x[ 7:0] <= di[ 7:0];
else if (dvld2x[2]) di2x[ 7:0] <= di2x[15:8];
// calculate bayer phase of the pixel
// reg [ 1:0] bayer_phase_latched;
// if (dvld2x[0]) bayer[0] <= bayer_phase[0];
if (dvld2x[0]) bayer[0] <= 1'b0;
else if (dvld2x[2]) bayer[0] <= ~bayer[0];
// if (frame_start) bayer[1] <= bayer_phase[1];
if (frame_start) bayer[1] <= 1'b0;
else if (line_start) bayer[1] <= ~bayer[1];
if (hist_seq[1]) hist_waddr_hold1[9:0] <= hist_waddr[9:0];
if (hist_seq[3]) hist_waddr_hold2[9:0] <= hist_waddr_hold1[9:0];
// we need to clear all histogram at the begining of a frame (will not work if the window is too small)
if (init_hist) hist_waddr[9:0] <= hist_init_cntr[9:0]; // to clear histogram memory
else if (hist_seq[0]) hist_waddr[9:0] <= {bayer[1:0]^bayer_phase_latched[1:0],di2x[7:0]};
else if (hist_seq[5]) hist_waddr[9:0] <= {hist_waddr_hold2[9:0]};
/* same_waddr <= hist_seq[0] && // next cycle - read from memory
hist_seq[4] && // second next cycle - write modified
(di2x[7:0] == hist_waddr_hold2[7:0]); // same address (colors should be the same - same line, over one pixel)
*/
pre_same_addr <= (di2x[7:0] == hist_waddr_hold2[7:0]);
same_waddr <= hist_seq[1] && // next cycle - read from memory
hist_seq[5] && // second next cycle - write modified
pre_same_addr;
if (hist_seq[2]) hist_pre[17:0] <= same_waddr? hist_post[17:0] : hist_doa[17:0]; // bypass memory for the same histogram count/color
// hist_pre[17:0] -> hist_post[17:0] - dual cycle
// data to write to histogram memory
if (init_hist) hist_post[17:0] <= 18'h0; // to write 0 to all histogram page memory locations
else if (hist_seq[4] && (hist_pre[17:0]!=18'h3ffff)) hist_post[17:0] <= hist_pre[17:0] + 1; // saturate
// odd/even scan lines
if (frame_start) odd_line <= 1'b1;
else if (line_end) odd_line <= ~odd_line;
minus_pos_left[13:1] <= -pos_left[13:1]; // TIG
pos_left_is_zero <= (pos_left[13:1]==13'h0); // TIG
// count pixels (in pairs) to determine active window
// if (line_start) pix_cntr[13:1] <= ~pos_left[13:1];
// else if (dvld2x[1]) pix_cntr[13:1] <= pix_cntr[13:1]+1; // window_on will switch right after dvld2x[3]
if (line_start) pix_cntr[13:1] <= minus_pos_left[13:1]; // @dvld2x[0]
else if (dvld2x[0]) pix_cntr[13:1] <= pix_cntr[13:1]+1; // (may change to dvld2x[2])window_on will switch right after dvld2x[3]
if (line_start_posl_nzero || !frame_run_s[2]) line_started <= 1'h0;
else if (line_start_posl_zero || (dvld2x[2] &&((~pix_cntr[13:1])== 13'h0))) line_started <= 1'h1; // Doublecycle
if (line_start || !frame_run_s[2]) line_ended <= 1'h0;
else if (dvld2x[2] && line_started && (pix_cntr[13:1] == size_width[13:1])) line_ended <= 1'h1; // Doublecycle
if (frame_start) line_cntr[13:1] <= ~pos_top[13:1];
else if (line_end && !odd_line) line_cntr[13:1] <= line_cntr[13:1]+1;
if (!frame_run_s[2]) frame_started <= 1'h0;
else if ((~line_cntr[13:1])== 13'h0) frame_started <= 1'h1;
last_line <= (line_cntr[13:1] == size_height[13:1]);
if (!frame_run_s[2]) frame_ended <= 1'h0;
else if ((line_start && frame_started && last_line) || (frame_run_s[2] && ! frame_run_s[1])) frame_ended <= 1'h1;
// frame_ended_d <= frame_ended;
// window_on <= (line_start_posl_zero || line_started) && !line_ended && frame_started && !frame_ended;
window_on <= (line_start_posl_zero || (line_started && !line_ended)) && frame_started && !frame_ended;
end
always @ (negedge sclk) begin
wdd[15:0] <= wd[15:0];
we_pos[1:0] <= {wen && (wa[2:0]==3'h1), wen && (wa[2:0]==3'h0)};
we_size[1:0] <= {wen && (wa[2:0]==3'h3), wen && (wa[2:0]==3'h2)};
we_addr <= wen && (wa[2:0]==3'h4);
we_addr_d <= we_addr;
if (we_pos[0]) pos_left[13:1] <= wdd[13: 1];
if (we_pos[1]) pos_top[13:1] <= wdd[13: 1];
if (we_size[0]) size_width[13:1] <= wdd[13: 1];
if (we_size[1]) size_height[13:1] <= wdd[13: 1];
if (we_addr) hist_raddr[9:0] <= wdd[9:0];
else if (rd_hist) hist_raddr[9:0] <= hist_raddr[9:0] + 1;
end
// port A - histogram calculation
// port B - histogram readout
RAMB16_S9_S9 i_hist_low (
.DOA(hist_doa[7:0]), // Port A 8-bit Data Output
.DOPA(hist_doa[8]), // Port A 1-bit Parity Output
.ADDRA({hist_bank,hist_waddr[9:0]}), // Port A 11-bit Address Input
.CLKA( pclk2x), // Port A Clock
.DIA(hist_dia[7:0]), // Port A 8-bit Data Input
.DIPA(hist_dia[8]), // Port A 1-bit parity Input
.ENA(hist_ena), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(hist_wea), // Port A Write Enable Input
.DOB(hist_do0[7:0]), // Port B 8-bit Data Output
.DOPB(hist_do0[8]), // Port B 1-bit Parity Output
.ADDRB({~hist_bank,hist_raddr[9:0]}), // Port B 11-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB(8'h0), // Port B 8-bit Data Input
.DIPB(1'h0), // Port-B 1-bit parity Input
.ENB(rd_hist), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
RAMB16_S9_S9 i_hist_high (
.DOA(hist_doa[16:9]), // Port A 8-bit Data Output
.DOPA(hist_doa[17]), // Port A 1-bit Parity Output
.ADDRA({hist_bank,hist_waddr[9:0]}), // Port A 11-bit Address Input
.CLKA( pclk2x), // Port A Clock
.DIA(hist_dia[16:9]), // Port A 8-bit Data Input
.DIPA(hist_dia[17]), // Port A 1-bit parity Input
.ENA(hist_ena), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(hist_wea), // Port A Write Enable Input
.DOB(hist_do0[16:9]), // Port B 8-bit Data Output
.DOPB(hist_do0[17]), // Port B 1-bit Parity Output
.ADDRB({~hist_bank,hist_raddr[9:0]}), // Port B 11-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB(8'h0), // Port B 8-bit Data Input
.DIPB(1'h0), // Port-B 1-bit parity Input
.ENB(rd_hist), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
endmodule
04000a 020000 020001 030004 04000b 05001a 070078 0800f8 0a03f6 10ff82 10ff83 000000 000000 000000 000000 020000
000000 04000c 05001b 070079 0901f6 0b07f6 10ff84 10ff85 10ff86 10ff87 10ff88 000000 000000 000000 000000 030002
000000 05001c 0800f9 0a03f7 0c0ff4 10ff89 10ff8a 10ff8b 10ff8c 10ff8d 10ff8e 000000 000000 000000 000000 030003
000000 06003a 0901f7 0c0ff5 10ff8f 10ff90 10ff91 10ff92 10ff93 10ff94 10ff95 000000 000000 000000 000000 030004
000000 06003b 0a03f8 10ff96 10ff97 10ff98 10ff99 10ff9a 10ff9b 10ff9c 10ff9d 000000 000000 000000 000000 030005
000000 07007a 0b07f7 10ff9e 10ff9f 10ffa0 10ffa1 10ffa2 10ffa3 10ffa4 10ffa5 000000 000000 000000 000000 030006
000000 07007b 0c0ff6 10ffa6 10ffa7 10ffa8 10ffa9 10ffaa 10ffab 10ffac 10ffad 000000 000000 000000 000000 04000e
000000 0800fa 0c0ff7 10ffae 10ffaf 10ffb0 10ffb1 10ffb2 10ffb3 10ffb4 10ffb5 000000 000000 000000 000000 05001e
000000 0901f8 0f7fc0 10ffb6 10ffb7 10ffb8 10ffb9 10ffba 10ffbb 10ffbc 10ffbd 000000 000000 000000 000000 06003e
000000 0901f9 10ffbe 10ffbf 10ffc0 10ffc1 10ffc2 10ffc3 10ffc4 10ffc5 10ffc6 000000 000000 000000 000000 07007e
000000 0901fa 10ffc7 10ffc8 10ffc9 10ffca 10ffcb 10ffcc 10ffcd 10ffce 10ffcf 000000 000000 000000 000000 0800fe
000000 0a03f9 10ffd0 10ffd1 10ffd2 10ffd3 10ffd4 10ffd5 10ffd6 10ffd7 10ffd8 000000 000000 000000 000000 0901fe
000000 0a03fa 10ffd9 10ffda 10ffdb 10ffdc 10ffdd 10ffde 10ffdf 10ffe0 10ffe1 000000 000000 000000 000000 000000
000000 0b07f8 10ffe2 10ffe3 10ffe4 10ffe5 10ffe6 10ffe7 10ffe8 10ffe9 10ffea 000000 000000 000000 000000 000000
000000 10ffeb 10ffec 10ffed 10ffee 10ffef 10fff0 10fff1 10fff2 10fff3 10fff4 000000 000000 000000 000000 000000
0b07f9 10fff5 10fff6 10fff7 10fff8 10fff9 10fffa 10fffb 10fffc 10fffd 10fffe 000000 000000 000000 000000 000000
020000 020001 030004 04000a 050018 050019 060038 070078 0901f4 0a03f6 0c0ff4 000000 000000 000000 000000 020000
000000 04000b 060039 0800f6 0901f5 0b07f6 0c0ff5 10ff88 10ff89 10ff8a 10ff8b 000000 000000 000000 000000 020001
000000 05001a 0800f7 0a03f7 0c0ff6 0f7fc2 10ff8c 10ff8d 10ff8e 10ff8f 10ff90 000000 000000 000000 000000 020002
000000 05001b 0800f8 0a03f8 0c0ff7 10ff91 10ff92 10ff93 10ff94 10ff95 10ff96 000000 000000 000000 000000 030006
000000 06003a 0901f6 10ff97 10ff98 10ff99 10ff9a 10ff9b 10ff9c 10ff9d 10ff9e 000000 000000 000000 000000 04000e
000000 06003b 0a03f9 10ff9f 10ffa0 10ffa1 10ffa2 10ffa3 10ffa4 10ffa5 10ffa6 000000 000000 000000 000000 05001e
000000 070079 0b07f7 10ffa7 10ffa8 10ffa9 10ffaa 10ffab 10ffac 10ffad 10ffae 000000 000000 000000 000000 06003e
000000 07007a 0b07f8 10ffaf 10ffb0 10ffb1 10ffb2 10ffb3 10ffb4 10ffb5 10ffb6 000000 000000 000000 000000 07007e
000000 0800f9 10ffb7 10ffb8 10ffb9 10ffba 10ffbb 10ffbc 10ffbd 10ffbe 10ffbf 000000 000000 000000 000000 0800fe
000000 0901f7 10ffc0 10ffc1 10ffc2 10ffc3 10ffc4 10ffc5 10ffc6 10ffc7 10ffc8 000000 000000 000000 000000 0901fe
000000 0901f8 10ffc9 10ffca 10ffcb 10ffcc 10ffcd 10ffce 10ffcf 10ffd0 10ffd1 000000 000000 000000 000000 0a03fe
000000 0901f9 10ffd2 10ffd3 10ffd4 10ffd5 10ffd6 10ffd7 10ffd8 10ffd9 10ffda 000000 000000 000000 000000 0b07fe
000000 0901fa 10ffdb 10ffdc 10ffdd 10ffde 10ffdf 10ffe0 10ffe1 10ffe2 10ffe3 000000 000000 000000 000000 000000
000000 0b07f9 10ffe4 10ffe5 10ffe6 10ffe7 10ffe8 10ffe9 10ffea 10ffeb 10ffec 000000 000000 000000 000000 000000
000000 0e3fe0 10ffed 10ffee 10ffef 10fff0 10fff1 10fff2 10fff3 10fff4 10fff5 000000 000000 000000 000000 000000
0a03fa 0f7fc3 10fff6 10fff7 10fff8 10fff9 10fffa 10fffb 10fffc 10fffd 10fffe 000000 000000 000000 000000 000000
/*
** -----------------------------------------------------------------------------**
** huffman333.v
**
** Huffman encoder for JPEG compressorrdy
**
** Copyright (C) 2002-2004 Elphelk, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// 01/22/2004 - extended flush until ready (modified stuffer.v too)
module huffman (pclk, // half frequency, sync to incoming data
clk, // pixel clock
en, // enable (0 resets) sync to pclk
// cwr, // CPU WR global clock
twe, // enable write to a table - now the following will be valid ant negedge clk
ta, // [8:0] table address
tdi, // [15:0] table data in
// readback, // [23:0] readback data
di, // [15:0] specially RLL prepared 16-bit data (to FIFO) (sync to pclk)
ds, // di valid strobe (sync to pclk)
rdy, // receiver (bit stuffer) is ready to accept data
do, // [15:0] output data
dl, // [3:0] data length (4'h0 is 'h16)
dv, // output data valid
flush, // last block done - flush the rest bits
last_block,
test_lbw,
gotLastBlock
);
input pclk;
input clk;
input en;
// input cwr;
input twe;
input [ 8:0] ta;
input [15:0] tdi;
// output [23:0] readback; // readback data
input [15:0] di;
input ds;
input rdy;
output [15:0] do;
output [ 3:0] dl;
output dv;
output flush;
output last_block;
output test_lbw;
output gotLastBlock;
reg test_lbw;
wire [19:0] tables_out;
wire [15:0] hcode; // table output huffman code (1..16 bits)
wire [ 3:0] hlen; // table - code length only 4 LSBs are used
wire [11:0] unused;
reg [ 7:0] haddr_r; // index in huffman table
wire [ 7:0] haddr_next;
wire [ 8:0] haddr; // index in huffman table (after latches)
wire [15:0] fifo_o;
reg stuffer_was_rdy;
wire tables_re;
wire read_next; // assigned depending on steps (each other cycle for normal codes, each for special 00/F0
reg [5:0] steps;
// first stage registers
reg [5:0] rll; // 2 MSBs - counter to send "f0" codes
// replacing SRL16 with FD as SRL has longer output delay from clock
reg [3:0] rll1;
reg [3:0] rll2;
reg typeDC;
reg typeAC;
reg [11:0] sval; // signed input value
wire [1:0] code_typ0; // valid at steps[0]
reg tbsel_YC0; // valid at steps[0] - 0 -Y table, 1 - CbCr
reg [1:0] code_typ1;
reg [1:0] code_typ2;
reg code_typ3;
reg code_typ4;
reg tbsel_YC1;
reg tbsel_YC2;
reg tbsel_YC3;
reg last_block; //
reg [15:0] out_bits; // bits to send
reg [3:0] out_len; // length of bits to send (4'h0 means 16)
wire fifo_or_full; // fifo output register full read_next
wire will_read;
wire [10:0] var_do;
wire [3:0] var_dl;
wire [3:0] var_dl_late;
//wire dv;
reg dv;
reg dv0;
//reg dv_d; // dv0 delayed
//reg [15:0] out_bits_d; // bits to send (delayed)
//reg [3:0] out_len_d; // length of bits to send (4'h0 means 16) (delayed)
reg flush;
//wire [23:0] readback; // readback data
reg eob;
wire gotDC;
wire gotAC;
wire gotRLL;
wire gotEOB;
wire gotLastBlock;
wire gotLastWord;
wire gotColor;
wire want_read; // as will_read, but w/o fifo status
reg ready_to_flush; // read the last data from fifo
reg en2x; // en sync to clk;
reg [15:0] do;
reg [ 3:0] dl;
wire pre_dv;
wire [15:0] pre_bits;
wire [ 3:0] pre_len;
reg twe_d; // table write enable (twe) delayued by 1 clock
always @ (negedge clk) en2x <= en;
assign gotDC= fifo_o[15] && fifo_o[14];
assign gotAC= fifo_o[15] && !fifo_o[14];
assign gotRLL= !fifo_o[15] && !fifo_o[12];
assign gotEOB= !fifo_o[15] && fifo_o[12];
assign gotLastBlock= fifo_o[15] && fifo_o[14] && fifo_o[12];
assign gotLastWord= !fifo_o[14] && fifo_o[12]; // (AC or RLL) and last bit set
assign gotColor= fifo_o[13];
always @(negedge clk) stuffer_was_rdy <= !en2x || rdy; // stuffer ready shoud be on if !en (move to register?)for now]
wire stuffer_was_rdy_early;
wire want_read_early;
LD i_stuffer_was_rdy_early (.Q(stuffer_was_rdy_early),.G(clk),.D(!en2x || rdy));
LD i_tables_re (.Q(tables_re),.G(clk),.D(en2x && rdy));
assign read_next= en2x && ((!steps[0] && !rll[5]) || eob ) && fifo_or_full; // fifo will never have data after the last block...
assign will_read= stuffer_was_rdy && fifo_or_full && en2x && ((!steps[0] && !rll[5]) || eob ); // fifo will never have data after the last block...
assign want_read= stuffer_was_rdy && ((!steps[0] && !rll[5]) || eob ); // for FIFO
assign want_read_early= stuffer_was_rdy_early && ((!steps[0] && !rll[5]) || eob ); // for FIFO
always @ (negedge clk) if (stuffer_was_rdy) begin
eob <= read_next && gotEOB;// will be 1 only during step[0]
if (!en2x) steps[5:0] <= 'b0;
else steps[5:0] <= { steps[4] && code_typ4, // will be skipped for codes 00/F0
steps[3:0],
(read_next && !(gotRLL && (fifo_o[5:4]==2'b00))) || rll[5] }; // will not start if it was <16, waiting for AC
end
always @ (negedge clk) begin
last_block <= en2x && (last_block?(!flush):(stuffer_was_rdy && will_read && gotLastBlock));
ready_to_flush <= en2x && (ready_to_flush?(!flush):(stuffer_was_rdy && last_block && will_read && gotLastWord));
test_lbw <= en2x && last_block && gotLastWord;
// did not work if flush was just after not ready?
flush <= en2x &&( flush?(!rdy):(rdy && stuffer_was_rdy && ready_to_flush && !(|steps)) );
end
always @ (negedge clk) if (will_read) begin
typeDC <= gotDC;
typeAC <= gotAC;
sval[11:0] <= fifo_o[11:0];
if (gotDC) tbsel_YC0 <= gotColor;
end
always @ (negedge clk) if (stuffer_was_rdy) begin
if (!en2x || (read_next && gotAC) || (steps[0] && typeAC)) rll[5:4] <= 2'b0;
else if (read_next && gotRLL) rll[5:4] <= fifo_o[5:4];
else if (rll[5:4]!=2'b00) rll[5:4] <= rll[5:4]-1;
if (!en2x || (read_next && !gotAC && !gotRLL) || (steps[0] && typeAC)) rll[3:0] <= 4'b0;
else if (read_next && gotRLL) rll[3:0] <= fifo_o[3:0];
end
assign code_typ0={typeDC || (!eob && (rll[5:4]==2'b0)),
typeDC || (!eob && (rll[5:4]!=2'b0))};
assign haddr_next[7:0] = code_typ2[1]?
(code_typ2[0]?{var_dl[3:0],4'hf}: // DC (reusing the spare cells of the AC table)
{rll2[3:0],var_dl[3:0]}): // AC normal code
(code_typ2[0]?8'hf0: //skip 16 zeros code
8'h00); //skip to end of block code
always @ (negedge clk) if (stuffer_was_rdy && steps[2]) begin // may be just if (stuffer_was_rdy)
haddr_r[7:0] <= haddr_next[7:0];
end
LD i_haddr_7 (.Q(haddr[7]),.G(clk),.D((stuffer_was_rdy && steps[2])?haddr_next[7]:haddr_r[7]));
LD i_haddr_6 (.Q(haddr[6]),.G(clk),.D((stuffer_was_rdy && steps[2])?haddr_next[6]:haddr_r[6]));
LD i_haddr_5 (.Q(haddr[5]),.G(clk),.D((stuffer_was_rdy && steps[2])?haddr_next[5]:haddr_r[5]));
LD i_haddr_4 (.Q(haddr[4]),.G(clk),.D((stuffer_was_rdy && steps[2])?haddr_next[4]:haddr_r[4]));
LD i_haddr_3 (.Q(haddr[3]),.G(clk),.D((stuffer_was_rdy && steps[2])?haddr_next[3]:haddr_r[3]));
LD i_haddr_2 (.Q(haddr[2]),.G(clk),.D((stuffer_was_rdy && steps[2])?haddr_next[2]:haddr_r[2]));
LD i_haddr_1 (.Q(haddr[1]),.G(clk),.D((stuffer_was_rdy && steps[2])?haddr_next[1]:haddr_r[1]));
LD i_haddr_0 (.Q(haddr[0]),.G(clk),.D((stuffer_was_rdy && steps[2])?haddr_next[0]:haddr_r[0]));
//
assign pre_dv = steps[4] || (steps[5] && (var_dl_late[3:0]!=4'b0));
assign pre_bits[15:0] = steps[5]?{5'b0,var_do[10:0]}: hcode[15:0];
assign pre_len [ 3:0] = steps[5]? var_dl_late[ 3:0]: hlen [3:0];
always @ (negedge clk) if (stuffer_was_rdy) begin
dv0 <= pre_dv;
out_bits[15:0] <= pre_bits[15:0];
out_len [ 3:0] <= pre_len [ 3:0];
end
always @ (negedge clk) if (!en2x || rdy) begin
dv <= stuffer_was_rdy? pre_dv:dv0;
do[15:0] <= stuffer_was_rdy? pre_bits[15:0]:out_bits[15:0];
dl[ 3:0] <= stuffer_was_rdy? pre_len [ 3:0]:out_len [ 3:0];
end
// "Extract shift registers" in synthesis should be off! FD has lower output delay than SRL16
always @ (negedge clk) if (stuffer_was_rdy) begin
code_typ1[1:0] <= code_typ0[1:0];
code_typ2[1:0] <= code_typ1[1:0];
code_typ3 <= code_typ2[1];
code_typ4 <= code_typ3;
rll1[3:0] <= rll[3:0];
rll2[3:0] <= rll1[3:0];
tbsel_YC1 <= tbsel_YC0;
tbsel_YC2 <= tbsel_YC1;
tbsel_YC3 <= tbsel_YC2;
end
LD i_haddr_8 (.Q(haddr[8]),.G(clk),.D(stuffer_was_rdy?tbsel_YC2:tbsel_YC3));
LD_1 i_hlen3 (.Q( hlen[ 3]),.G(clk),.D(tables_out[19]));
LD_1 i_hlen2 (.Q( hlen[ 2]),.G(clk),.D(tables_out[18]));
LD_1 i_hlen1 (.Q( hlen[ 1]),.G(clk),.D(tables_out[17]));
LD_1 i_hlen0 (.Q( hlen[ 0]),.G(clk),.D(tables_out[16]));
LD_1 i_hcode15(.Q(hcode[15]),.G(clk),.D(tables_out[15]));
LD_1 i_hcode14(.Q(hcode[14]),.G(clk),.D(tables_out[14]));
LD_1 i_hcode13(.Q(hcode[13]),.G(clk),.D(tables_out[13]));
LD_1 i_hcode12(.Q(hcode[12]),.G(clk),.D(tables_out[12]));
LD_1 i_hcode11(.Q(hcode[11]),.G(clk),.D(tables_out[11]));
LD_1 i_hcode10(.Q(hcode[10]),.G(clk),.D(tables_out[10]));
LD_1 i_hcode9 (.Q(hcode[ 9]),.G(clk),.D(tables_out[ 9]));
LD_1 i_hcode8 (.Q(hcode[ 8]),.G(clk),.D(tables_out[ 8]));
LD_1 i_hcode7 (.Q(hcode[ 7]),.G(clk),.D(tables_out[ 7]));
LD_1 i_hcode6 (.Q(hcode[ 6]),.G(clk),.D(tables_out[ 6]));
LD_1 i_hcode5 (.Q(hcode[ 5]),.G(clk),.D(tables_out[ 5]));
LD_1 i_hcode4 (.Q(hcode[ 4]),.G(clk),.D(tables_out[ 4]));
LD_1 i_hcode3 (.Q(hcode[ 3]),.G(clk),.D(tables_out[ 3]));
LD_1 i_hcode2 (.Q(hcode[ 2]),.G(clk),.D(tables_out[ 2]));
LD_1 i_hcode1 (.Q(hcode[ 1]),.G(clk),.D(tables_out[ 1]));
LD_1 i_hcode0 (.Q(hcode[ 0]),.G(clk),.D(tables_out[ 0]));
huff_fifo i_huff_fifo(.pclk(pclk),
.clk(clk),
.en(en), // will reset if ==0 (sync to pclk)
.di(di[15:0]), // data in (sync to pclk)
.ds(ds), // din valid (sync to pclk)
.want_read(want_read),
.want_read_early(want_read_early),
.dav(fifo_or_full), // FIFO output register has data
.q(fifo_o[15:0])); // output data (will add extra buffering if needed)
varlen_encode i_varlen_encode(.clk(clk),
.en(stuffer_was_rdy), //will enable registers. 0 - freese
.start(steps[0]),
.d(sval[11:0]), // 12-bit signed
.l(var_dl[ 3:0]), // [3:0] code length
.l_late(var_dl_late[3:0]),
.q(var_do[10:0])); // [10:0]code
always @ (negedge clk) twe_d <= twe;
RAMB16_S18_S36 i_htab (
.DOA(), // Port A 16-bit Data Output
.DOPA(), // Port A 2-bit Parity Output
.ADDRA({ta[8:0],twe_d}), // Port A 10-bit Address Input
.CLKA(!clk), // Port A Clock
.DIA(tdi[15:0]), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(twe | twe_d),// Port A Write Enable Input
.DOB({unused[11:0],tables_out[19:0]}), // Port B 32-bit Data Output
.DOPB(), // Port B 4-bit Parity Output
.ADDRB(haddr[8:0]), // Port B 9-bit Address Input
.CLKB(clk), // Port B Clock
.DIB(32'b0), // Port B 32-bit Data Input
.DIPB(4'b0), // Port-B 4-bit parity Input
.ENB(tables_re), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
endmodule
//used the other edge of the clk2x
module huff_fifo (pclk,
clk,
en, // will reset if ==0 (sync to pclk)
di, // data in (sync to pclk)
ds, // din valid (sync to pclk)
want_read,
want_read_early,
dav, // FIFO output register has data (fifo_or_full)
q); // output data
input pclk,clk,en,ds, want_read, want_read_early; //,got; // will_read;
input [15:0] di;
output dav;
output[15:0] q;
reg [9:0] wa;
reg [9:0] sync_wa; // delayed wa, re-calculated at output clock
reg [9:0] ra_r;
wire [9:0] ra;
wire [15:0] q;
reg load_q;
wire [15:0] fifo_o;
reg ds1; // ds delayed by one pclk to give time to block ram to write data. Not needed likely.
reg synci;
reg [1:0] synco;
reg sync_we; // single clk period pulse for each ds@pclk
reg en2x; // en sync to clk;
reg re_r;
wire re;
reg dav; // output latch has data
reg fifo_dav; // RAM output reg has data
reg dav_and_fifo_dav;
wire ram_dav; // RAM has data inside
reg [9:0] diff_a;
wire next_re;
always @ (posedge pclk) begin // input stage, no overrun detection
if (!en) wa[9:0] <= 10'b0;
else if (ds) wa[9:0] <= wa[9:0]+1;
ds1 <= ds && en;
if (!en) synci <= 1'b0;
else if (ds1) synci <= ~synci;
end
always @ (negedge clk) begin
en2x <= en;
synco[1:0] <= {synco[0],synci};
sync_we <= en2x && (synco[0] != synco[1]);
end
assign ram_dav= sync_we || (diff_a[9:0] != 10'b0);
// assign next_re= ram_dav && (!dav || !fifo_dav || want_read);
assign next_re= ram_dav && (!dav_and_fifo_dav || want_read);
always @ (negedge clk) begin
dav <= en2x && (fifo_dav || (dav && !want_read));
fifo_dav <= en2x && (ram_dav ||(dav && fifo_dav && !want_read));
dav_and_fifo_dav <= en2x && (fifo_dav || (dav && !want_read)) && (ram_dav ||(dav && fifo_dav && !want_read)); // will optimize auto
re_r <= en2x && next_re;
if (!en2x) sync_wa[9:0] <= 10'b0;
else if (sync_we) sync_wa[9:0] <= sync_wa[9:0]+1;
if (!en2x) ra_r [9:0] <= 10'b0;
else if (next_re) ra_r [9:0] <= ra_r[9:0]+1;
if (!en2x) diff_a[9:0] <= 10'b0;
else if (sync_we && !next_re) diff_a[9:0] <= diff_a[9:0]+1;
else if (!sync_we && next_re) diff_a[9:0] <= diff_a[9:0]-1;
end
LD i_re (.Q(re),.G(clk),.D(next_re));
LD i_ra9 (.Q(ra[9]),.G(clk),.D(ra_r[9]));
LD i_ra8 (.Q(ra[8]),.G(clk),.D(ra_r[8]));
LD i_ra7 (.Q(ra[7]),.G(clk),.D(ra_r[7]));
LD i_ra6 (.Q(ra[6]),.G(clk),.D(ra_r[6]));
LD i_ra5 (.Q(ra[5]),.G(clk),.D(ra_r[5]));
LD i_ra4 (.Q(ra[4]),.G(clk),.D(ra_r[4]));
LD i_ra3 (.Q(ra[3]),.G(clk),.D(ra_r[3]));
LD i_ra2 (.Q(ra[2]),.G(clk),.D(ra_r[2]));
LD i_ra1 (.Q(ra[1]),.G(clk),.D(ra_r[1]));
LD i_ra0 (.Q(ra[0]),.G(clk),.D(ra_r[0]));
always @ (posedge clk) begin
// load_q <= dav?want_read:re_r;
load_q <= dav?want_read_early:re_r;
end
LD_1 i_q15 (.Q( q[15]),.G(clk),.D(load_q?fifo_o[15]:q[15]));
LD_1 i_q14 (.Q( q[14]),.G(clk),.D(load_q?fifo_o[14]:q[14]));
LD_1 i_q13 (.Q( q[13]),.G(clk),.D(load_q?fifo_o[13]:q[13]));
LD_1 i_q12 (.Q( q[12]),.G(clk),.D(load_q?fifo_o[12]:q[12]));
LD_1 i_q11 (.Q( q[11]),.G(clk),.D(load_q?fifo_o[11]:q[11]));
LD_1 i_q10 (.Q( q[10]),.G(clk),.D(load_q?fifo_o[10]:q[10]));
LD_1 i_q9 (.Q( q[ 9]),.G(clk),.D(load_q?fifo_o[ 9]:q[ 9]));
LD_1 i_q8 (.Q( q[ 8]),.G(clk),.D(load_q?fifo_o[ 8]:q[ 8]));
LD_1 i_q7 (.Q( q[ 7]),.G(clk),.D(load_q?fifo_o[ 7]:q[ 7]));
LD_1 i_q6 (.Q( q[ 6]),.G(clk),.D(load_q?fifo_o[ 6]:q[ 6]));
LD_1 i_q5 (.Q( q[ 5]),.G(clk),.D(load_q?fifo_o[ 5]:q[ 5]));
LD_1 i_q4 (.Q( q[ 4]),.G(clk),.D(load_q?fifo_o[ 4]:q[ 4]));
LD_1 i_q3 (.Q( q[ 3]),.G(clk),.D(load_q?fifo_o[ 3]:q[ 3]));
LD_1 i_q2 (.Q( q[ 2]),.G(clk),.D(load_q?fifo_o[ 2]:q[ 2]));
LD_1 i_q1 (.Q( q[ 1]),.G(clk),.D(load_q?fifo_o[ 1]:q[ 1]));
LD_1 i_q0 (.Q( q[ 0]),.G(clk),.D(load_q?fifo_o[ 0]:q[ 0]));
/*
RAMB4_S16_S16 i_fifo (.DOB(fifo_o[15:0]),
.ADDRA(wa[7:0]),
.CLKA(pclk),
.DIA(di[15:0]),
.ENA(ds),.RSTA(1'b0),.WEA(1'b1),
.ADDRB(ra[7:0]),
.CLKB(clk),
.DIB(16'b0),.ENB(re),.RSTB(1'b0),.WEB(1'b0));
*/
RAMB16_S18_S18 i_fifo (
.DOA(), // Port A 16-bit Data Output
.DOPA(), // Port A 2-bit Parity Output
.ADDRA(wa[9:0]), // Port A 10-bit Address Input
.CLKA(pclk), // Port A Clock
.DIA(di[15:0]), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(ds), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b1), // Port A Write Enable Input
.DOB(fifo_o[15:0]),// Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.ADDRB(ra[9:0]), // Port B 10-bit Address Input
.CLKB(clk), // Port B Clock
.DIB(16'b0), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(re), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
endmodule
// Encoder will work 2 cycles/"normal" word, 1 cycle for codes "00" and "f0",
// only magnitude output is needed ASAP (2 cycles, the value out should be
// valid on the 5-th cycle - it will latency 4 cycles run each other cycle
// I'll make a shortcut - all codes processed in 2 cycles.
module varlen_encode (clk,
en, // will enable registers. 0 - "freese" at once
start, // (not faster than each other cycle)
d, // 12-bit signed
l, // [3:0] code length
l_late,// delayed l (sync to q)
q); // [10:0]code
input clk, en,start;
input [11:0] d;
output [ 3:0] l;
output [ 3:0] l_late;
output [10:0] q;
reg [11:0] d1;
reg [10:0] q,q0;
reg [ 3:0] l,l_late;
reg [2:0] cycles;
wire this0= |d1[ 3:0];
wire this1= |d1[ 7:4];
wire this2= |d1[10:8];
wire [1:0] codel0={|d1[ 3: 2],d1[ 3] || (d1[ 1] & ~d1[ 2])};
wire [1:0] codel1={|d1[ 7: 6],d1[ 7] || (d1[ 5] & ~d1[ 6])};
wire [1:0] codel2={|d1[ 10], (d1[ 9] & ~d1[10])};
wire [3:0] codel= this2? {2'b10,codel2[1:0]} :
(this1? {2'b01,codel1[1:0]} :
(this0? {2'b00,codel0[1:0]} : 4'b1111)); // after +1 will be 0;
always @ (negedge clk) if (en) begin
cycles[2:0] <= {cycles[1:0],start};
end
always @ (negedge clk) if (en && start) begin
d1[ 11] <= d[11];
d1[10:0] <= d[11]?-d[10:0]:d[10:0];
end
always @ (negedge clk) if (en & cycles[0]) begin
q0[10:0] <= d1[11]?~d1[10:0]:d1[10:0];
l <= codel[3:0]+1; // needed only ASAP, valid only 2 cycles after start
end
always @ (negedge clk) if (en & cycles[2]) begin
q[10:0] <= q0[10:0];
l_late[3:0] <= l[3:0];
end
endmodule
/*
** -----------------------------------------------------------------------------**
** i2c_writenly.v
**
** i2c (master, write only) controller with FIFO
**
** Copyright (C) 2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// This i2c controller is designed to reduce CPU load while programming sensor over the
// i2c interface. Only write registers operation is implemented,
// registers are read out using direct pin contol by the software - it is needed only
// currently sensor register readout is only needed for debug purposes (that is not true
// for non-sensor boards connected to the sensor port)
//
// Each register is written in a separate i2c access, fetched by the controller from the
// 32-bit wide FIFO, Each long word is sent over i2c starting from the MSB ( slave address+op),
// then 0..3 of the next bytes (3bytes for 16-bit registers like in Micron sensors).
// Bytes are sent starting from the MSB, so to send 8-bit data 0x12 to register 0x34 of slave 0x56
// length should be set to 3 and data word should be 0x56341200
//
// i2C FIFO is split in 8 (only 7 are used) pages, corresponding to frames (separated by start of
// frame sync pulses), each pages being able to hold up to 64 commands (register writes)
//
// If frame sync happens before all the commands for current frame were sent out, they stiil will be sent
// before controller proceeds to the next page ones.
//
// If sensor ir running with very small frames/high FPS and controller tries to send too many commands - it
// is possible the FIFO will be overrun. It is up to the software to avoid such (practically very unlikely)
// conditions
//
// Controller is programmed through 16 locations (currently mapped to 0x50..0x5f):
// 0x0..0x7 write directly to the frame number [2:0] modulo 8, except if you write to the frame
// "just missed" - in that case data will go to the current frame.
// 0x8 - write i2c commands to be sent ASAP
// 0x9 - write i2c commands to be sent after the next frame starts
//
// 0xe - write i2c commands to be sent after the next 6 frames start
// 0xf - control register:
// [14] - reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
// [13:12] - 3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
// [11] - if 1, use [10:9] to set command bytes to send after slave address (0..3)
// [10:9] - number of bytes to send, valid if [11] is set
// [8] - set duration of quarter i2c cycle in system clock cycles - nominal value 100 (0x64)
// [7:0] - duration of quater i2c cycle (applied if [8] is set)
module i2c_writeonly (sclk, // @negedge
wen, // sync to address and d[0:15]
wa, // [3:0] 0..7 - absolute data, 8..0x0e relative data, 0x0f - command
di, // [15:0] data in
sync, // frame sync (used to synchronize data), vacts_sclk @negedge sclk
busy, // busy (do not use software i2i)
scl, // i2c SCL
sda, // i2c SDA
scl_en, // switch i2c control to i2c_writeonly (from software direct bit control PIO)
sda_en, // enable SDA output
frame_no); // [2:0] current frame modulo 8
input sclk;
input wen;
input [ 3:0] wa;
input [15:0] di;
input sync;
output busy;
output scl;
output sda;
output scl_en;
output sda_en;
output [2:0] frame_no;
// reg [4:0] wen_d; // [0] - not just fifo, but any PIO writes, [1] and next - filtered for FIFO only
reg [3:0] wen_d; // [0] - not just fifo, but any PIO writes, [1] and next - filtered for FIFO only
reg [3:0] wad;
reg [15:0] di_1;
reg [15:0] di_2;
reg [15:0] di_3;
reg [2:0] wpage0; // FIFO page were ASAP writes go
reg [2:0] wpage7; // unused page, currently being cleared
reg [2:0] page_r; // FIFO page were current write goes (reading)
reg [2:0] wpage_w; // FIFO page were current write goes (reading)
reg wpage0_inc; // increment wpage0 (after frame syn or during reset
reg wpage0_inc_d; // next cycle after wpage0_inc
reg reset_cmd;
reg dly_cmd;
reg bytes_cmd;
reg run_cmd;
reg reset_on; // reset FIFO in progress
reg [1:0] i2c_bytes;
reg [7:0] i2c_dly;
reg i2c_enrun; // enable i2c
reg we_fifo_wp; // enable writing to fifo write pointer memory
reg req_clr; // request for clearing fifo_wp
wire is_ctl= (wad[3:0]==4'hf);
// wire is_rel= ((wad[3]==1) && (wad[2:0]!=3'h7));
wire is_abs= (wad[3]==0);
wire pre_wpage0_inc = (!wen_d[0] && !wen_d[1] && !wpage0_inc) && (req_clr || reset_on) ;
wire [2:0] frame_no=wpage0[2:0];
//fifo write pointers (dual port distributed RAM)
reg [5:0] fifo_wr_pointers [0:7];
wire [5:0] fifo_wr_pointers_outw=fifo_wr_pointers[wpage_w[2:0]];
wire [5:0] fifo_wr_pointers_outr=fifo_wr_pointers[page_r[2:0]];
reg [5:0] fifo_wr_pointers_outw_r;
reg [5:0] fifo_wr_pointers_outr_r;
// command i2c fifo (RAMB16_S9_S18)
reg [9:0] i2c_cmd_wa; // wite address for the current pair of 16-bit data words
// {page[2:0],word[5:0],MSW[0]}
reg i2c_cmd_we; // write enable to blockRAM
reg [1:0] page_r_inc; // increment page_r[2:0]; - signal and delayed version
reg [5:0] rpointer; // FIFO read pointer for current page
reg i2c_start; // initiate i2c register write sequence
reg i2c_run; // i2c sequence is in progress
reg i2c_done; // i2c sequence is over
reg [1:0] bytes_left; // bytes left to send after this one
reg [1:0] byte_number; // byte number to send next (3-2-1-0)
reg [1:0] byte_sending; // byte number currently sending (3-2-1-0)
reg [5:0] i2c_state; // 0x2b..0x28 - sending start, 0x27..0x24 - stop, 0x23..0x4 - data, 0x03..0x00 - ACKN
reg [7:0] dly_cntr; // bit delay down counter
reg scl_hard;
reg sda_hard;
reg sda_en_hard;
reg wen_i2c_soft; // write software-contrlolles SDA, SCL state
reg scl_en_soft; // software i2c control signals (used when i2c controller is disabled)
reg scl_soft;
reg sda_en_soft;
reg sda_soft;
wire scl=i2c_run? scl_hard: scl_soft ;
wire sda=i2c_run? sda_hard: sda_soft ;
wire scl_en=i2c_run? 1'b1: scl_en_soft ;
wire sda_en=i2c_run? sda_en_hard: sda_en_soft ;
wire [7:0] i2c_data;
reg [8:0] i2c_sr;
reg i2c_dly_pre_over;
wire i2c_dly_pre2_over;
reg i2c_dly_over;
wire i2c_startseq_last=(i2c_state[5:0]==6'h28);
wire i2c_stopseq_last= (i2c_state[5:0]==6'h24);
wire i2c_dataseq_last= (i2c_state[5:0]==6'h00);
wire i2c_bit_last = (i2c_state[1:0]==2'h0);
wire i2c_is_ackn = (i2c_state[5:2]==4'h0);
wire i2c_is_start = i2c_state[5] && i2c_state[3];
wire i2c_is_stop = i2c_state[5] && i2c_state[2];
wire i2c_is_data = !i2c_state[5] || (!i2c_state[3] && !i2c_state[2]); // including ackn
// reg i2c_startseq_done; // last cycle of start sequence
reg i2c_dataseq_done; // last cycle of each byte sequence
// reg i2c_dataseq_all_done; // last cycle of the last byte sequence
reg [1:0] i2c_byte_start;
reg i2c_sr_shift;
reg i2c_stop_start;
reg sda_0;
reg scl_0;
reg busy;
reg [2:0] busy_cntr;
assign i2c_dly_pre2_over=(dly_cntr[7:0]==8'h2);
always @ (negedge sclk) begin
// signals related to writing to i2c FIFO
// delayed versions of address, data write strobe
if (wen) wad [ 3:0] <= wa[ 3:0];
if (wen || wen_d[0]) di_1[15:0] <= di[15:0];
di_2[15:0] <= di_1[15:0];
di_3[15:0] <= di_2[15:0];
// wen_d[4:0] <= {wen_d[3:1],wen_d[0] && !is_ctl,wen};
wen_d[3:0] <= {wen_d[2:1],wen_d[0] && !is_ctl,wen};
// software i2c signals
wen_i2c_soft <= wen_d[0] && is_ctl;
if (i2c_run) scl_en_soft <= 1'b0;
else if (wen_i2c_soft & |di_1[1:0]) scl_en_soft <= (di_1[1:0]!=2'h3);
if (i2c_run) scl_soft <= 1'b0;
else if (wen_i2c_soft & |di_1[1:0]) scl_soft <= (di_1[1:0]==2'h2);
if (i2c_run) sda_en_soft <= 1'b0;
else if (wen_i2c_soft & |di_1[3:2]) sda_en_soft <= (di_1[3:2]!=2'h3);
if (i2c_run) sda_soft <= 1'b0;
else if (wen_i2c_soft & |di_1[3:2]) sda_soft <= (di_1[3:2]==2'h2);
// decoded commands
reset_cmd <= wen_d[0] && is_ctl && di_1[14];
run_cmd <= wen_d[0] && is_ctl && di_1[13];
bytes_cmd <= wen_d[0] && is_ctl && di_1[11];
dly_cmd <= wen_d[0] && is_ctl && di_1[ 8];
// setting control parameters
if (bytes_cmd) i2c_bytes[1:0]=di_2[10:9];
if (dly_cmd) i2c_dly[7:0] =di_2[ 7:0];
if (reset_cmd || (run_cmd && !di_2[12])) i2c_enrun <= 1'b0;
else if (run_cmd && di_2[12]) i2c_enrun <= 1'b1;
// write pointer memory
wpage0_inc <= pre_wpage0_inc;
wpage0_inc_d <= wpage0_inc;
if (reset_cmd) wpage0[2:0]<=3'h0;
else if (wpage0_inc) wpage0[2:0]<=wpage0[2:0]+1;
if (reset_cmd) wpage7[2:0]<=3'h7;
else if (wpage0_inc) wpage7[2:0]<=wpage0[2:0];
reset_on <= reset_cmd || (reset_on && !(wpage0_inc && ( wpage0[2:0]==3'h7)));
req_clr <= sync || (req_clr && !wpage0_inc);
if (wen_d[0]) wpage_w[2:0] <= is_abs?((wad[2:0]==wpage7[2:0])? wpage0[2:0] : wad[2:0]):(wpage0[2:0]+wad[2:0]);
else if (wpage0_inc) wpage_w[2:0] <= wpage7[2:0];
we_fifo_wp <= wen_d[1] || wpage0_inc;
if (wen_d[1]) fifo_wr_pointers_outw_r[5:0] <= fifo_wr_pointers_outw[5:0];
if (we_fifo_wp) fifo_wr_pointers[wpage_w[2:0]] <= wpage0_inc_d? 7'h0:(fifo_wr_pointers_outw_r[5:0]+1);
fifo_wr_pointers_outr_r[5:0] <= fifo_wr_pointers_outr[5:0]; // just register distri
// command i2c fifo (RAMB16_S9_S18)
if (wen_d[1]) i2c_cmd_wa[9:1] <= {wpage_w[2:0],fifo_wr_pointers_outw[5:0]};
i2c_cmd_wa[0] <= !wen_d[1]; // 0 for the first in a pair, 1 - for the second
i2c_cmd_we <= !reset_cmd && (wen_d[1] || (i2c_cmd_we && !wen_d[3])); //reset_cmd added to keep simulator happy
// signals related to reading from i2c FIFO
if (reset_on) page_r[2:0]<=3'h0;
else if (page_r_inc[0]) page_r[2:0]<=page_r[2:0]+1;
if (reset_cmd || page_r_inc[0]) rpointer[5:0] <= 6'h0;
else if (i2c_done) rpointer[5:0] <= rpointer[5:0] + 1;
i2c_run <= !reset_cmd && (i2c_start || (i2c_run && !i2c_done));
i2c_start <= i2c_enrun && !i2c_run && !i2c_start && (rpointer[5:0]!= fifo_wr_pointers_outr_r[5:0]) && !page_r_inc[1] && !page_r_inc[0];
page_r_inc[1:0] <= {page_r_inc[0], !i2c_run &&
!page_r_inc[0] &&
(rpointer[5:0] == fifo_wr_pointers_outr_r[5:0]) &&
(page_r[2:0]!=wpage0[2:0])};
//i2c sequence generation
if (!i2c_run) bytes_left[1:0] <= i2c_bytes[1:0];
else if (i2c_dataseq_done) bytes_left[1:0] <= bytes_left[1:0] -1;
if (!i2c_run) byte_sending[1:0] <= 2'h3;
else if (i2c_dataseq_done) byte_sending[1:0] <= byte_sending[1:0] + 1;
if (!i2c_run) byte_number[1:0] <= 2'h3;
else if (i2c_byte_start[1])byte_number[1:0] <= byte_number[1:0] - 1;
if (!i2c_run || i2c_dly_over) dly_cntr[7:0] <= i2c_dly[7:0];
else dly_cntr[7:0] <= dly_cntr[7:0] - 1;
// i2c_dly_pre_over <= (dly_cntr[7:0]==8'h2); // period = 3..258
i2c_dly_pre_over <= i2c_dly_pre2_over; // period = 3..258
i2c_dly_over <=i2c_dly_pre_over;
// i2c_startseq_done <= i2c_startseq_last && i2c_dly_pre_over;
i2c_dataseq_done <= i2c_dataseq_last && i2c_dly_pre_over;
// i2c_dataseq_all_done <= i2c_dataseq_last && i2c_dly_pre_over && (bytes_left == 2'h0) ;
i2c_byte_start[1:0] <= {i2c_byte_start[0],
(i2c_startseq_last || (i2c_dataseq_last && (bytes_left[1:0] != 2'h0))) && i2c_dly_pre2_over };
i2c_sr_shift <= i2c_bit_last && !(i2c_dataseq_last) && i2c_dly_pre_over;
i2c_stop_start <= i2c_dataseq_last && (bytes_left[1:0] == 2'h0) && i2c_dly_pre_over ;
i2c_done <= i2c_stopseq_last && i2c_dly_pre_over;
if (i2c_byte_start[1]) i2c_sr[8:0] <= {i2c_data[7:0], 1'b1};
else if (i2c_sr_shift) i2c_sr[8:0] <= {i2c_sr[7:0], 1'b1};
if (!i2c_run) i2c_state[5:0] <= 6'h2a; // start of start seq
else if (i2c_stop_start) i2c_state[5:0] <= 6'h26; // start of stop seq
else if (i2c_byte_start[1]) i2c_state[5:0] <= 6'h23; // start of data seq
else if (i2c_dly_over) i2c_state[5:0] <= i2c_state[5:0] - 1;
// now creating output signals
scl_0 <= (i2c_is_start && (i2c_state[1:0]!=2'h0)) ||
(i2c_is_stop && !i2c_state[1]) ||
(i2c_is_data && (i2c_state[1] ^i2c_state[0])) ||
!i2c_run;
sda_0 <= (i2c_is_start && i2c_state[1]) ||
(i2c_is_stop && (i2c_state[1:0]==2'h0)) ||
(i2c_is_data && i2c_sr[8]) ||
!i2c_run;
sda_hard <= sda_0;
scl_hard <= scl_0;
sda_en_hard <= i2c_run && (!sda_0 || (!i2c_is_ackn && !sda_hard));
if (wen) busy_cntr[2:0] <= 3'h7;
else if (|busy_cntr[2:0]) busy_cntr[2:0] <= busy_cntr[2:0]-1;
busy <= (i2c_enrun && ((rpointer[5:0]!= fifo_wr_pointers_outr_r[5:0]) || (page_r[2:0]!=wpage0[2:0]))) ||
|busy_cntr[2:0] ||
i2c_run ||
reset_on;
end
RAMB16_S9_S18 i_fifo (
.DOA(i2c_data[7:0]), // Port A 8-bit Data Output
.DOPA(), // Port A 1-bit Parity Output
.ADDRA({page_r[2:0],
rpointer[5:0],
byte_number[1:0]}), // Port A 11-bit Address Input
.CLKA(!sclk), // Port A Clock
.DIA(8'h0), // Port A 8-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.ENA(i2c_byte_start[0]), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.DOB(), // Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.ADDRB(i2c_cmd_wa[9:0]), // Port B 10-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB(di_3[15:0]), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(i2c_cmd_we), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b1) // Port B Write Enable Input
);
endmodule
module imu_logger ( clk, // system clock, negedge
xclk, // half frequency (80 MHz nominal)
we, // write enable (lower 16 bits, high - next cycle)
wa, // write address(1)/data(0)
di, // 16-bit data in (32 multiplexed)
usec, // un-latched timestamp microseconds
sec, // un-latched timestamp seconds
ext_di,
ext_do,
ext_en,
ts_rcv_sec, // [31:0] timestamp seconds received over the sync line
ts_rcv_usec, // [19:0] timestamp microseconds received over the sync line
ts_stb, // strobe when received timestamp is valid - single negedge sclk cycle
data_out, // 16-bit data out to DMA1 (@negedge clk)
data_out_stb,// data out valid (@negedge clk)
sample_counter, // could be DMA latency, safe to use sample_counter-1
debug_state
);
input clk; // system clock, negedge
input xclk; // half frequency (80 MHz nominal)
input we; // write enable (lower 16 bits, high - next cycle)
input wa; // write address(1)/data(0)
input [15:0] di; // 16-bit data in (32 multiplexed)
input [19:0] usec; // latched timestamp microseconds
input [31:0] sec; // latched timestamp seconds
input [11:0] ext_di; // external GPIO in
output [11:0] ext_do; // external GPIO out
output [11:0] ext_en; // external GPIO enable out
input [31:0] ts_rcv_sec; // [31:0] timestamp seconds received over the sync line
input [19:0] ts_rcv_usec; // [19:0] timestamp microseconds received over the sync line
input ts_stb; // strobe when received timestamp is valid - single negedge sclk cycle
output [15:0] data_out; // 16-bit data out to DMA1 (@negedge clk)
output data_out_stb;// data out valid (@negedge clk)
output [23:0] sample_counter; // could be DMA latency, safe to use sample_counter-1
output [31:0] debug_state;
wire ser_di; // gps serial data in
wire gps_pulse1sec;
wire mosi; // to IMU, bit 2 in J9
wire miso; // from IMU, bit 3 on J9
wire sda, sda_en, scl, scl_en;
reg [6:0] ctrl_addr=7'h0; // 0 - period, 1 - reserved, 2..31 - registers to log, >32 - gps parameters, >64 - odometer message
reg we_d; // only if wa was 0
reg we_imu;
reg we_gps;
reg we_period;
reg we_bit_duration;
reg we_message;
reg we_config;
reg we_config_imu; // bits 1:0, 2 - enable slot[1:0]
reg we_config_gps; // bits 6:3, 7 - enable - {ext,invert, slot[1:0]} slot==0 - disable
reg we_config_msg; // bits 12:8,13 - enable - {invert,extinp[3:0]} extinp[3:0]=='hf' - disable
reg we_config_syn; // bit 14, 15 - enable - enable logging external timestamps
// reg we_config_rst; // bit 16, 17 - enable - reset modules
// reg we_config_debug; // bits 21:18, 22 - enable
reg [15:0] di_d;
// reg di_d2;
reg [1:0] config_imu;
reg [3:0] config_gps;
reg [4:0] config_msg;
reg config_syn;
reg config_rst;
reg [3:0] config_debug;
reg [1:0] config_imu_mclk;
reg [3:0] config_gps_mclk;
reg [4:0] config_msg_mclk;
reg config_syn_mclk;
reg config_rst_mclk;
reg [3:0] config_debug_mclk;
reg [1:0] config_imu_pre;
reg [3:0] config_gps_pre;
reg [4:0] config_msg_pre;
reg config_syn_pre;
reg config_rst_pre;
reg [3:0] config_debug_pre;
reg [15:0] bitHalfPeriod;// serial gps speed - number of xclk pulses in half bit period
reg we_bitHalfPeriod;
reg [15:0] bitHalfPeriod_mclk;
reg enable_gps;
reg enable_msg;
reg enable_syn;
reg enable_timestamps;
wire message_trig;
reg ts_stb_rq;
reg [1:0] ext_ts_stb;
wire gps_ts_stb, ser_do,ser_do_stb;
wire [15:0] imu_data;
wire [15:0] nmea_data;
wire [15:0] extts_data;
wire [15:0] msg_data;
wire [15:0] timestamps_rdata; // multiplexed timestamp data
reg [2:0] gps_pulse1sec_d;
reg [1:0] gps_pulse1sec_denoise;
reg [7:0] gps_pulse1sec_denoise_count;
reg gps_pulse1sec_single;
// wire gps_ts; // single cycle @posedge xclk
wire [3:0] timestamp_request; // 0 - imu, 1 - gps, 2 - ext, 3 - msg
wire [3:0] timestamp_ackn;
wire [23:0] sample_counter;// could be DMA latency, safe to use sample_counter-1
wire [3:0] timestamp_request_long; //from sub-module ts request until reset by arbiter, to allow timestamp_ackn
wire [3:0] channel_ready; // 0 - imu, 1 - gps, 2 - ext, 3 - msg
wire [3:0] channel_next; // 0 - imu, 1 - gps, 2 - ext, 3 - msg
wire [1:0] channel; // currently logged channel number
wire [1:0] timestamp_sel; // selected word in timestamp (0..3)
wire ts_en; // log timestamp (when false - data)
wire mux_data_valid; // data valid from multiplexer (to xclk->clk converter fifo)
reg [15:0] mux_data_source;// data multiplexed from 1 of the 4 channels
reg mux_rdy_source; // data ready multiplexed from 1of the 4 channels (to fill rest with zeros)
reg [15:0] mux_data_final; // data multiplexed between timestamps and channel data (or 0 if ~ready)
wire [15:0] data_out; // 16-bit data out to DMA1 (@negedge clk)
wire data_out_stb;// data out valid (@posegedge clk)
wire rs232_wait_pause;// may be used as reset for decoder
wire rs232_start; // serial character start (single pulse)
wire nmea_sent_start; // serial character start (single pulse)
reg pre_message_trig;
// reg [1:0] debug_reg;
reg [7:0] dbg_cntr;
assign ext_en[11:0]= {5'b0,(config_imu[1:0]==2'h3)?1'b1:1'b0,1'b0,(config_imu[1:0]==2'h2)?1'b1:1'b0,1'b0,(config_imu[1:0]==2'h1)?1'b1:1'b0,(config_imu[1:0]!=2'h0)?{sda_en,scl_en}:2'h0};
assign ext_do[11:0]= {5'b0,(config_imu[1:0]==2'h3)?mosi:1'b0,1'b0,(config_imu[1:0]==2'h2)?mosi:1'b0,1'b0,(config_imu[1:0]==2'h1)?mosi:1'b0,(config_imu[1:0]!=2'h0)?{sda,scl}:2'h0};
assign miso= config_imu[1]?(config_imu[0]?ext_di[7] :ext_di[5]):(config_imu[0]?ext_di[3]:1'b0);
assign ser_di= config_gps[1]?(config_gps[0]?ext_di[6] :ext_di[4]):(config_gps[0]?ext_di[2]:1'b0);
assign gps_pulse1sec=config_gps[2]^(config_gps[1]?(config_gps[0]?ext_di[7] :ext_di[5]):(config_gps[0]?ext_di[3]:1'b0));
//sngl_wire
always @(config_msg[3:0] or ext_di[11:0]) begin
case (config_msg[3:0])
4'h0: pre_message_trig = ext_di[0];
4'h1: pre_message_trig = ext_di[1];
4'h2: pre_message_trig = ext_di[2];
4'h3: pre_message_trig = ext_di[3];
4'h4: pre_message_trig = ext_di[4];
4'h5: pre_message_trig = ext_di[5];
4'h6: pre_message_trig = ext_di[6];
4'h7: pre_message_trig = ext_di[7];
4'h8: pre_message_trig = ext_di[8]; // internal optocoupler, use invert 5'h18
4'h9: pre_message_trig = ext_di[9];
4'ha: pre_message_trig = ext_di[10];// external optocoupler, use invert 5'h1a
4'hb: pre_message_trig = ext_di[10];
default:pre_message_trig = 1'b0;
endcase
end
assign message_trig= config_msg[4]^pre_message_trig;
assign timestamp_request[1]=config_gps[3]? (config_gps[2]?nmea_sent_start:gps_ts_stb):gps_pulse1sec_single;
// filter gps_pulse1sec
always @ (posedge xclk) begin
if (config_rst) gps_pulse1sec_d[2:0] <= 3'h0;
else gps_pulse1sec_d[2:0] <= {gps_pulse1sec_d[1:0], gps_pulse1sec};
if (config_rst) gps_pulse1sec_denoise[0] <= 1'b0;
else if (gps_pulse1sec_denoise_count[7:0]==8'h0) gps_pulse1sec_denoise[0] <= gps_pulse1sec_d[2];
if (gps_pulse1sec_d[2]==gps_pulse1sec_denoise[0]) gps_pulse1sec_denoise_count[7:0] <= 8'hff;
else gps_pulse1sec_denoise_count[7:0] <= gps_pulse1sec_denoise_count[7:0] - 1;
gps_pulse1sec_denoise[1] <= gps_pulse1sec_denoise[0];
gps_pulse1sec_single <= !gps_pulse1sec_denoise[1] && gps_pulse1sec_denoise[0];
end
// re-sync single pulse @ negedge sclk - ts_stb to @posedge xclk
always @ (posedge ext_ts_stb[1] or negedge clk) begin
if (ext_ts_stb[1]) ts_stb_rq <= 1'b0;
else if (config_rst_mclk) ts_stb_rq <= 1'b0;
else if (ts_stb) ts_stb_rq <= 1'b1;
end
always @ (posedge xclk) begin
ext_ts_stb[1:0] <= {ext_ts_stb[0] & ~ext_ts_stb[1],ts_stb_rq};
end
always @ (negedge clk) begin
if (we) di_d[15:0] <= di[15:0];
// di_d2 <=di_d[0];
// we_d <= we && !wa;
we_d <= we && !wa;
we_imu <= we && !wa && (ctrl_addr[6:5] == 2'h0);
we_gps <= we && !wa && (ctrl_addr[6:5] == 2'h1);
we_message <= we && !wa && (ctrl_addr[6:5] == 2'h2);
// we_timer[4:0] <= {we_timer[3:0], we && !wa && (ctrl_addr[5:0]==6'h0)} ;
we_period <= we && !wa && (ctrl_addr[6:0]==7'h0);
we_bit_duration <= we && !wa && (ctrl_addr[6:0]==7'h1);
we_bitHalfPeriod<= we && !wa && (ctrl_addr[6:0]==7'h2);
we_config <= we && !wa && (ctrl_addr[6:0]==7'h3);
we_config_imu <= we && !wa && (ctrl_addr[6:0]==7'h3) && di[ 2];
we_config_gps <= we && !wa && (ctrl_addr[6:0]==7'h3) && di[ 7];
we_config_msg <= we && !wa && (ctrl_addr[6:0]==7'h3) && di[13];
we_config_syn <= we && !wa && (ctrl_addr[6:0]==7'h3) && di[15];
// we_config_rst <= we_config && di[1];
if (we_config_imu) config_imu_mclk[1:0] <= di_d[ 1:0]; // bits 1:0, 2 - enable slot[1:0]
if (we_config_gps) config_gps_mclk[3:0] <= di_d[ 6:3]; // bits 6:3, 7 - enable - {ext,inver, slot[1:0]} slot==0 - disable
if (we_config_msg) config_msg_mclk[4:0] <= di_d[12:8]; // bits 12:8,13 - enable - {invert,extinp[3:0]} extinp[3:0]=='hf' - disable
if (we_config_syn) config_syn_mclk <= di_d[ 14]; // bit 14, 15 - enable
if (we_config && di[1]) config_rst_mclk <= di[0]; // bit 16, 17 - enable
if (we_config && di[6]) config_debug_mclk[3:0] <= di[5:2]; // bit 21:18, 22 - enable
if (we_bitHalfPeriod) bitHalfPeriod_mclk[15:0]<=di_d[15:0];
if (we && wa) ctrl_addr[6:5] <= di[6:5];
if (we && wa) ctrl_addr[4:0] <= di[4:0];
else if (we_d && (ctrl_addr[4:0]!=5'h1f)) ctrl_addr[4:0] <=ctrl_addr[4:0]+1; // no roll over,
end
always @ (posedge xclk) begin
bitHalfPeriod[15:0] <= bitHalfPeriod_mclk[15:0];
config_imu_pre[1:0] <= config_imu_mclk[1:0];
config_gps_pre[3:0] <= config_gps_mclk[3:0];
config_msg_pre[4:0] <= config_msg_mclk[4:0];
config_syn_pre <= config_syn_mclk;
config_rst_pre <= config_rst_mclk;
config_debug_pre[3:0] <= config_debug_mclk[3:0];
config_imu[1:0] <= config_imu_pre[1:0];
config_gps[3:0] <= config_gps_pre[3:0];
config_msg[4:0] <= config_msg_pre[4:0];
config_syn <= config_syn_pre;
config_rst <= config_rst_pre;
config_debug[3:0] <= config_debug_pre[3:0];
enable_gps <= (config_gps[1:0] != 2'h0) && !config_rst;
enable_msg <= (config_gps[3:0] != 4'hf) && !config_rst;
enable_syn <= config_syn && !config_rst;
enable_timestamps <= !config_rst;
end
always @ (posedge xclk) begin
mux_data_source[15:0] <= channel[1]?(channel[0]?msg_data[15:0]:extts_data[15:0]):(channel[0]?nmea_data[15:0]:imu_data[15:0]);
mux_rdy_source <= channel[1]?(channel[0]?channel_ready[3]:channel_ready[2]):(channel[0]?channel_ready[1]:channel_ready[0]);
mux_data_final[15:0] <= ts_en? timestamps_rdata[15:0]:(mux_rdy_source?mux_data_source[15:0]:16'h0); // replace 16'h0 with some pattern to debug output
end
imu_spi i_imu_spi ( .sclk(clk), // system clock, negedge
.xclk(xclk), // half frequency (80 MHz nominal)
.we_ra(we_imu), // write enable for registers to log (@negedge clk)
.we_div(we_bit_duration),// write enable for clock dividing(@negedge clk)
.we_period(we_period),// write enable for IMU cycle period(@negedge clk) 0 - disable, 1 - single, >1 - half bit periods
.wa(ctrl_addr[4:0]), // write address for register (5 bits, @negedge clk)
.di(di[15:0]), // 16?-bit data in (di, not di_d)
.mosi(mosi), // to IMU, bit 2 in J9
.miso(miso), // from IMU, bit 3 on J9
.config_debug(config_debug[3:0]),
.sda(sda), // sda, shared with i2c, bit 1
.sda_en(sda_en), // enable sda output (when sda==0 and 1 cycle after sda 0->1)
.scl(scl), // scl, shared with i2c, bit 0
.scl_en(scl_en), // enable scl output (when scl==0 and 1 cycle after sda 0->1)
// .sngl_wire(sngl_wire), // single wire clock/data for the 103695 rev A
.ts(timestamp_request[0]), // timestamop request
.rdy(channel_ready[0]), // data ready
.rd_stb(channel_next[0]), // data read strobe (increment address)
.rdata(imu_data[15:0])); // data out (16 bits)
/*
logs events from odometer (can be software triggered), includes 56-byte message written to the buffer
So it is possible to assert trig input (will request timestamp), write message by software, then
de-assert the trig input - message with the timestamp will be logged
fixed-length de-noise circuitry with latency 256*T(xclk) (~3usec)
*/
imu_message i_imu_message(.sclk(clk), // system clock, negedge
.xclk(xclk), // half frequency (80 MHz nominal)
.we(we_message), // write enable for registers to log (@negedge sclk), with lower data half
.wa(ctrl_addr[3:0]), // write address for register (4 bits, @negedge sclk)
.di(di[15:0]), // 16-bit data in multiplexed
.en(enable_msg), // enable module operation, if 0 - reset
.trig(message_trig), // leading edge - sample time, trailing set rdy
.ts(timestamp_request[3]), // timestamop request
.rdy(channel_ready[3]), // data ready
.rd_stb(channel_next[3]), // data read strobe (increment address)
.rdata(msg_data[15:0])); // data out (16 bits)
/* logs frame synchronization data from other camera (same as frame sync) */
// ts_stb (mclk) -> trig)
imu_exttime i_imu_exttime(.xclk(xclk), // half frequency (80 MHz nominal)
.en(enable_syn), // enable module operation, if 0 - reset
.trig(ext_ts_stb[1]), // external time stamp updated, single pulse @posedge xclk
.usec(ts_rcv_usec[19:0]), // microseconds from external timestamp (should not chnage after trig for 10 xclk)
.sec(ts_rcv_sec[31:0]), // seconds from external timestamp
.ts(timestamp_request[2]), // timestamop request
.rdy(channel_ready[2]), // data ready
.rd_stb(channel_next[2]), // data read strobe (increment address)
.rdata(extts_data[15:0])); // data out (16 bits)
imu_timestamps i_imu_timestamps (
.sclk(clk), // 160MHz, negedge
.xclk(xclk), // 80 MHz, posedge
.rst(!enable_timestamps), // reset (@posedge xclk)
.sec(sec[31:0]), // running seconds (@negedge sclk)
.usec(usec[19:0]), // running microseconds (@negedge sclk)
.ts_rq(timestamp_request_long[3:0]),// requests to create timestamps (4 channels), @posedge xclk
.ts_ackn(timestamp_ackn[3:0]), // timestamp for this channel is stored
.ra({channel[1:0],timestamp_sel[1:0]}), // read address (2 MSBs - channel number, 2 LSBs - usec_low, (usec_high ORed with channel <<24), sec_low, sec_high
.dout(timestamps_rdata[15:0]));// output data
rs232_rcv i_rs232_rcv (.xclk(xclk), // half frequency (80 MHz nominal)
.bitHalfPeriod(bitHalfPeriod[15:0]), // half of the serial bit duration, in xclk cycles
.ser_di(ser_di), // rs232 (ttl) serial data in
.ser_rst(!enable_gps), // reset (force re-sync)
.ts_stb(gps_ts_stb), // strobe timestamp (start of message) (reset bit counters in nmea decoder)
.wait_just_pause(rs232_wait_pause),// may be used as reset for decoder
.start(rs232_start), // serial character start (single pulse)
.ser_do(ser_do), // serial data out(@posedge xclk) LSB first!
.ser_do_stb(ser_do_stb), // output data strobe (@posedge xclk), first cycle after ser_do becomes valid
// .debug(debug_state[4:0]),
.debug(debug_state[15:12]),
.bit_dur_cntr(debug_state[31:16]),
.bit_cntr(debug_state[11:7])
);
// output [15:0] debug_state;
// reg [7:0] dbg_cntr;
// assign debug_state[15:12]=3'b0;
assign debug_state[6:0] = dbg_cntr [6:0];
always @ (posedge xclk) begin
if (!enable_gps) dbg_cntr[7:0] <= 8'h0;
// else if (ser_do_stb) dbg_cntr[7:0] <= dbg_cntr[7:0]+1;
else if (rs232_start) dbg_cntr[7:0] <= dbg_cntr[7:0]+1;
end
nmea_decoder i_nmea_decoder (.sclk(clk), // system clock, @negedge
.we(we_gps), // registers write enable (@negedge sclk)
.wa(ctrl_addr[4:0]), // registers write adderss
.wd(di_d[7:0]), // write data
.xclk(xclk), // 80MHz, posedge
.start(gps_ts_stb), // start of the serial message
.rs232_wait_pause(rs232_wait_pause),// may be used as reset for decoder
.start_char(rs232_start), // serial character start (single pulse)
.nmea_sent_start(nmea_sent_start), // serial character start (single pulse)
.ser_di(ser_do), // serial data in (LSB first)
.ser_stb(ser_do_stb),// serial data strobe, single-cycle, first cycle after ser_di valid
.rdy(channel_ready[1]), // encoded nmea data ready
.rd_stb(channel_next[1]), // encoded nmea data read strobe (increment address)
.rdata(nmea_data[15:0]), // encoded data (16 bits)
.ser_rst(!enable_gps), // reset (now only debug register)
// .debug(debug_state[31:8])
// .debug(debug_state[15:8])
.debug()
);
logger_arbiter i_logger_arbiter(.xclk(xclk), // 80 MHz, posedge
.rst(config_rst), // module reset
.ts_rq_in(timestamp_request[3:0]), // in requests for timestamp (single-cycle - just leading edge )
.ts_rq(timestamp_request_long[3:0]), // out request for timestamp, to timestmp module
.ts_grant(timestamp_ackn[3:0]), // granted ts requests from timestamping module
.rdy(channel_ready[3:0]), // channels ready (leading edge - became ready, trailing - no more data, use zero)
.nxt(channel_next[3:0]), // pulses to modules to output next word
.channel(channel[1:0]), // decoded channel number (2 bits)
.ts_sel(timestamp_sel[1:0]), // select timestamp word to be output (0..3)
.ts_en(ts_en), // 1 - use timestamp, 0 - channel data (or 16'h0 if !ready)
.dv(mux_data_valid), // output data valid (from registered mux - 2 stage - first selects data and ready, second ts/data/zero)
.sample_counter(sample_counter));// number of 64-byte samples logged
buf_xclk_mclk16 i_buf_xclk_mclk16(.xclk(xclk), // posedge
.mclk(clk), // posedge!
.rst(config_rst), // @posedge xclk
.din(mux_data_final[15:0]),
.din_stb(mux_data_valid),
.dout(data_out[15:0]),
.dout_stb(data_out_stb));
endmodule
module logger_arbiter(xclk, // 80 MHz, posedge
rst, // module reset
ts_rq_in, // in requests for timestamp (single-cycle - just leading edge )
ts_rq, // out request for timestamp, to timestmp module
ts_grant, // granted ts requests from timestamping module
rdy, // channels ready (leading edge - became ready, trailing - no more data, use zero)
nxt, // pulses to modules to output next word
channel, // decoded channel number (2 bits)
ts_sel, // select timestamp word to be output (0..3)
ts_en, // 1 - use timestamp, 0 - channel data (or 16'h0 if !ready)
dv, // output data valid (from registered mux - 2 stage - first selects data and ready, second ts/data/zero)
sample_counter);// number of 64-byte samples logged
input xclk; // half frequency (80 MHz nominal)
input rst; // reset module
input [ 3:0] ts_rq_in; // in requests for timestamp (sinlgle-cycle)
output [ 3:0] ts_rq; // out request for timestamp, to timestmp module
input [ 3:0] ts_grant; // granted ts requests from timestamping module
input [ 3:0] rdy; // channels ready (leading edge - became ready, trailing - no more data, use zero)
output [ 3:0] nxt; // pulses to modules to output next word
output [ 1:0] channel; // decoded channel number (2 bits)
output [ 1:0] ts_sel; // select timestamp word to be output (0..3)
output ts_en; // 1 - use timestamp, 0 - channel data (or 16'h0 if !ready)
output dv; // output data valid (from registered mux - 2 stage - first selects data and ready, second ts/data/zero)
output [23:0] sample_counter;// number of 64-byte samples logged
reg [3:0] ts_rq_in_d;
reg [3:0] ts_rq;
reg [3:0] ts_valid;
// reg [3:0] ts_rq_reset;
reg [3:0] channels_ready;// channels granted and ready
reg [3:1] chn1hot; // channels 1-hot - granted and ready, priority applied
reg rq_not_zero; // at least one channel is ready for processing (same time as chn1hot[3:0])
reg [1:0] channel;
reg start;
reg busy;
wire wstart;
reg ts_en;
reg [4:0] seq_cntr;
reg seq_cntr_last;
reg [1:0] ts_sel;
reg dv;
reg inc_sample_counter;
reg [23:0] sample_counter;// number of 64-byte samples logged
reg [ 3:0] nxt;
reg pre_nxt;
reg [ 3:0] chn_servicing; //1-hot channel being service
// reg [ 3:0] rdy_d;
wire [3:0] wts_rq;
assign wstart= !busy && rq_not_zero;
assign wts_rq[3:0]= ts_rq_in[3:0] & ~ts_rq_in_d[3:0] & (~rdy[3:0] | chn_servicing[3:0]);
always @ (posedge xclk) begin
ts_rq_in_d[3:0] <= ts_rq_in[3:0];
// rdy_d[3:0] <=rdy[3:0];
if (wstart) channel[1:0] <= {chn1hot[3] | chn1hot[2],chn1hot[3] | chn1hot[1]};
if (wstart) chn_servicing[3:0] <= {chn1hot[3:1], ~|chn1hot[3:1]};
else if (!busy) chn_servicing[3:0] <= 4'h0;
// if (rst) ts_rq[3:0] <= 4'h0;
// else ts_rq[3:0] <= ~ts_rq_reset[3:0] & ((ts_rq_in[3:0] & ~ts_rq_in_d[3:0]) | ts_rq[3:0]);
if (rst) ts_rq[3:0] <= 4'h0;
// else ts_rq[3:0] <= ~ts_grant & ( (ts_rq_in[3:0] & ~ts_rq_in_d[3:0] & (~rdy[3:0] | ~ts_valid[3:0])) | ts_rq[3:0]);
else ts_rq[3:0] <= ~ts_grant & ( wts_rq[3:0] | ts_rq[3:0]);
if (rst) ts_valid[3:0] <= 4'h0;
// else ts_valid[3:0] <= ~ts_rq_reset[3:0] &( ts_grant[3:0] | (ts_valid & ~(ts_rq_in[3:0] & ~ts_rq_in_d[3:0] & ~rdy[3:0])));
else ts_valid[3:0] <= (ts_grant[3:0] | (ts_valid & ~wts_rq[3:0]));
// if (rst) request[3:0] <= 4'h0;
// else request[3:0] <= ~ts_rq_reset[3:0] &( request[3:0] | (rdy[3:0] & ~rdy_d[3:0])));
// channels_ready[3:0] <= ts_grant[3:0] & rdy[3:0];
channels_ready[3:0] <= ts_valid[3:0] & rdy[3:0] & ~chn_servicing[3:0]; // ready should go down during servicing
rq_not_zero <= channels_ready[3:0] != 4'h0;
chn1hot[3:1] <= {channels_ready[3] & ~|channels_ready[2:0],
channels_ready[2] & ~|channels_ready[1:0],
channels_ready[1] & ~channels_ready[0]};
start <= wstart;
if ((seq_cntr[4:0]=='h1e) || rst) busy <= 1'b0;
else if (rq_not_zero) busy <= 1'b1;
// if (!busy) seq_cntr[4:0] <= 5'h1f;
if (!busy) seq_cntr[4:0] <= 5'h0;
else seq_cntr[4:0] <= seq_cntr[4:0] + 1;
seq_cntr_last <= (seq_cntr[4:0]=='h1e);
if (wstart) ts_en <=1'b1;
else if (seq_cntr[1:0]==2'h3) ts_en <=1'b0;
if (!ts_en) ts_sel[1:0] <= 2'h0;
else ts_sel[1:0] <= ts_sel[1:0] + 1;
if (!busy || (seq_cntr[4:0]=='h1d)) pre_nxt <= 1'b0;
else if (seq_cntr[4:0]=='h01) pre_nxt <= 1'b1;
/*
nxt [3:0] <= pre_nxt? { channel[1] & channel[0],
channel[1] & ~channel[0],
~channel[1] & channel[0],
~channel[1] & ~channel[0]}:4'h0;
*/
nxt [3:0] <= pre_nxt? chn_servicing[3:0]:4'h0;
/*
ts_rq_reset[3:0] <= start? { channel[1] & channel[0],
channel[1] & ~channel[0],
~channel[1] & channel[0],
~channel[1] & ~channel[0]}:4'h0;
*/
dv <= busy || seq_cntr_last;
inc_sample_counter <= seq_cntr_last;
if (rst) sample_counter[23:0] <= 24'h0;
else if (inc_sample_counter) sample_counter[23:0] <= sample_counter[23:0] +1;
end
endmodule
module buf_xclk_mclk16 (xclk, // posedge
mclk, // posedge
rst, // @posedge xclk
din,
din_stb,
dout,
dout_stb);
input xclk; // half frequency (80 MHz nominal)
input mclk; // system clock - frequency (160 MHz nominal)
input rst; // reset module
input [15:0] din;
input din_stb;
output [15:0] dout;
output dout_stb;
reg [1:0] wa;
reg [1:0] wa_mclk;
reg [1:0] wa_mclk_d;
reg rst_mclk;
reg [1:0] ra;
reg [1:0] ra_next;
reg inc_ra;
wire [15:0] pre_dout;
reg [15:0] dout;
reg dout_stb;
always @ (posedge xclk) begin
if (rst) wa[1:0] <= 2'h0;
else if (din_stb) wa[1:0] <={wa[0],~wa[1]};
end
always @ (posedge mclk) begin
wa_mclk[1:0] <= wa[1:0];
wa_mclk_d[1:0] <= wa_mclk[1:0];
rst_mclk<= rst;
if (rst_mclk) ra[1:0] <= 2'h0;
else ra[1:0] <= inc_ra?{ra[0],~ra[1]}:{ra[1],ra[0]};
if (rst_mclk) ra_next[1:0] <= 2'h1;
else ra_next[1:0] <= inc_ra?{~ra[1],~ra[0]}:{ra[0],~ra[1]};
inc_ra <= !rst && (ra[1:0]!=wa_mclk_d[1:0]) && (!inc_ra || (ra_next[1:0]!=wa_mclk_d[1:0]));
dout_stb <= inc_ra;
if (inc_ra) dout[15:0] <= pre_dout[15:0];
end
myRAM_WxD_D #( .DATA_WIDTH(16),.DATA_DEPTH(2))
i_fifo_4x16 (.D(din[15:0]),
.WE(din_stb),
.clk(xclk),
.AW(wa[1:0]),
.AR(ra[1:0]),
.QW(),
.QR(pre_dout[15:0]));
endmodule
module imu_spi ( sclk, // system clock, negedge
xclk, // half frequency (80 MHz nominal)
we_ra, // write enable for registers to log (@negedge clk)
we_div,// write enable for clock dividing(@negedge clk)
we_period,// write enable for IMU cycle period(@negedge clk) 0 - disable, 1 - single, >1 - half bit periods
wa, // write address for register (5 bits, @negedge clk)
di, // 16?-bit data in (di, not di_d)
mosi, // to IMU, bit 2 in J9
miso, // from IMU, bit 3 on J9
config_debug, // bit 0 - long sda_en
sda, // sda, shared with i2c, bit 1
sda_en, // enable sda output (when sda==0 and 1 cycle after sda 0->1)
scl, // scl, shared with i2c, bit 0
scl_en, // enable scl output (when scl==0 and 1 cycle after sda 0->1)
// sngl_wire, // single wire clock/data for the 103695 rev A
ts, // timestamop request
rdy, // data ready
rd_stb, // data read strobe (increment address)
rdata); // data out (16 bits)
input sclk; // system clock, negedge
input xclk; // half frequency (80 MHz nominal)
input we_ra; // write enable for registers to log (@negedge sclk)
input we_div;// write enable for clock dividing(@negedge sclk)
input we_period;// write enable for IMU cycle period(@negedge clk)
input [4:0] wa; // write address for register (5 bits, @negedge sclk)
input [15:0] di; // 16-bit data in
output mosi; // to IMU, bit 2 in J9
input miso; // from IMU, bit 3 on J9
input [3:0] config_debug;
output sda; // sda, shared with i2c, bit 1
output sda_en; // enable sda output (when sda==0 and 1 cycle after sda 0->1)
output scl; // scl, shared with i2c, bit 0
output scl_en; // enable scl output (when scl==0 and 1 cycle after sda 0->1)
output ts; // timestamp request
output rdy; // encoded nmea data ready
input rd_stb; // encoded nmea data read strobe (increment address)
output [15:0] rdata; // encoded data (16 bits)
// output sngl_wire; // combined clock/data
reg [ 7:0] bit_duration_mclk=8'h0;
reg [ 7:0] bit_duration;
reg [ 7:0] bit_duration_cntr=8'h0;
reg bit_duration_zero; // just for simulation
reg [ 3:0] clk_en=4'h0;
reg [ 1:0] clk_div;
reg [ 4:0] imu_in_word= 5'b0; // number of IMU output word in a sample (0..31), 0..3 - timestamp
reg pre_imu_wr_buf,imu_wr_buf;
wire [15:0] imu_in_buf;
reg [4:0] reg_seq_number; // number of register in a sequence
wire [6:1] imu_reg_number; // register numer to read
reg [1:0] seq_state; // 0 - idle, 1 - prepare spi(4?), 2 - spi-comm(32*29), 3 - finish (2)
reg [9:0] seq_counter;
reg end_spi, end_prepare;
reg set_mosi_prepare, set_mosi_spi;
reg seq_counter_zero, pre_seq_counter_zero;
reg [15:0] mosi_reg;
wire mosi;
reg sda, sda_d;
wire sda_en;
reg scl, scl_d;
wire scl_en;
reg shift_miso;
reg [15:0] miso_reg;
reg last_bit; // last clk _/~ in spi word (but first one)
reg last_bit_ext=1'b0; // from last bit till buffer write
reg last_buf_wr;
reg [ 4:0] raddr;
reg rdy=1'b0;
reg imu_start;
reg ts; // delay imu_start by one cycle, so it will be aftre rdy is reset
reg [31:0] period; // 0 - disable, 1 - single, >1 - period in 50 ns steps
reg [15:0] di_d;
reg imu_enabled_mclk;
reg [1:0] imu_enabled=2'h0;
reg imu_run_mclk;
reg [1:0] imu_run;
reg imu_when_ready_mclk;
reg [1:0] imu_when_ready;
reg imu_run_confirmed;
reg imu_start_mclk;
reg [1:0] imu_start_grant;
reg imu_start_first;
reg imu_start_first_was;
reg [31:0] period_counter;
wire en;
reg [4:01] we_timer;
reg first_prepare;
reg [1:0] first_prepare_d;
wire config_long_sda_en;
wire config_late_clk;
reg [7:0] stall_dur_mclk;
reg [7:0] stall_dur;
reg stall; // stall between words to satisfy SPI stall time
reg [7:0] stall_cntr; // stall counter (in half sclk periods)
reg set_stall;
reg skip_stall; // first word after CS -\_
wire shift_mosi;
reg imu_ready_reset;
reg [6:0] imu_ready_denoise_count;
reg [2:0] imu_data_ready_d;
reg [5:0] imu_data_ready;
reg [1:0] seq_state_zero;
reg pre_scl;
reg [2:0] sngl_wire_stb;
reg [1:0] sngl_wire_r;
wire sngl_wire;
wire config_single_wire; // used in 103695 rev A
assign sngl_wire=~|sngl_wire_r[1:0];
assign shift_mosi=(clk_en[3] && seq_counter[0] && !stall);
assign mosi=config_single_wire?sngl_wire:mosi_reg[15];
assign config_long_sda_en=config_debug[0];
assign config_late_clk= config_debug[1];
assign config_single_wire=config_debug[2];
assign en=imu_enabled[1];
assign sda_en= !config_single_wire && (!sda || !sda_d || (config_long_sda_en && (seq_state[1:0]!=2'b0)));
assign scl_en= !config_single_wire && (!scl || !scl_d);
always @ (negedge sclk) begin
di_d[15:0] <= di[15:0];
if (we_div) bit_duration_mclk[7:0]<=di_d[7:0];
if (we_div) stall_dur_mclk[7:0]<=di_d[15:8];
we_timer[4:1] <= {we_timer[3:1], we_period};
if (we_period) period[31:0]<={di[15:0],di_d[15:0]};
if (we_timer[2]) imu_run_mclk <= (period[31:1]!=31'b0); // double-cycle
if (we_timer[3]) imu_enabled_mclk <= imu_run_mclk | period[0];
if (we_timer[2]) imu_when_ready_mclk <= &period[31:16]; // double-cycle
if (!imu_enabled_mclk || imu_start_grant[1]) imu_start_mclk<=1'b0;
else if (we_timer[4])imu_start_mclk<=imu_enabled_mclk;
end
// debounce imu_data_ready
always @ (posedge xclk) begin
seq_state_zero[1:0] <= {seq_state_zero[0], ~|seq_state[1:0]};
imu_ready_reset <= !imu_enabled[1] || (seq_state[1:0]!=2'b0) || !imu_when_ready[1];
if (imu_ready_reset) imu_data_ready_d[2:0] <=3'b0;
else imu_data_ready_d[2:0] <= {imu_data_ready_d[1:0], miso};
if (imu_ready_reset) imu_data_ready[0] <= 1'b0;
else if (imu_ready_denoise_count[6:0]==7'h0) imu_data_ready[0] <= imu_data_ready_d[2];
if (imu_data_ready_d[2]==imu_data_ready[0]) imu_ready_denoise_count[6:0] <= 7'h7f; // use period LSBs?
else imu_ready_denoise_count[6:0] <= imu_ready_denoise_count[6:0] - 1;
if (imu_ready_reset) imu_data_ready[1] <= 1'b0;
else if (imu_data_ready[0]) imu_data_ready[1] <= 1'b1;
if (imu_ready_reset) imu_data_ready[2] <= 1'b0;
else if (imu_data_ready[1] && !imu_data_ready[0]) imu_data_ready[2] <= 1'b1;
if (imu_ready_reset) imu_data_ready[3] <= 1'b0;
else if (imu_data_ready[2] && imu_data_ready[0]) imu_data_ready[3] <= 1'b1;
if (clk_en[1]) imu_data_ready[4] <= imu_data_ready[3] ;
imu_data_ready[5] <=clk_en[1] && imu_data_ready[3] && !imu_data_ready[4]; // single pulse @clk_en[2]
end
always @ (posedge xclk) begin
imu_enabled[1:0] <= {imu_enabled[0],imu_enabled_mclk};
imu_run[1:0] <= {imu_run[0],imu_run_mclk};
imu_when_ready[1:0] <= {imu_when_ready[0],imu_when_ready_mclk};
if (~imu_run[1:0]) imu_run_confirmed <= 1'b0;
else if (imu_start_first) imu_run_confirmed <= imu_run[1];
imu_start_grant[1:0] <= {imu_enabled_mclk && (imu_start_grant[0] || (imu_start_grant[1] && !imu_start)),imu_start_mclk};
imu_start_first_was <= imu_start_grant[1] && (imu_start_first || imu_start_first_was);
imu_start_first<=clk_en[1] && imu_start_grant[1] && !imu_start_first_was; // single xclk at clk_en[2] time slot
imu_start <=(!imu_when_ready[1] && imu_start_first)||
(!imu_when_ready[1] && imu_run_confirmed && (period_counter[31:0]==32'h1) && clk_en[2]) ||
imu_data_ready[5]; // single pulses at clk_en[3]
if (imu_start || imu_when_ready[1]) period_counter[31:0] <= period[31:0];
else if (clk_en[3]) period_counter[31:0] <= period_counter[31:0] - 1;
end
always @ (posedge xclk) begin
bit_duration[7:0] <= bit_duration_mclk[7:0];
stall_dur[7:0] <= stall_dur_mclk[7:0];
bit_duration_zero <= (bit_duration[7:0]==8'h0);
clk_div[1:0]=en?(clk_div[1:0]+1):2'b0;
clk_en[3:0] <= {clk_en[2:0],clk_div[1:0]==2'h3};
if (bit_duration_zero || (bit_duration_cntr[7:0]==8'h0)) bit_duration_cntr[7:0]<=bit_duration[7:0];
else bit_duration_cntr[7:0] <= bit_duration_cntr[7:0]-1;
clk_en[3:0] <= {clk_en[2:0],bit_duration_cntr[7:0]==8'h3}; // change 9'h3 to enforce frequency limit
end
always @ (posedge xclk) begin
pre_seq_counter_zero <= clk_en[1] && (seq_counter[9:0]==10'h0) && (seq_state[1:0]!=2'h0); // active at clk_en[2]
seq_counter_zero <= pre_seq_counter_zero; // active at clk_en[3]
if (!en) seq_state[1:0] <= 2'h0;
else if (imu_start) seq_state[1:0] <= 2'h1;
else if (seq_counter_zero ) seq_state[1:0] <= seq_state[1:0] + 1; // will not count from 0 as seq_counter_zero will be disabled
if (!en) first_prepare <=1'b0;
else if (imu_start) first_prepare <=1'b1;
else if (clk_en[3]) first_prepare <=1'b0;
if (!en) first_prepare_d[1:0] <= 2'b0;
else if (clk_en[3]) first_prepare_d[1:0] <= {first_prepare_d[0],first_prepare};
end_prepare <= pre_seq_counter_zero && (seq_state[1:0]==2'h1);
end_spi <= pre_seq_counter_zero && (seq_state[1:0]==2'h2);
if (!en) seq_counter[9:0] <= 10'h000;
else if (imu_start) seq_counter[9:0] <= config_late_clk?10'h005:10'h003; // should be odd
else if (end_prepare) seq_counter[9:0] <= 10'h39f;
else if (end_spi) seq_counter[9:0] <= 10'h001;
else if (clk_en[3] && (seq_state[1:0]!=2'h0) && !stall) seq_counter[9:0] <= seq_counter[9:0] - 1;
set_mosi_prepare <= clk_en[2] && first_prepare;
set_mosi_spi <= clk_en[2] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h1f) && (seq_counter[9:5]!=6'h0) && !stall; // last word use zero
// no stall before the first word
if (!en) skip_stall <= 1'b0;
else if (end_prepare) skip_stall <= 1'b1;
else if (clk_en[3]) skip_stall <= 1'b0;
// set_stall <= clk_en[2] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h1f) && !skip_stall; // same as set_mosi_spi, but including last
// set_stall <= clk_en[1] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h1f) && !skip_stall && !stall; // @ clk_en[2]
set_stall <= clk_en[0] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h1f) && !skip_stall && !stall; // @ clk_en[1]
if (!en) mosi_reg[15:0] <= 16'h0;
else if (set_mosi_prepare) mosi_reg[15:0] <= 16'h7fff;
else if (set_mosi_spi) mosi_reg[15:0] <= {1'b0,imu_reg_number[6:1],9'b0};
else if (shift_mosi) mosi_reg[15:0] <= {mosi_reg[14:0],1'b0};
// assign shift_mosi=(clk_en[3] && seq_counter[0] && !stall);
// stall switches at clk_en[2]
// stall switches at clk_en[1]
if (!en) stall_cntr[7:0] <= 8'h0;
else if (set_stall) stall_cntr[7:0] <= stall_dur[7:0];
else if (clk_en[1]) stall_cntr[7:0] <= stall?(stall_cntr[7:0]-1):8'h0;
if (!en) stall <= 1'b0;
else if (set_stall) stall <= (stall_dur[7:0]!=0);
else if (clk_en[1] && (stall_cntr[7:1]==0)) stall <= 1'b0;
if (!en) sda <=1'b1;
else if (clk_en[3]) sda <= !(first_prepare_d[1] || (seq_counter[0] && (seq_state[1:0]==2'h3))) ;
if (!en) sda_d <=1'b1;
else if (clk_en[3]) sda_d <= sda;
// if (!en) scl <=1'b1;
// else if (clk_en[3]) scl <= (seq_state[1:0]!=2'h2) || !seq_counter[0] || stall;
if (!en) pre_scl <=1'b1;
else if (clk_en[2]) pre_scl <= (seq_state[1:0]!=2'h2) || !seq_counter[0] || stall;
scl <= pre_scl;
sngl_wire_stb[2:0] <={sngl_wire_stb[1:0], en & ((scl ^ pre_scl) | end_prepare)};
if (!en) sngl_wire_r[0]<=1'b0;
// else if (!pre_scl && scl) sngl_wire_r[0]<=1'b1;
// else if (!mosi || sngl_wire_stb[2]) sngl_wire_r[0]<=1'b0;
else if ((pre_scl ^scl) | end_prepare) sngl_wire_r[0]<=1'b1;
else if (!mosi_reg[15] || sngl_wire_stb[2] || scl) sngl_wire_r[0]<=1'b0;
if (!en) scl_d <=1'b1;
else if (clk_en[3]) scl_d <= scl;
if (imu_start) reg_seq_number[4:0] <= 5'h04;
else if (set_mosi_spi) reg_seq_number[4:0] <= reg_seq_number[4:0] + 1;
shift_miso <= !scl_d && clk_en[2]; // active at clk_en[3]
// shift_miso <= !scl_d && clk_en[2] && !stall; // active at clk_en[3]
if (shift_miso) miso_reg[15:0] <= {miso_reg[14:0], miso};
last_bit <= clk_en[2] && (seq_state[1:0]==2'h2) && (seq_counter[4:0]==5'h0) && (seq_counter[9:5]!=5'h1c);
last_bit_ext <= en && (last_bit || (last_bit_ext && !(clk_en[2] && !seq_counter[0])));
pre_imu_wr_buf <=clk_en[1] && last_bit_ext && !seq_counter[0];
imu_wr_buf <= pre_imu_wr_buf;
if (imu_start) imu_in_word[4:0] <= 5'h0;
else if (imu_wr_buf) imu_in_word[4:0] <= imu_in_word[4:0] + 1;
last_buf_wr <= (pre_imu_wr_buf && (seq_state[1:0]==2'h3));
end
always @ (negedge xclk) begin
sngl_wire_r[1] <= sngl_wire_stb[0];
end
always @ (posedge xclk) begin
if (!en || imu_start) raddr[4:0] <= 5'h0;
else if (rd_stb) raddr[4:0] <= raddr[4:0] + 1;
if (imu_start || (rd_stb && (raddr[4:0]==5'h1b)) || !en) rdy <= 1'b0; // only 28 words, not 32
else if (last_buf_wr) rdy <= 1'b1;
ts <=imu_start;
end
assign imu_in_buf[15:0]= miso_reg[15:0];
myRAM_WxD_D #( .DATA_WIDTH(6),.DATA_DEPTH(5))
i_registers2log (.D(di_d[6:1]),
.WE(we_ra),
.clk(!sclk),
.AW(wa[4:0]),
.AR(reg_seq_number[4:0]),
.QW(),
.QR(imu_reg_number[6:1]));
myRAM_WxD_D #( .DATA_WIDTH(16),.DATA_DEPTH(5))
i_odbuf0 (.D(imu_in_buf[15:0]),
.WE(imu_wr_buf),
.clk(xclk),
.AW(imu_in_word[4:0]),
.AR(raddr[4:0]),
.QW(),
.QR(rdata[15:0]));
endmodule
/*
logs events from odometer (can be software triggered), includes 56-byte message written to the buffer
So it is possible to assert trig input (will request timestamp), write message by software, then
de-assert the trig input - message with the timestamp will be logged
fixed-length de-noise circuitry with latency 256*T(xclk) (~3usec)
*/
module imu_message ( sclk, // system clock, negedge
xclk, // half frequency (80 MHz nominal)
we, // write enable for registers to log (@negedge sclk), with lower data half
wa, // write address for register (4 bits, @negedge sclk)
di, // 16-bit data in multiplexed
en, // enable module operation, if 0 - reset
trig, // leading edge - sample time, trailing set rdy
ts, // timestamop request
rdy, // data ready
rd_stb, // data read strobe (increment address)
rdata); // data out (16 bits)
input sclk; // system clock, negedge
input xclk; // half frequency (80 MHz nominal)
input we; // write enable for registers to log (@negedge sclk)
input [3:0] wa; // write address for register (4 bits, @negedge sclk)
input [15:0] di; // 16-bit data in (32 multiplexed)
input en; // enable
input trig; // leading edge - sample time, trailing set rdy
output ts; // timestamp request
output rdy; // encoded nmea data ready
input rd_stb; // encoded nmea data read strobe (increment address)
output [15:0] rdata; // encoded data (16 bits)
reg [ 4:0] raddr;
reg rdy=1'b0;
reg we_d;
reg [ 4:1] waddr;
reg [ 2:0] trig_d;
reg [ 7:0] denoise_count;
reg [ 1:0] trig_denoise;
reg ts;
reg [15:0] di_d;
always @ (negedge sclk) begin
di_d[15:0] <= di[15:0];
waddr[4:1] <= wa[3:0];
we_d <=we;
end
always @ (posedge xclk) begin
if (!en) trig_d[2:0] <= 3'h0;
else trig_d[2:0] <= {trig_d[1:0], trig};
if (!en) trig_denoise[0] <= 1'b0;
else if (denoise_count[7:0]==8'h0) trig_denoise[0] <= trig_d[2];
if (trig_d[2]==trig_denoise[0]) denoise_count[7:0] <= 8'hff;
else denoise_count[7:0] <= denoise_count[7:0] - 1;
trig_denoise[1] <= trig_denoise[0];
ts <= !trig_denoise[1] && trig_denoise[0];
if (!en || ts) raddr[4:0] <= 5'h0;
else if (rd_stb) raddr[4:0] <= raddr[4:0] + 1;
if (ts || (rd_stb && (raddr[4:0]==5'h1b)) || !en) rdy <= 1'b0;
else if (trig_denoise[1] && !trig_denoise[0]) rdy <= 1'b1;
end
myRAM_WxD_D #( .DATA_WIDTH(16),.DATA_DEPTH(5))
i_odbuf (.D(di_d[15:0]),
.WE(we | we_d),
.clk(~sclk),
.AW({waddr[4:1],we_d}),
.AR(raddr[4:0]),
.QW(),
.QR(rdata[15:0]));
endmodule
/*
logs frame synchronization data from other camera (same as frame sync)
*/
module imu_exttime ( xclk, // half frequency (80 MHz nominal)
en, // enable module operation, if 0 - reset
trig, // external time stamp updated
usec, // microseconds from external timestamp (should not chnage after trig for 10 xclk)
sec, // seconds from external timestamp
ts, // timestamop request
rdy, // data ready
rd_stb, // data read strobe (increment address)
rdata); // data out (16 bits)
input xclk; // half frequency (80 MHz nominal)
input en; // enable
input trig; // external time stamp updated
input [19:0] usec; // microseconds from external timestamp
input [31:0] sec; // seconds from external timestamp
output ts; // timestamp request
output rdy; // encoded nmea data ready
input rd_stb;// encoded nmea data read strobe (increment address)
output [15:0] rdata; // encoded data (16 bits)
reg [ 4:0] raddr;
reg rdy=1'b0;
reg we, pre_we;
reg [ 3:0] pre_waddr;
reg [ 1:0] waddr;
reg [ 2:0] trig_d;
reg pre_ts,ts;
reg [15:0] time_mux;
always @ (posedge xclk) begin
if (!en) trig_d[2:0] <= 3'h0;
else trig_d[2:0] <= {trig_d[1:0], trig};
pre_ts <= !trig_d[2] && trig_d[1];
ts <= pre_ts; // delayed so arbiter will enable ts to go through
if (!en || pre_ts) pre_waddr[3:0] <= 4'b0;
else if (!pre_waddr[3]) pre_waddr[3:0] <= pre_waddr[3:0] + 1;
if (pre_waddr[0]) waddr[1:0] <=pre_waddr[2:1];
if (pre_waddr[0] && !pre_waddr[3]) case (pre_waddr[2:1])
2'b00: time_mux[15:0] <= usec[15:0];
2'b01: time_mux[15:0] <= {12'h0,usec[19:16]};
2'b10: time_mux[15:0] <= sec[15:0];
2'b11: time_mux[15:0] <= sec[31:16];
endcase
pre_we<=pre_waddr[0] && !pre_waddr[3];
we <= pre_we;
if (!en || pre_ts) raddr[4:0] <= 5'h0;
else if (rd_stb) raddr[4:0] <= raddr[4:0] + 1;
if (pre_ts || (rd_stb && (raddr[1:0]==2'h3)) || !en) rdy <= 1'b0;
else if (we && (waddr[1:0]==2'h3)) rdy <= 1'b1;
end
myRAM_WxD_D #( .DATA_WIDTH(16),.DATA_DEPTH(2))
i_odbuf (.D(time_mux[15:0]),
.WE(we),
.clk(xclk),
.AW(waddr[1:0]),
.AR(raddr[1:0]),
.QW(),
.QR(rdata[15:0]));
endmodule
module rs232_rcv (xclk, // half frequency (80 MHz nominal)
bitHalfPeriod, // half of the serial bit duration, in xclk cycles
ser_di, // rs232 (ttl) serial data in
ser_rst, // reset (force re-sync)
ts_stb, // strobe timestamp (start of message) (reset bit counters in nmea decoder)
wait_just_pause,// may be used as reset for decoder
start, // serial character start (single pulse)
// char, // byte out
// char_stb); // char strobe (@posedge xclk)
ser_do, // serial data out(@posedge xclk) LSB first!
ser_do_stb, // output data strobe (@posedge xclk), first cycle after ser_do becomes valid
debug, // {was_ts_stb, was_start, was_error, was_ser_di_1, was_ser_di_0} - once after reset
bit_dur_cntr,
bit_cntr);
input xclk; // half frequency (80 MHz nominal)
input [15:0] bitHalfPeriod; // half of the serial bit duration, in xclk cycles
input ser_di; // rs232 (ttl) serial data in
input ser_rst; // reset (force re-sync)
output ts_stb; // strobe timestamp (start of message)
output wait_just_pause;// may be used as reset for decoder
output start; // serial character start (single pulse)
output [4:0] debug; // {was_ts_stb, was_start, was_error, was_ser_di_1, was_ser_di_0} - once after reset
output ser_do; // serial data out(@posedge xclk)
output ser_do_stb; // output data strobe (@posedge xclk), 2 cycles after ser_do becomes valid
output [15:0] bit_dur_cntr; // debug
output [4:0] bit_cntr; // debug
reg [4:0] ser_di_d;
reg ser_filt_di;
reg ser_filt_di_d;
reg bit_half_end; // last cycle in half-bit
reg last_half_bit;
reg wait_pause; // waiting input to stay at 1 for 10 cycles
reg wait_start; // (or use in_sync - set it after wait_pause is over?
reg receiving_byte;
reg start;
reg [15:0] bit_dur_cntr; // bit duration counter (half bit duration)
reg [4:0] bit_cntr; // counts half-bit intervals
wire error; // low level during stop slot
reg [1:0] restart;
wire reset_wait_pause;
reg ts_stb;
reg shift_en;
reg ser_do;
reg ser_do_stb;
wire sample_bit;
wire reset_bit_duration;
reg wait_just_pause;
wire wstart;
wire [4:0] debug;
reg [4:0] debug0; // {was_ts_stb, was_start, was_error, was_ser_di_1, was_ser_di_0} - once after reset
assign reset_wait_pause= (restart[1] && !restart[0]) || (wait_pause && !wait_start && !ser_di);
assign error=!ser_filt_di && last_half_bit && bit_half_end && receiving_byte;
assign sample_bit=shift_en && bit_half_end && !bit_cntr[0];
assign reset_bit_duration= reset_wait_pause || start || bit_half_end || ser_rst;
assign wstart=wait_start && ser_filt_di_d && !ser_filt_di;
assign debug[4:0] = {1'b0,wait_start,wait_pause,receiving_byte,shift_en};
always @ (posedge xclk) begin
// reg [4:0] ser_di_d;
// reg ser_filt_di;
// reg ser_filt_di_d;
ser_di_d[4:0] <= {ser_di_d[3:0],ser_di};
if (ser_rst || &ser_di_d[4:0]) ser_filt_di <= 1'b1;
else if (~|ser_di_d[4:0]) ser_filt_di <= 1'b0;
ser_filt_di_d <= ser_filt_di;
restart[1:0] <= {restart[0],(ser_rst || (last_half_bit && bit_half_end && receiving_byte))};
wait_pause <= !ser_rst && (reset_wait_pause ||
(receiving_byte && last_half_bit && bit_half_end ) ||
(wait_pause && !(last_half_bit && bit_half_end) && !(wait_start && !ser_filt_di)));
// start <= wait_start && ser_di_d && !ser_di;
start <= wstart;
// ts_stb <= !wait_pause && wait_start && ser_di_d && !ser_di;
ts_stb <= !wait_pause && wstart; // only first start after pause
bit_half_end <=(bit_dur_cntr[15:0]==16'h1) && !reset_bit_duration;
// wait_start <= ser_di && !ser_rst && ((wait_pause || receiving_byte) && last_half_bit && bit_half_end || wait_start);
wait_start <= !ser_rst && ((wait_pause || receiving_byte) && last_half_bit && bit_half_end || (wait_start && !wstart));
// receiving_byte <= !ser_rst && !error && (start || (receiving_byte && !(last_half_bit && bit_half_end)));
receiving_byte <= !ser_rst && (start || (receiving_byte && !(last_half_bit && bit_half_end)));
wait_just_pause <=wait_pause && !wait_start;
if (reset_bit_duration) bit_dur_cntr[15:0] <= bitHalfPeriod[15:0];
else bit_dur_cntr[15:0] <= bit_dur_cntr[15:0] - 1;
if (reset_wait_pause || ser_rst) bit_cntr[4:0] <= 5'h13;
else if (start) bit_cntr[4:0] <= 5'h12;
else if (bit_half_end) bit_cntr[4:0] <= bit_cntr[4:0] - 1;
last_half_bit <= ((bit_cntr[4:0] == 5'h0) && !bit_half_end);
shift_en <= receiving_byte && ((bit_half_end && ( bit_cntr[3:0]==4'h2))? bit_cntr[4]:shift_en);
if (sample_bit) ser_do <= ser_filt_di;
ser_do_stb <= sample_bit;
if (ser_rst) debug0[4:0] <=5'b0;
else debug0[4:0] <= debug | {ts_stb,start,error,ser_di_d,~ser_di_d};
end
endmodule
module nmea_decoder (sclk, // system clock, @negedge
we, // registers write enable (@negedge sclk)
wa, // registers write adderss
wd, // write data
xclk, // 80MHz, posedge
start, // start of the serail message
rs232_wait_pause,// may be used as reset for decoder
start_char, // serial character start (single pulse)
nmea_sent_start, // serial character start (single pulse)
ser_di, // serial data in (LSB first)
ser_stb,// serial data strobe, single-cycle, first cycle after ser_di valid
rdy, // encoded nmea data ready
rd_stb, // encoded nmea data read strobe (increment address)
rdata, // encoded data (16 bits)
ser_rst,
debug);
input sclk; // system clock, @negedge
input we; // registers write enable (@negedge sclk)
input [4:0] wa; // registers write adderss
input [7:0] wd; // write data
input xclk; // 80MHz, posedge
input start; // start of the serail message (after pause only)
input rs232_wait_pause;// may be used as reset for decoder
input start_char; // serial character start (single pulse)
output nmea_sent_start; // serial character start (single pulse), will repeat until got "$" and the sentence recognized
input ser_di; // serial data in (LSB first)
input ser_stb;// serial data strobe, single-cycle, ends 2 cycles after ser_di valid
output rdy; // encoded nmea data ready
input rd_stb; // encoded nmea data read strobe (increment address)
output [15:0] rdata; // encoded data (16 bits)
input ser_rst;
output[23:0] debug;
reg [ 9:0] bitnum;
reg gp_exp_bit;
reg valid; // so far valid sentence
reg [3:0] sentence1hot; // one-hot sentence, matching first 6 bytes ($GPxxx)
reg restart; // reset byte number if the first byte was not "$"
reg start_d;
reg [3:0] stb; // ser_stb delayed
reg msb,bits37,bit3;
reg vfy_dollar;
reg vfy_gp;
reg vfy_sel_sent;
reg vfy_first_comma; // first comma after $GPxxx
reg proc_fields;
reg last_vfy_gp; // delayed by 1 cycle from bit counters
reg last_vfy_sent; // delayed by 1 cycle from bit counters
// reg [3:0] sent_sel_cntr; // counts 3 times to 5, as $GPxxx - each 'x' is an upper case latter (0x40..0x5f)
reg lsbs5; // 5 LSBs during reading 3 last letters in $GPxxx
reg [3:0] gpxxx_addr;
wire [3:1] sentence1hot_pri; // sentence1hot made really one-hot
reg [1:0] sentence; // decoded sentence number (0..3)
reg [4:0] format_length; // number of fields in the sentence
reg [4:0] format_length_plus_7;
reg [4:0] format_field; // current number of the field in the sentence
wire start_format;
reg read_format_length; //, read_format_length_d;
reg read_format_byte;
reg shift_format_byte;
reg format_over;
reg sentence_over;
reg [7:0] format_byte;
reg [7:1] last_byte;
wire wcomma; // comma
wire weof; //asterisk, or cr/lf (<0x10)
wire wsep; //any separator
reg [3:0] nibble;
reg [3:0] nibble_pre;
wire [7:0] wbyte;
reg nibble_stb;
reg first_byte_in_field;
reg [1:0] extra_nibble; // empty byte field - send two 4'hf nibbles
reg [6:0] nibble_count;
wire [15:0] rdata; // encoded data (16 bits)
reg [ 4:0] raddr;
wire [3:0] gpxxx_w_one;
wire [7:0] format_data;
wire w_sentence_over;
reg [4:0] last_word_written; // number of the last word (4 nibbles) written - used ro deassert rdy (garbage after)
reg rdy=1'b0;
reg nmea_sent_start;
reg save_sent_number;
// input ser_rst;
reg [ 7:0] debug0;
reg [15:0] debug1;
reg [15:0] debug1_or;
wire [23:0] debug;
// assign debug[23:0] = {debug1[15:0],debug0[7:0]};
assign debug[23:0] = {1'b0,
proc_fields,
vfy_first_comma,
vfy_sel_sent,
vfy_gp,
vfy_dollar,
bitnum[9:0],
debug0[7:0]};
assign sentence1hot_pri[3:1]={sentence1hot[3]& ~|sentence1hot[2:0],
sentence1hot[2]& ~|sentence1hot[1:0],
sentence1hot[1]& ~sentence1hot[0]};
// assign start_format=(last_vfy_sent && (sentence1hot[3:0]!=4'h0) && (stb[3] && msb));
assign start_format=(vfy_first_comma && (sentence1hot[3:0]!=4'h0) && (stb[3] && msb));
assign wbyte[7:0]={ser_di,last_byte[7:1]}; // valid up to stb[3];
assign wcomma= proc_fields && msb && (wbyte[7:0]==8'h2c);
assign weof= proc_fields && msb && ((wbyte[7:0]==8'h2a) || (wbyte[7:4]==4'h0)); // 0x2a or 0x0? (<0x10)
assign wsep= wcomma || weof;
// assign w_sentence_over=wsep && (format_field[2:0]==format_length[2:0]) && (format_field[4:3]==(format_length[4:3]+1));
assign w_sentence_over=wsep && (format_field[4:0]==format_length_plus_7[4:0]);
//format_length_plus_7
always @ (posedge xclk) begin
if (ser_rst) debug0 [7:0] <= 8'b0;
else debug0 [7:0] <=debug0 [7:0] | {rdy,
proc_fields,
shift_format_byte,
start_format,
vfy_first_comma,
vfy_sel_sent,
vfy_gp,
vfy_dollar};
if (ser_rst) debug1 [15:0] <= 16'b0;
else if (stb[1] && vfy_sel_sent && lsbs5) debug1 [15:0] <= debug1 [15:0] | debug1_or [15:0];
case (gpxxx_addr[3:0])
4'h0: debug1_or[15:0] <= 16'h0001;
4'h1: debug1_or[15:0] <= 16'h0002;
4'h2: debug1_or[15:0] <= 16'h0004;
4'h3: debug1_or[15:0] <= 16'h0008;
4'h4: debug1_or[15:0] <= 16'h0010;
4'h5: debug1_or[15:0] <= 16'h0020;
4'h6: debug1_or[15:0] <= 16'h0040;
4'h7: debug1_or[15:0] <= 16'h0080;
4'h8: debug1_or[15:0] <= 16'h0100;
4'h9: debug1_or[15:0] <= 16'h0200;
4'ha: debug1_or[15:0] <= 16'h0400;
4'hb: debug1_or[15:0] <= 16'h0800;
4'hc: debug1_or[15:0] <= 16'h1000;
4'hd: debug1_or[15:0] <= 16'h2000;
4'he: debug1_or[15:0] <= 16'h4000;
4'hf: debug1_or[15:0] <= 16'h8000;
endcase
stb[3:0] <= {stb[2:0], ser_stb};
start_d <= start;
restart <= start || sentence_over || stb[2] && msb && ((!valid && (vfy_dollar || last_vfy_gp || vfy_first_comma)) || // may abort earlier (use vfy_gp)
((sentence1hot==4'h0) && last_vfy_sent)); // may abort earlier (use vfy_sel_sent)
if (start_d) bitnum[2:0] <= 3'h0;
else if (stb[3]) bitnum[2:0] <= bitnum[2:0] + 1;
if (start_d) msb <= 1'b0;
else if (stb[3]) msb <= (bitnum[2:0] ==3'h6);
if (start_d) bit3 <= 1'b0;
else if (stb[3]) bit3 <= (bitnum[2:0] ==3'h2);
if (start_d) bits37 <= 1'b0;
else if (stb[3]) bits37 <= (bitnum[1:0] ==2'h2);
if (start_d) lsbs5 <= 1'b1;
else if (stb[3]) lsbs5 <= !bitnum[2] || (bitnum[2:0] ==3'h7);
if (restart) bitnum[9:3] <= 'h0;
else if (stb[3] && msb) bitnum[9:3] <= bitnum[9:3] + 1;
if (restart || rs232_wait_pause) vfy_dollar <= 1'b1; // byte 0
else if (stb[3] && msb) vfy_dollar <= 1'b0;
last_vfy_gp <= vfy_gp && !bitnum[3];
if (restart) vfy_gp <= 1'b0;
else if (stb[3] && msb) vfy_gp <= (valid && vfy_dollar) || (vfy_gp && !last_vfy_gp); // bytes 1-2
last_vfy_sent <= vfy_sel_sent && (bitnum[3] && bitnum[5]);
if (restart) vfy_sel_sent <= 1'b0;
else if (stb[3] && msb) vfy_sel_sent <= (valid && last_vfy_gp) || (vfy_sel_sent && !last_vfy_sent); // bytes 3,4,5
if (restart) vfy_first_comma <= 1'b0;
else if (stb[3] && msb) vfy_first_comma <= last_vfy_sent;
if (restart) valid <= 1'b1; // ready @ stb[2]
else if (stb[1] && (ser_di!=gp_exp_bit) &&
(vfy_dollar || vfy_gp || vfy_first_comma || (vfy_sel_sent && !lsbs5))) valid <= 1'b0;
if (!vfy_sel_sent) gpxxx_addr[3:0] <= 4'h0;
else if (lsbs5 &&stb[3]) gpxxx_addr[3:0] <= gpxxx_addr[3:0] + 1;
if (vfy_gp) sentence1hot[3:0] <= 4'hf;
else if (stb[1] && vfy_sel_sent && lsbs5) sentence1hot[3:0] <= sentence1hot & (ser_di?(gpxxx_w_one[3:0]): (~gpxxx_w_one[3:0]));
if (last_vfy_sent && stb[3] && msb) sentence[1:0] <= {sentence1hot_pri[3] | sentence1hot_pri[2], sentence1hot_pri[3] | sentence1hot_pri[1]};
if (restart || sentence_over) proc_fields <=1'b0;
else if (start_format) proc_fields <=1'b1;
if (!proc_fields) format_field[4:0] <= 5'h0;
else if (read_format_length) format_field[4:0] <= 5'h8;
else if (format_over) format_field[4:0] <= format_field[4:0] + 1;
format_length_plus_7[4:0] <= format_length[4:0]+7;
if (start_format) first_byte_in_field <=1'b1;
else if (stb[3] && msb) first_byte_in_field <= format_over;
read_format_length <= start_format;
if (read_format_length) format_length[4:0] <= format_data[4:0];
read_format_byte <= read_format_length || (format_over && format_field[2:0]==3'h7); // @stb[4]
shift_format_byte <= format_over; // @stb[4]
if (read_format_byte) format_byte[7:0] <= format_data[7:0];
else if (shift_format_byte) format_byte[7:0] <= {1'b0,format_byte[7:1]};
// format_byte[0] - current format
if (stb[3]) last_byte[7:1] <= {ser_di,last_byte[7:2]};
format_over <= stb[2] && wsep;
// sentence_over <= stb[2] && (weof || (wsep && w_sentence_over));
sentence_over <= stb[2] && (weof || w_sentence_over);
if (bits37 && stb[3]) nibble_pre[3:0] <= last_byte[4:1]; // always OK
if (stb[3] && bit3) nibble[3:0] <= nibble_pre[3:0];
else if (stb[3] && msb && wsep && (first_byte_in_field || !format_byte[0])) nibble[3:0] <= 4'hf;
else if (stb[3] && msb && format_byte[0]) nibble[3:0] <= {wsep,nibble_pre[2:0]};
else if (save_sent_number) nibble[3:0] <= {2'b0,sentence[1:0]};
//first_byte_in_field
extra_nibble[1:0] <= {extra_nibble[0],
msb && wsep && first_byte_in_field & proc_fields & stb[3] & format_byte[0]};// active at stb[4], stb[5]
save_sent_number <= start_format; // valid at stb[4]
nibble_stb <= save_sent_number ||
(proc_fields && ((stb[3] && bit3 && !first_byte_in_field) ||
(stb[3] && msb && !first_byte_in_field && format_byte[0]) ||
(stb[3] && msb && wsep))) || extra_nibble[1]; // extra_nibble[1] will repeat 4'hf
if (start_format) nibble_count[6:0] <= 7'h0;
else if (nibble_stb) nibble_count[6:0] <= nibble_count[6:0] + 1;
// if (weof && stb[3]) raddr[4:0] <= 5'h0;
if (sentence_over) raddr[4:0] <= 5'h0;
else if (rd_stb) raddr[4:0] <= raddr[4:0] + 1;
if (nibble_stb) last_word_written[4:0]<=nibble_count[6:2];
if (start || vfy_first_comma || (rd_stb && ((raddr[4:0]==5'h1b) ||(raddr[4:0]==last_word_written[4:0])))) rdy <= 1'b0;
else if (sentence_over) rdy <= 1'b1;
nmea_sent_start <= start_char && vfy_dollar;
end
// output buffer to hold up to 32 16-bit words. Written 1 nibble at a time
myRAM_WxD_D #( .DATA_WIDTH(4),.DATA_DEPTH(5))
i_odbuf0 (.D(nibble[3:0]),
.WE(nibble_stb && (nibble_count[1:0]==2'h0)),
.clk(xclk),
.AW(nibble_count[6:2]),
.AR(raddr[4:0]),
.QW(),
.QR(rdata[3:0]));
myRAM_WxD_D #( .DATA_WIDTH(4),.DATA_DEPTH(5))
i_odbuf1 (.D(nibble[3:0]),
.WE(nibble_stb && (nibble_count[1:0]==2'h1)),
.clk(xclk),
.AW(nibble_count[6:2]),
.AR(raddr[4:0]),
.QW(),
.QR(rdata[7:4]));
myRAM_WxD_D #( .DATA_WIDTH(4),.DATA_DEPTH(5))
i_odbuf2 (.D(nibble[3:0]),
.WE(nibble_stb && (nibble_count[1:0]==2'h2)),
.clk(xclk),
.AW(nibble_count[6:2]),
.AR(raddr[4:0]),
.QW(),
.QR(rdata[11:8]));
myRAM_WxD_D #( .DATA_WIDTH(4),.DATA_DEPTH(5))
i_odbuf3 (.D(nibble[3:0]),
.WE(nibble_stb && (nibble_count[1:0]==2'h3)),
.clk(xclk),
.AW(nibble_count[6:2]),
.AR(raddr[4:0]),
.QW(),
.QR(rdata[15:12]));
myRAM_WxD_D #( .DATA_WIDTH(4),.DATA_DEPTH(4))
i_gpxxx (.D(wd[3:0]),
.WE(we & ~wa[4]), // we_d, decoded sub_address
.clk(!sclk),
.AW(wa[3:0]),
.AR(gpxxx_addr[3:0]),
.QW(),
.QR(gpxxx_w_one[3:0]));
// for each of the four sentences first byte - number of field (<=24), next 3 bytes - formats for each nmea filed (LSB first):
// 0 - nibble ("-" -> 0xd, "." -> 0xe), terminated with 0xf
// 1 - byte (2 nibbles), all bytes but last have MSB clear, last - set.
// No padding of nibbles to byte borders, bytes are encoded as 2 nibbles
myRAM_WxD_D #( .DATA_WIDTH(8),.DATA_DEPTH(4))
i_format (.D(wd[7:0]),
.WE(we & wa[4]), // we_d, decoded sub_address
.clk(!sclk),
.AW(wa[3:0]),
.AR({sentence[1:0],format_field[4:3]}),
.QW(),
.QR(format_data[7:0]));
// ROM to decode "$GP"
always @ (posedge xclk) begin
if (ser_stb) case ({(bitnum[4] & ~ vfy_sel_sent) | vfy_first_comma, bitnum[3] | vfy_sel_sent | vfy_first_comma, bitnum[2:0]}) // during vfy_sel_sent will point to 1 ('G')
5'h00: gp_exp_bit <= 1'b0; //$
5'h01: gp_exp_bit <= 1'b0;
5'h02: gp_exp_bit <= 1'b1;
5'h03: gp_exp_bit <= 1'b0;
5'h04: gp_exp_bit <= 1'b0;
5'h05: gp_exp_bit <= 1'b1;
5'h06: gp_exp_bit <= 1'b0;
5'h07: gp_exp_bit <= 1'b0;
5'h08: gp_exp_bit <= 1'b1; //G
5'h09: gp_exp_bit <= 1'b1;
5'h0a: gp_exp_bit <= 1'b1;
5'h0b: gp_exp_bit <= 1'b0;
5'h0c: gp_exp_bit <= 1'b0;
5'h0d: gp_exp_bit <= 1'b0;
5'h0e: gp_exp_bit <= 1'b1;
5'h0f: gp_exp_bit <= 1'b0;
5'h10: gp_exp_bit <= 1'b0; //P
5'h11: gp_exp_bit <= 1'b0;
5'h12: gp_exp_bit <= 1'b0;
5'h13: gp_exp_bit <= 1'b0;
5'h14: gp_exp_bit <= 1'b1;
5'h15: gp_exp_bit <= 1'b0;
5'h16: gp_exp_bit <= 1'b1;
5'h17: gp_exp_bit <= 1'b0;
5'h18: gp_exp_bit <= 1'b0; //'h2c: "," - will use later - attach first comma to $GPxxx,
5'h19: gp_exp_bit <= 1'b0;
5'h1a: gp_exp_bit <= 1'b1;
5'h1b: gp_exp_bit <= 1'b1;
5'h1c: gp_exp_bit <= 1'b0;
5'h1d: gp_exp_bit <= 1'b1;
5'h1e: gp_exp_bit <= 1'b0;
5'h1f: gp_exp_bit <= 1'b0;
default:gp_exp_bit <= 1'bX;
endcase
end
endmodule
module imu_timestamps (
sclk, // 160MHz, negedge
xclk, // 80 MHz, posedge
rst, // reset (@posedge xclk)
sec, // running seconds (@negedge sclk)
usec, // running microseconds (@negedge sclk)
ts_rq,// requests to create timestamps (4 channels), @posedge xclk
ts_ackn, // timestamp for this channel is stored
ra, // read address (2 MSBs - channel number, 2 LSBs - usec_low, (usec_high ORed with channel <<24), sec_low, sec_high
dout);// output data
input sclk;
input xclk;
input rst;
input [31:0] sec;
input [19:0] usec;
input [ 3:0] ts_rq;
output [ 3:0] ts_ackn;
input [ 3:0] ra;
output [15:0] dout;
reg [31:0] sec_latched;
reg [19:0] usec_latched;
reg [15:0] ts_mux;
reg [ 3:0] wa;
reg srst;
reg [3:0] rq_d;
reg [3:0] rq_d2;
reg [3:0] rq_r;
reg [3:0] rq_sclk;
reg [3:0] rq_sclk2;
reg [3:0] pri_sclk;
reg [3:0] pri_sclk_d;
reg [3:0] rst_rq;
reg [9:0] proc;
wire wstart;
reg we;
wire [3:0] wrst_rq;
reg [3:0] ts_preackn;
reg [3:0] ts_ackn;
assign wstart=|pri_sclk[3:0] && (pri_sclk[3:0] != pri_sclk_d[3:0]);
assign wrst_rq[3:0]={wa[3]&wa[2],wa[3]&~wa[2],~wa[3]&wa[2],~wa[3]&~wa[2]} & {4{proc[5]}};
always @ (posedge xclk) begin
rq_d[3:0] <= ts_rq[3:0];
rq_d2[3:0] <= rq_d[3:0];
end
always @ (negedge sclk) begin
srst <= rst;
rq_sclk[3:0] <= srst?4'h0:(~rst_rq[3:0] & (rq_r[3:0] | rq_sclk[3:0])) ;
rq_sclk2[3:0] <= srst?4'h0:(~rst_rq[3:0] & rq_sclk[3:0]) ;
pri_sclk[3:0] <= {rq_sclk2[3] & ~|rq_sclk2[2:0],
rq_sclk2[2] & ~|rq_sclk2[1:0],
rq_sclk2[1] & ~rq_sclk2[0],
rq_sclk2[0]};
pri_sclk_d[3:0] <= pri_sclk[3:0];
proc[9:0] <= {proc[9:0], wstart};
if (proc[0]) wa[3:2] <= {|pri_sclk_d[3:2], pri_sclk_d[3] | pri_sclk_d[1]};
if (proc[0]) sec_latched[31:0] <= sec[31:0];
if (proc[0]) usec_latched[19:0] <= usec[19:0];
// if (proc[2]) ts_mux[15:0] <= {6'h0,wa[3:2],4'h0,usec[19:16]};
casex({proc[8],proc[6],proc[4],proc[2]})
// 4'bXXX1: ts_mux[15:0] <= {6'h0,wa[3:2],4'h0,usec_latched[19:16]};
// 4'bXX1X: ts_mux[15:0] <= usec_latched[15: 0];
// 4'bX1XX: ts_mux[15:0] <= sec_latched[31:16];
// 4'b1XXX: ts_mux[15:0] <= sec_latched[15: 0];
4'bXXX1: ts_mux[15:0] <= usec_latched[15: 0];
4'bXX1X: ts_mux[15:0] <= {6'h0,wa[3:2],4'h0,usec_latched[19:16]};
4'bX1XX: ts_mux[15:0] <= sec_latched[15: 0];
4'b1XXX: ts_mux[15:0] <= sec_latched[31:16];
endcase
we <= proc[3] || proc[5] || proc[7] || proc[9];
if (proc[2]) wa[1:0] <= 2'b0;
else if (we) wa[1:0] <= wa[1:0] + 1;
rst_rq[3:0] <= wrst_rq[3:0] | {4{srst}};
end
always @ (posedge xclk or posedge rq_sclk2[0]) begin
if (rq_sclk2[0]) rq_r[0] <= 1'b0;
else if (srst) rq_r[0] <= 1'b0;
else if (rq_d[0] && !rq_d2[0]) rq_r[0] <= 1'b1;
end
always @ (posedge xclk or posedge rq_sclk2[1]) begin
if (rq_sclk2[1]) rq_r[1] <= 1'b0;
else if (srst) rq_r[1] <= 1'b0;
else if (rq_d[1] && !rq_d2[1]) rq_r[1] <= 1'b1;
end
always @ (posedge xclk or posedge rq_sclk2[2]) begin
if (rq_sclk2[2]) rq_r[2] <= 1'b0;
else if (srst) rq_r[2] <= 1'b0;
else if (rq_d[2] && !rq_d2[2]) rq_r[2] <= 1'b1;
end
always @ (posedge xclk or posedge rq_sclk2[3]) begin
if (rq_sclk2[3]) rq_r[3] <= 1'b0;
else if (srst) rq_r[3] <= 1'b0;
else if (rq_d[3] && !rq_d2[3]) rq_r[3] <= 1'b1;
end
always @ (posedge xclk or posedge rst_rq[0]) begin
if (rst_rq[0]) ts_preackn[0] <= 1'b1;
else if (!ts_rq[0]) ts_preackn[0] <= 1'b0;
end
always @ (posedge xclk or posedge rst_rq[1]) begin
if (rst_rq[1]) ts_preackn[1] <= 1'b1;
else if (!ts_rq[1]) ts_preackn[1] <= 1'b0;
end
always @ (posedge xclk or posedge rst_rq[2]) begin
if (rst_rq[2]) ts_preackn[2] <= 1'b1;
else if (!ts_rq[2]) ts_preackn[2] <= 1'b0;
end
always @ (posedge xclk or posedge rst_rq[3]) begin
if (rst_rq[3]) ts_preackn[3] <= 1'b1;
else if (!ts_rq[3]) ts_preackn[3] <= 1'b0;
end
always @ (posedge xclk) begin
ts_ackn[3:0] <= ts_preackn[3:0] & ts_rq[3:0];
end
myRAM_WxD_D #( .DATA_WIDTH(16),.DATA_DEPTH(4))
i_ts (.D(ts_mux[15:0]),
.WE(we), // we_d, decoded sub_address
.clk(!sclk),
.AW(wa[3:0]),
.AR(ra[3:0]),
.QW(),
.QR(dout[15:0]));
endmodule
/*
** -----------------------------------------------------------------------------**
** interrupts_vector333.v
**
** Interrupts controller
**
** Copyright (C) 2005-2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// will support 16 priority (0 - highest) masked vector interrupts (pos. edge triggered), use 4 locations of address space,
// generate 32-bit data output (16MSBs - before mask, lower 16 bits - masked)
module interrupts_vector(sclk, // @negedge
pre_wen, // 1 cycle ahead of write data
pre_wa, // [1:0] - write address:
// 0 - reset selected interrupt bits
// 1 - disable selected interrupt bits (mask)
// 2 - enable selected interrupt bits
// 3 - write vector number (bits [0:7], [11:8] - interrupt number (0..15)
di, // [15:0] data in
do, // [31:0] data out (bits {15:0} - masked interrupts, [31:0] - same before mask
irq, // interrupt request (active high)
inta, // interrupt acknowledge input (active low) 170ns long
irq_in, // [15:0] input interrupt requests (posedge)
irqv); // [7:0] interrupt vector (valid befor end on inta
input sclk;
input pre_wen;
input [1:0] pre_wa;
input [15:0] di;
output [31:0] do;
output irq;
input inta;
input [15:0] irq_in;
output [7:0] irqv;
wire [15:0] irq_insa;
reg [15:0] irq_insb;
reg [15:0] irq_insc; //single cycle sync interrupt request.
wire [15:0] irq_rst;
reg rst_rqs, en_rqs, dis_rqs, pre_set_irqv, set_irqv;
reg [ 3:0] irqv_a; // irq vectors table write address
reg [ 7:0] irqv_d; // irq vectors table write data
reg [15:0] rst_rq;
reg [15:0] dis_rq;
// reg [15:0] en_rq;
wire [15:0] en_rq;
wire [15:0] irqm;
reg [ 5:0] inta_s; // inta sync to clock
// reg [15:0] irq_um; // interrupts (before mask)
wire [15:0] irq_um; // interrupts (before mask)
reg [15:0] irq_frz; // frozen masked irq-s (for the duration of the synchronized inta)
wire [15:0] irqp; // one-hot irq (prioritized)
wire [ 3:0] irqn; // encoded vector number;
reg [ 3:0] irqn_r; // registered encoded vector number (not neded to be registered?
wire [15:0] rst_rq_inta; // reset interrupts from inta
reg pre_irq;
reg [15:0] did; // did[15:0] delayed by 1 cycle
wire en_all_rq; // for simulation
assign irq=pre_irq && inta;
assign do[31:0]={irq_um[15:0], irq_frz[15:0]};
assign irqp[ 0] = irq_frz[ 0];
assign irqp[ 1] = irq_frz[ 1] && !irq_frz[ 0];
assign irqp[ 2] = irq_frz[ 2] && !(|irq_frz[ 1:0]);
assign irqp[ 3] = irq_frz[ 3] && !(|irq_frz[ 2:0]);
assign irqp[ 4] = irq_frz[ 4] && !(|irq_frz[ 3:0]);
assign irqp[ 5] = irq_frz[ 5] && !(|irq_frz[ 4:0]);
assign irqp[ 6] = irq_frz[ 6] && !(|irq_frz[ 5:0]);
assign irqp[ 7] = irq_frz[ 7] && !(|irq_frz[ 6:0]);
assign irqp[ 8] = irq_frz[ 8] && !(|irq_frz[ 7:0]);
assign irqp[ 9] = irq_frz[ 9] && !(|irq_frz[ 8:0]);
assign irqp[10] = irq_frz[10] && !(|irq_frz[ 9:0]);
assign irqp[11] = irq_frz[11] && !(|irq_frz[10:0]);
assign irqp[12] = irq_frz[12] && !(|irq_frz[11:0]);
assign irqp[13] = irq_frz[13] && !(|irq_frz[12:0]);
assign irqp[14] = irq_frz[14] && !(|irq_frz[13:0]);
assign irqp[15] = irq_frz[15] && !(|irq_frz[14:0]);
assign irqn[0]= irqp[1] | irqp[3] | irqp[ 5] | irqp[ 7] | irqp[ 9] | irqp[11] | irqp[13] | irqp[15];
assign irqn[1]= irqp[2] | irqp[3] | irqp[ 6] | irqp[ 7] | irqp[10] | irqp[11] | irqp[14] | irqp[15];
assign irqn[2]= irqp[4] | irqp[5] | irqp[ 6] | irqp[ 7] | irqp[12] | irqp[13] | irqp[14] | irqp[15];
assign irqn[3]= irqp[8] | irqp[9] | irqp[10] | irqp[11] | irqp[12] | irqp[13] | irqp[14] | irqp[15];
assign rst_rq_inta[ 0]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h0);
assign rst_rq_inta[ 1]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h1);
assign rst_rq_inta[ 2]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h2);
assign rst_rq_inta[ 3]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h3);
assign rst_rq_inta[ 4]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h4);
assign rst_rq_inta[ 5]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h5);
assign rst_rq_inta[ 6]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h6);
assign rst_rq_inta[ 7]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h7);
assign rst_rq_inta[ 8]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h8);
assign rst_rq_inta[ 9]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'h9);
assign rst_rq_inta[10]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'ha);
assign rst_rq_inta[11]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'hb);
assign rst_rq_inta[12]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'hc);
assign rst_rq_inta[13]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'hd);
assign rst_rq_inta[14]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'he);
assign rst_rq_inta[15]= inta_s[1] && !inta_s[2] && (irqn_r[3:0] == 4'hf);
FDE_1 i_en_all_rq(.C(sclk), .CE(pre_wen), .D(1'b1), .Q(en_all_rq)); // initially disabled - till first write
FDC i_insa_0 (.C(irq_in[ 0]), .CLR(irq_insc[ 0]), .D(1'b1), .Q(irq_insa[ 0]));
FDC i_insa_1 (.C(irq_in[ 1]), .CLR(irq_insc[ 1]), .D(1'b1), .Q(irq_insa[ 1]));
FDC i_insa_2 (.C(irq_in[ 2]), .CLR(irq_insc[ 2]), .D(1'b1), .Q(irq_insa[ 2]));
FDC i_insa_3 (.C(irq_in[ 3]), .CLR(irq_insc[ 3]), .D(1'b1), .Q(irq_insa[ 3]));
FDC i_insa_4 (.C(irq_in[ 4]), .CLR(irq_insc[ 4]), .D(1'b1), .Q(irq_insa[ 4]));
FDC i_insa_5 (.C(irq_in[ 5]), .CLR(irq_insc[ 5]), .D(1'b1), .Q(irq_insa[ 5]));
FDC i_insa_6 (.C(irq_in[ 6]), .CLR(irq_insc[ 6]), .D(1'b1), .Q(irq_insa[ 6]));
FDC i_insa_7 (.C(irq_in[ 7]), .CLR(irq_insc[ 7]), .D(1'b1), .Q(irq_insa[ 7]));
FDC i_insa_8 (.C(irq_in[ 8]), .CLR(irq_insc[ 8]), .D(1'b1), .Q(irq_insa[ 8]));
FDC i_insa_9 (.C(irq_in[ 9]), .CLR(irq_insc[ 9]), .D(1'b1), .Q(irq_insa[ 9]));
FDC i_insa_10 (.C(irq_in[10]), .CLR(irq_insc[10]), .D(1'b1), .Q(irq_insa[10]));
FDC i_insa_11 (.C(irq_in[11]), .CLR(irq_insc[11]), .D(1'b1), .Q(irq_insa[11]));
FDC i_insa_12 (.C(irq_in[12]), .CLR(irq_insc[12]), .D(1'b1), .Q(irq_insa[12]));
FDC i_insa_13 (.C(irq_in[13]), .CLR(irq_insc[13]), .D(1'b1), .Q(irq_insa[13]));
FDC i_insa_14 (.C(irq_in[14]), .CLR(irq_insc[14]), .D(1'b1), .Q(irq_insa[14]));
FDC i_insa_15 (.C(irq_in[15]), .CLR(irq_insc[15]), .D(1'b1), .Q(irq_insa[15]));
FD_1 i_irqm_0 (.C(sclk), .D(en_rq[ 0] || (!dis_rq[ 0] && irqm[ 0])), .Q(irqm[ 0]));
FD_1 i_irqm_1 (.C(sclk), .D(en_rq[ 1] || (!dis_rq[ 1] && irqm[ 1])), .Q(irqm[ 1]));
FD_1 i_irqm_2 (.C(sclk), .D(en_rq[ 2] || (!dis_rq[ 2] && irqm[ 2])), .Q(irqm[ 2]));
FD_1 i_irqm_3 (.C(sclk), .D(en_rq[ 3] || (!dis_rq[ 3] && irqm[ 3])), .Q(irqm[ 3]));
FD_1 i_irqm_4 (.C(sclk), .D(en_rq[ 4] || (!dis_rq[ 4] && irqm[ 4])), .Q(irqm[ 4]));
FD_1 i_irqm_5 (.C(sclk), .D(en_rq[ 5] || (!dis_rq[ 5] && irqm[ 5])), .Q(irqm[ 5]));
FD_1 i_irqm_6 (.C(sclk), .D(en_rq[ 6] || (!dis_rq[ 6] && irqm[ 6])), .Q(irqm[ 6]));
FD_1 i_irqm_7 (.C(sclk), .D(en_rq[ 7] || (!dis_rq[ 7] && irqm[ 7])), .Q(irqm[ 7]));
FD_1 i_irqm_8 (.C(sclk), .D(en_rq[ 8] || (!dis_rq[ 8] && irqm[ 8])), .Q(irqm[ 8]));
FD_1 i_irqm_9 (.C(sclk), .D(en_rq[ 9] || (!dis_rq[ 9] && irqm[ 9])), .Q(irqm[ 9]));
FD_1 i_irqm_10 (.C(sclk), .D(en_rq[10] || (!dis_rq[10] && irqm[10])), .Q(irqm[10]));
FD_1 i_irqm_11 (.C(sclk), .D(en_rq[11] || (!dis_rq[11] && irqm[11])), .Q(irqm[11]));
FD_1 i_irqm_12 (.C(sclk), .D(en_rq[12] || (!dis_rq[12] && irqm[12])), .Q(irqm[12]));
FD_1 i_irqm_13 (.C(sclk), .D(en_rq[13] || (!dis_rq[13] && irqm[13])), .Q(irqm[13]));
FD_1 i_irqm_14 (.C(sclk), .D(en_rq[14] || (!dis_rq[14] && irqm[14])), .Q(irqm[14]));
FD_1 i_irqm_15 (.C(sclk), .D(en_rq[15] || (!dis_rq[15] && irqm[15])), .Q(irqm[15]));
FD_1 i_en_rq_0 (.C(sclk), .D(en_rqs & did[ 0]), .Q(en_rq[ 0]));
FD_1 i_en_rq_1 (.C(sclk), .D(en_rqs & did[ 1]), .Q(en_rq[ 1]));
FD_1 i_en_rq_2 (.C(sclk), .D(en_rqs & did[ 2]), .Q(en_rq[ 2]));
FD_1 i_en_rq_3 (.C(sclk), .D(en_rqs & did[ 3]), .Q(en_rq[ 3]));
FD_1 i_en_rq_4 (.C(sclk), .D(en_rqs & did[ 4]), .Q(en_rq[ 4]));
FD_1 i_en_rq_5 (.C(sclk), .D(en_rqs & did[ 5]), .Q(en_rq[ 5]));
FD_1 i_en_rq_6 (.C(sclk), .D(en_rqs & did[ 6]), .Q(en_rq[ 6]));
FD_1 i_en_rq_7 (.C(sclk), .D(en_rqs & did[ 7]), .Q(en_rq[ 7]));
FD_1 i_en_rq_8 (.C(sclk), .D(en_rqs & did[ 8]), .Q(en_rq[ 8]));
FD_1 i_en_rq_9 (.C(sclk), .D(en_rqs & did[ 9]), .Q(en_rq[ 9]));
FD_1 i_en_rq_10 (.C(sclk), .D(en_rqs & did[10]), .Q(en_rq[10]));
FD_1 i_en_rq_11 (.C(sclk), .D(en_rqs & did[11]), .Q(en_rq[11]));
FD_1 i_en_rq_12 (.C(sclk), .D(en_rqs & did[12]), .Q(en_rq[12]));
FD_1 i_en_rq_13 (.C(sclk), .D(en_rqs & did[13]), .Q(en_rq[13]));
FD_1 i_en_rq_14 (.C(sclk), .D(en_rqs & did[14]), .Q(en_rq[14]));
FD_1 i_en_rq_15 (.C(sclk), .D(en_rqs & did[15]), .Q(en_rq[15]));
FD_1 i_irq_um_0 (.C(sclk), .D(~(rst_rq[ 0]) & (irq_insc[ 0] | irq_um[ 0])), .Q(irq_um[ 0]));
FD_1 i_irq_um_1 (.C(sclk), .D(~(rst_rq[ 1]) & (irq_insc[ 1] | irq_um[ 1])), .Q(irq_um[ 1]));
FD_1 i_irq_um_2 (.C(sclk), .D(~(rst_rq[ 2]) & (irq_insc[ 2] | irq_um[ 2])), .Q(irq_um[ 2]));
FD_1 i_irq_um_3 (.C(sclk), .D(~(rst_rq[ 3]) & (irq_insc[ 3] | irq_um[ 3])), .Q(irq_um[ 3]));
FD_1 i_irq_um_4 (.C(sclk), .D(~(rst_rq[ 4]) & (irq_insc[ 4] | irq_um[ 4])), .Q(irq_um[ 4]));
FD_1 i_irq_um_5 (.C(sclk), .D(~(rst_rq[ 5]) & (irq_insc[ 5] | irq_um[ 5])), .Q(irq_um[ 5]));
FD_1 i_irq_um_6 (.C(sclk), .D(~(rst_rq[ 6]) & (irq_insc[ 6] | irq_um[ 6])), .Q(irq_um[ 6]));
FD_1 i_irq_um_7 (.C(sclk), .D(~(rst_rq[ 7]) & (irq_insc[ 7] | irq_um[ 7])), .Q(irq_um[ 7]));
FD_1 i_irq_um_8 (.C(sclk), .D(~(rst_rq[ 8]) & (irq_insc[ 8] | irq_um[ 8])), .Q(irq_um[ 8]));
FD_1 i_irq_um_9 (.C(sclk), .D(~(rst_rq[ 9]) & (irq_insc[ 9] | irq_um[ 9])), .Q(irq_um[ 9]));
FD_1 i_irq_um_10 (.C(sclk), .D(~(rst_rq[10]) & (irq_insc[10] | irq_um[10])), .Q(irq_um[10]));
FD_1 i_irq_um_11 (.C(sclk), .D(~(rst_rq[11]) & (irq_insc[11] | irq_um[11])), .Q(irq_um[11]));
FD_1 i_irq_um_12 (.C(sclk), .D(~(rst_rq[12]) & (irq_insc[12] | irq_um[12])), .Q(irq_um[12]));
FD_1 i_irq_um_13 (.C(sclk), .D(~(rst_rq[13]) & (irq_insc[13] | irq_um[13])), .Q(irq_um[13]));
FD_1 i_irq_um_14 (.C(sclk), .D(~(rst_rq[14]) & (irq_insc[14] | irq_um[14])), .Q(irq_um[14]));
FD_1 i_irq_um_15 (.C(sclk), .D(~(rst_rq[15]) & (irq_insc[15] | irq_um[15])), .Q(irq_um[15]));
myRAM16X8D_1 i_vecttab (.D(irqv_d[7:0]), .WE(set_irqv), .clk(sclk), .AW(irqv_a[3:0]), .AR(irqn_r[3:0]), .QR(irqv[7:0]));
always @ (negedge sclk) begin
if (pre_wen) did[15:0] <= di[15:0];
if (en_all_rq) begin
irq_insb[15:0] <= irq_insa[15:0];
irq_insc[15:0] <= irq_insb[15:0] & (~irq_insc[15:0]);
end else begin
irq_insb[15:0] <= 16'h0;
irq_insc[15:0] <= 16'h0;
end
rst_rqs <= pre_wen && (pre_wa[1:0] == 2'h0);
dis_rqs <= pre_wen && (pre_wa[1:0] == 2'h1);
en_rqs <= pre_wen && (pre_wa[1:0] == 2'h2);
pre_set_irqv <= pre_wen && (pre_wa[1:0] == 2'h3);
set_irqv <= pre_set_irqv;
if (pre_set_irqv) irqv_a[3:0] <= did[11:8];
if (pre_set_irqv) irqv_d[7:0] <= did[ 7:0];
rst_rq[15:0] <= ({15{rst_rqs}} & did[15:0]) | rst_rq_inta[15:0];
dis_rq[15:0] <= ({15{dis_rqs}} & did[15:0]);
// en_rq [15:0] <= ({15{ en_rqs}} & did[15:0]);
inta_s[5:0] <= {inta_s[4:0], inta};
if (inta_s[1]) irq_frz[15:0] <= irq_um[15:0] & irqm[15:0];
irqn_r[3:0] <= irqn[3:0]; // will be invalid for a cycle - long combinatorial logic delays
pre_irq <= |irq_frz[15:0] & inta_s[5];
end
endmodule
module myRAM16X8D_1(D,WE,clk,AW,AR,QW,QR);
input [7:0] D;
input WE,clk;
input [3:0] AW;
input [3:0] AR;
output [7:0] QW;
output [7:0] QR;
reg [7:0] ram [0:15];
always @ (negedge clk) if (WE) ram[AW] <= D;
assign QW= ram[AW];
assign QR= ram[AR];
endmodule
/*
** -----------------------------------------------------------------------------**
** ioports353.v
**
** I/O pads related circuitry
**
** Copyright (C) 2002-2008 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 dmapads (dreq0,dack0,idreq0,idack0,dreq1,dack1,idreq1,idack1);
output dreq0,dreq1;
input dack0,dack1;
input idreq0,idreq1;
output idack0,idack1;
OBUF i_dreq0 (.I(idreq0), .O(dreq0));
IBUF i_dack0 (.I(dack0), .O(idack0));
OBUF i_dreq1 (.I(idreq1), .O(dreq1));
IBUF i_dack1 (.I(dack1), .O(idack1));
endmodule
module i2cpads (sda,scl,sda_o,sda_i,sda_en,scl_o,scl_i,scl_en);
inout sda;
inout scl;
input sda_o;
input sda_en;
output sda_i;
input scl_o;
input scl_en;
output scl_i;
IOBUF i_sda0 (.I(sda_o), .T(!sda_en), .O(sda_i), .IO(sda));
IOBUF i_scl0 (.I(scl_o), .T(!scl_en), .O(scl_i), .IO(scl));
endmodule
module sysinterface(clk,
drv_bus, // drive system bus (to write to system memory)
d, // 32 bit D[31:0] data pads
oe, // OE pad
ce, // CE pad (zero wait states)
ce1, // CE1 pad (EW=1)
we, // WE pad
a, // 13 bit A[12:0] pads
iod, // internal 32-bit data out (FPGA->CPU) bus
// as of v. 03533016 idi[31:16] is valid with da_*, twr_* and one cycle after,
// idi[15:0] is multiplexed: withda_*, twr_*it has di[15:0], next cycle = di[31:16]
idi, // internal 32-bit data in, synchronous to clk
ia, // internal 8-bit address bus (fast - directly from I/O pads)
as, // internal 8-bit address bus (synchronized to clk)
am, // multiplexed addr - switching between ia and as
wnr, // write/not read, sync with clk
da_ctl, // WE to control 32-bit register, low 24 bits (1 loc)
da_ctl_h, // enable writing to high 8 bits of the dcr
da_dmamode, // select writing to dma_cntr/dma_raw (1 loc)
da_sensormode, // select writing to sensorpix (1 loc)
da_virttrig, // write virtual trigger threshold
da_sensortrig, // sensor control: bit0 continuous, bit1 - external, bit2 - enable
da_sensortrig_lines,// write number of lines to be transferred in a frame (or aftre trigger)
da_dswe, // select reading/writing to mcontr (16 locations)
da_init_ch3, // write to init cnhannel 3 (will reset address r/w)
da_next_ch3, // advance to the next channel3 page, reset address
da_mem, // read/write to SDRAM buffer, autoincrement address
// in read mode - needs CE1 to autoincrement!
da_lensff, // lens flat field correction parameters (1 location, 8 bit address, 16bit - data)
da_hist, // 0x40..0x47 write/read histogram related data/registers
// 40 - left
// 41 - top
// 42 - width-1
// 43 - height-1
// 44 - hist. data start address (will also read pointed word to output word
da_hist_next, // 45 - read histogram (with CE1 to autoincrement)
da_rtc, // 48 - write microseconds (actual write will happen after writing seconds)
// 49 - write seconds
// 4a - write correction (16 bit, signed
// 4b - nop, just latch the output 32+20 bits to read to CPU). Maybe nop (or 2 writes) are needed between read.
da_timestamp, // 4c - write timesatmp mode (0 - off, 1 - normal frames, 1 photo-finish)
da_sens_dc, // write clock divisor for sensor DCDC converter
da_interrupts, // interrupt control 0x1c..0x1f
da_compressor, // 0x0c - 0x0f - will be farther decoded in the compressor module
da_dcm, // tune SDRAM clock
da_saturation, // write color saturation vaues (currently 10 bits
da_framesync_dly,
da_quantizer_mode, // Quantizer tuning - 0..7 - zero bin, 15:8 - quantizer bias
da_io_pins, // write i/o pins control (for 6 pins to connector J2) - 0x70
da_pio_dmafifo, // increment address of the DMA FIFO(S) (PIO mode should be enabled in the desired channel)
da_xjtag, // write to external (sensor board) JTAG
da_extsync, // control of external sync module 0x78 - 0x7b
da_extio, // external I/O (motor control 0x7c-0x7d)
da_imu, // IMU (imu r/w 0x7e-0x7f)
// da_imu_read, // read any of the IMU data/status (updates memory output reg)
// da_imu_next, // read IMU dataread from pointer, increment address
da_i2c, // i2c_writeonly control (0x50 - 0x5f)
da_irq_smart, // single IRQ control (0x1a)
da_sequencer, // command sequencer (0x60..0x6f)
da_dcr, // write to control registers (0x4e..0x4f), each bit/group with individual enable by data bit
ta, // [10:0] table address - will be valid at twr_xx and one cycle beforfe (@ negedge clk)
twr_quant, // write enable to quantization table (@negedge clk - addr and data valid this cycle and one before)
twr_coring, // coring functions tables (@negedge clk - addr and data valid this cycle and one before)
twr_huff, // write enable to huffman table (@negedge clk - addr and data valid this cycle and one before)
twr_gamma, // write enable to "gamma" table (@negedge clk - addr and data valid this cycle and one before)
twr_focus, // write enable to "focus" table (@negedge clk - addr and data valid this cycle and one before)
dcmrst, // (emergency)async DCM reset Seems SE hangs if the frequency changed on the fly
ioe, // OE after IBUF
seq_rq, // request from the sequencer
seq_ack, // sequencer acknowledge
seq_a, // address from the sequencer
seq_d // data from the sequencer
);
input clk;
input drv_bus;
inout [31:0] d;
input oe;
input ce;
input ce1;
input we;
inout [12:0] a;
input [31:0] iod;
output [31:0] idi;
output [7:0] ia;
output [7:0] as; // output clock-synchronous address
output [7:0] am;
output wnr;
output [11:0] ta;
output twr_quant;
output twr_coring;
output twr_huff;
output twr_gamma;
output twr_focus;
output da_ctl; // WE to control 32-bit register (1 loc) (lower 25 bits)
output da_ctl_h; // WE to control 32-bit register (1 loc) (top 8 bits)
output da_dmamode; // select writing to dma_cntr/dma_raw (1 loc)
output da_sensormode; // select writing to sensorpix (1 loc)
output da_virttrig; // write virtual trigger threshold
output da_sensortrig; // sensor control: bit0 continuous, bit1 - external, bit2 - enable
output da_sensortrig_lines; // write number of lines to be transferred in a frame (or aftre trigger)
output da_dswe; // select reading/writing to mcontr (16 locations)
output da_init_ch3; // write to init cnhannel 3 (will reset address r/w)
output da_next_ch3; // advance to the next channel3 page, reset address
output da_mem; // read/write to SDRAM buffer, autoincrement address
// in read mode - needs CE1 to autoincrement!
output da_lensff; // lens flat field correction parameters (1 location, 8 bit address, 16bit - data)
output da_sens_dc; // write clock divisor for sensor DCDC converter
output da_interrupts; // interrupt mask
output da_compressor; // 0x0c - 0x0f - will be farther decoded in the compressor module
output da_dcm; // tune SDRAM clock
output da_saturation; // write color saturation vaues (currently 10 bits
output da_quantizer_mode; // Quantizer tuning - 0..7 - zero bin, 15:8 - quantizer bias
output da_hist; // write/read histogram related data/registers
output da_hist_next;
output da_framesync_dly;
output da_io_pins; // write i/o pins control (for 6 pins to connector J2) - 0x70
output da_rtc;
output da_timestamp; // 4c - write timesatmp mode (0 - off, 1 - normal frames, 1 photo-finish)
output dcmrst; // async
output da_pio_dmafifo; // increment address of the DMA FIFO(S) (PIO mode should be enabled in the desired channel)
output da_xjtag; // write to external (sensor board) JTAG
output da_extsync; // control of external sync module 0x78 - 0x7b
output da_extio; // external I/O (motor control 0x7c-0x7d)
output da_imu; // IMU
// output da_imu_read; // read any of the IMU data/status (updates memory output reg)
// output da_imu_next; // read IMU data: read from pointer, increment address
output da_i2c; // i2c_writeonly control (0x50 - 0x5f)
output da_irq_smart; // single IRQ control (0x1a)
output da_sequencer; // command sequencer (0x60..0x6f)
output da_dcr; // write to control registers (0x4e..0x4f), each bit/group with individual enable by data bit
output ioe;
input seq_rq; // request from the sequencer
output seq_ack; // sequencer acknowledge
input [ 7:0] seq_a; // address from the sequencer
input [23:0] seq_d; // data from the sequencer
reg dcmrst;
wire cwr;
wire iwe;
reg [31:0] idi;
wire t;
wire ioe;
wire ice;
wire ice1;
wire irnw;
wire [ 7:0] ial; // enabled during oe/we high, held - during low
reg wnr;
wire [31:0] id0; //registered at the end of !cwr
reg [ 7:0] ia0; //registered at the end of !cwr
reg irnw0;//registered at the end of !cwr
reg [ 7:0] as; // output clock-synchronous address
reg da_ctl; // WE to control 32-bit register (1 loc)
reg da_ctl_h; // enable writing to high 8 bits of the dcr
reg da_dmamode; // select writing to dma_cntr/dma_raw (1 loc)
reg da_sensormode; // select writing to sensorpix (1 loc)
reg da_virttrig; // write virtual trigger threshold
reg da_sensortrig; // sensor control: bit0 continuous, bit1 - external, bit2 - enable
reg da_sensortrig_lines; // write number of lines to be transferred in a frame (or aftre trigger)
reg da_dswe; // select reading/writing to mcontr (16 locations)
reg da_init_ch3; // write to init cnhannel 3 (will reset address r/w)
reg da_next_ch3; // advance to the next channel3 page, reset address
reg da_mem; // read/write to SDRAM buffer, autoincrement address
reg da_lensff; // lens flat field correction parameters (1 location, 8 bit address, 16bit - data)
reg da_sens_dc; // write clock divisor for sensor DCDC converter
reg da_interrupts; // interrupt mask
reg da_compressor; // 0x0c - 0x0f - will be farther decoded in the compressor module
reg da_dcm; // tune SDRAM clock phase
reg da_table_a; // write table address (internal)
reg da_saturation; // write color saturation values
reg da_quantizer_mode;// Quantizer tuning - 0..7 - zero bin, 15:8 - quantizer bias
reg da_hist; // write/read histogram related data/registers
reg da_framesync_dly;
reg da_io_pins; // write i/o pins control (for 6 pins to connector J2) - 0x70
reg da_rtc;
reg da_timestamp;
reg da_pio_dmafifo0, da_pio_dmafifo; // increment address of the DMA FIFO(S) (PIO mode should be enabled in the desired channel)
reg da_xjtag; // write to external (sensor board) JTAG
reg da_extsync; // control of external sync module 0x78 - 0x7b
reg da_extio; // external I/O (motor control 0x7c-0x7d)
reg da_imu; // imu control
reg da_i2c; // i2c_writeonly control (0x50 - 0x5f)
reg da_sequencer; // command sequencer (0x60..0x6f)
reg da_dcr; // write to control registers (0x4e..0x4f), each bit/group with individual enable by data bit
reg da_irq_smart; // single IRQ control (0x1a)
reg twr; // write table data (address will be incremented 1 cycle after
reg da_hist_next0, da_hist_next; // reading histogram - ASAP, nosequencer - use sync2
// reg da_imu_read0, da_imu_read; // read any of the IMU data/status (updates memory output reg)
// reg da_imu_next0, da_imu_next; // read IMU dataread from pointer, increment address
reg [11:0] pre_ta; // one cycle ahead of ta
reg [11:0] ta; // table address. valid with twr_* and 1 cycle after
reg twr_quant;
reg twr_coring; // coring functions tables (@negedge clk - addr and data valid this cycle and one before)
reg twr_huff;
reg twr_gamma;
reg twr_focus;
wire [7:0] am;
reg wra; // to select source of as - for 2 cycles during sync write will use as, else - ia;
// inter-clock synchronization
wire sync0; // from end of the cwr low to sync2
wire sync1; // sync0 registered @negedge sclk
wire sync2; // sync1 registered @posedge sclk
wire sync_cwr_start0; // from start of the cwr low to sync_cwr_start2
wire sync_cwr_start1; // sync_cwr_start0 registered @negedge sclk
wire sync_cwr_start2; // sync_cwr_start1 registered @posedge sclk
wire sync_cwr_on; // from sync_cwr_start1 to sync1, registered @posedge sclk
reg [7:0] a_pio_seq_mux; // address, multiplexed between direct/sequencer access (valid @wr_state[0])
reg wnr_seq_mux; // write/not read, multiplexed between direct/sequencer access (valid @wr_state[0])
reg [31:0] d_pio_seq_mux; // data, multiplexed between direct/sequencer access (valid @wr_state[0])
reg seq_ack; // using data from sequencer (first cycle)
// reg [2:0] wr_state; // 1-hot write sequence for both pio and seq.
reg [1:0] wr_state; // 1-hot write sequence for both pio and seq.
// [0] - decoding address,
// [1] - output low 16 (32)
// [2] - output high 16 (8)
assign am[7:0]= wra? as[7:0] : ia[7:0];
IBUF i_oe (.I(oe), .O(ioe ));
IBUF i_ce (.I(ce), .O(ice ));
IBUF i_ce1 (.I(ce1), .O(ice1));
ipadql i_we (.g(cwr),.q(iwe),.qr(irnw),.d(we));
// negative pulse - with CE (zero w.s.) - only with WE, with CE1 (EW=1) - both WE and OE
BUFG i_cwr (.I((ice | iwe) & (ice1 | (iwe & ioe))), .O(cwr));
wire [12:0] ao=13'b0;
always @ (negedge clk) begin
// wr_state[2:0] <= {wr_state[1:0], (~wr_state[0] & ~ sync_cwr_on & seq_rq) | sync2};
wr_state[1:0] <= {wr_state[0], (~wr_state[0] & ~ sync_cwr_on & seq_rq) | sync2};
seq_ack <= ~wr_state[0] & ~(sync_cwr_on | sync2) & seq_rq;
if (sync2) a_pio_seq_mux[7:0] <= ia0[7:0];
else a_pio_seq_mux[7:0] <= seq_a[7:0];
wnr_seq_mux <= !sync2 || !irnw0; // sequencer - write only
if (sync2) d_pio_seq_mux[31:0] <= id0[31:0];
else d_pio_seq_mux[31:0] <= {8'b0,seq_d[23:0]};
end
always @ (negedge clk) begin
if (wr_state[0]) as[7:0] <= a_pio_seq_mux[7:0];
if (wr_state[0]) wnr <= wnr_seq_mux;
wra <= wr_state[0] && wnr_seq_mux;
if (wr_state[0]) idi[31:16] <= d_pio_seq_mux[31:16];
if (wr_state[0]) idi[15: 0] <= d_pio_seq_mux[15:0];
else if (wr_state[1]) idi[15: 0] <= idi[31:16];
end
// these signals will be valid after the end of the CPU r/w cycle
always @ (posedge cwr) begin
ia0[7:0] <= ial[7:0];
irnw0 <= irnw;
da_hist_next0 <= irnw && (ial[7:0]==8'h45); // read from 0x45 (ASAP, no sequencer!)
// da_imu_read0 <= irnw && (ial[7:1]==7'h3f); // 0x7e..0x7f, read
// da_imu_next0 <= irnw && (ial[7:0]==8'h7e); // 0x7e, read
dcmrst <= !irnw && (ial[7:0]==8'h1b); // 0x1b async signal to restart DCMs
da_pio_dmafifo0 <= irnw && (ial[7:1]==7'h0); // 0x0..0x01, read
end
always @ (negedge clk) begin
da_hist_next <= sync2 && da_hist_next0; // ASAP, no sequencer!
// da_imu_read <= sync2 && da_imu_read0; // 0x7e..0x7f, read
// da_imu_next <= sync2 && da_imu_next0; // 0x7e, read
da_pio_dmafifo <= sync2 && da_pio_dmafifo0;
ta[11:0] <= pre_ta[11:0];
end
always @ (negedge clk) begin
da_ctl_h <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h00); // 0x00 WE to control 32-bit register (1 loc)
da_dmamode <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h01); // 0x01 select writing to dma_cntr/dma_raw (1 loc)
da_sensormode <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h02); // 0x02 select writing to sensorpix (1 loc)
da_virttrig <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h03); // 0x03 write virtual trigger threshold
da_sensortrig <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h04); // 0x04 select writing to sensorpix (1 loc)
da_sensortrig_lines<= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h05); // 0x05 write number of lines to be transferred in a frame (or aftre trigger)
da_ctl <= wr_state[0] && wnr_seq_mux && ((a_pio_seq_mux[7:0]==8'h06) || (a_pio_seq_mux[7:0]==8'h00)); //0x00, 0x06
da_sens_dc <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h07); // 0x07 write to sensor DCDC converter frequency divider
da_dcm <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h08); // 0x08 tune SDRAM clock phase
da_saturation <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h09); // 0x09 write color saturation values
da_framesync_dly <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h0a); // 0x0a write frame sync interrupt delay (in scan lines)
da_quantizer_mode <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h0b); // 0x0b Quantizer tuning - 0..7 - zero bin, 15:8 - quantizer bias
da_compressor <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:1]==7'h06); // 0x0c..0x0d - will be farther decoded in the compressor module
da_table_a <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h0e); // 0x0e - write tables address
twr <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:0]==8'h0f); // 0x0f - write tables data
da_irq_smart <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h1a); // 0x1a single IRQ control
da_interrupts <= wr_state[0] && (a_pio_seq_mux[7:2]==6'h07); // 0x1c - 0x1f interrup control
da_dswe <= wr_state[0] && (a_pio_seq_mux[7:4]==4'h2 ); // 0x2x select reading/writing to mcontr (16 locations)
da_init_ch3 <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h2c); // 0x2c write to init cnhannel 3 (will reset address r/w)
da_next_ch3 <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h2f); // 0x2f advance to the next channel3 page, reset address
da_mem <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h30); // 0x30 read/write to SDRAM buffer, autoincrement address
da_lensff <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h31); // 0x31 lens flat field correction parameters (1 location, 8 bit address, 16bit - data)
twr_quant <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h0f) && (pre_ta[11: 9] ==3'h0); // 3'h0
twr_huff <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h0f) && (pre_ta[11: 9] ==3'h1); // 3'h1
twr_gamma <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h0f) && (pre_ta[11:10] ==2'h1); // 3'h2..3'h3
twr_focus <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h0f) && (pre_ta[11:10] ==2'h2); // 3'h4..3'h5
twr_coring <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h0f) && (pre_ta[11: 9] ==3'h6); // 3'h6 (3'h7 spare)
if (da_table_a) pre_ta[11:0]<= idi[11:0]; //d_pio_seq_mux[11:0];
else if (twr) pre_ta[11:0]<= pre_ta[11:0]+1;
da_hist <= wr_state[0] && (a_pio_seq_mux[7:3]==5'h08); // 0x40..0x47write/read histogram related data/registers
da_rtc <= wr_state[0] && (a_pio_seq_mux[7:2]==6'h12); // 0x48..0x4b
da_timestamp <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h4c); // 0x4c write timestamp mode
// da_dcr <= wr_state[0] && (a_pio_seq_mux[7:1]==7'h27); // 0x4e - 0x4f write to control registers, each bit/group with individual enable by data bit
// now da_dcr overlaps with 0x4c (timestamp mode), will be decoded in the control_regs module
da_dcr <= wr_state[0] && (a_pio_seq_mux[7:2]==6'h13); // 0x4c - 0x4f write to control registers, each bit/group with individual enable by data bit
da_i2c <= wr_state[0] && (a_pio_seq_mux[7:4]==4'h5); // 0x50 - 0x5f i2c_writeonly control
da_sequencer <= wr_state[0] && (a_pio_seq_mux[7:4]==4'h6); // 0x60 - 0x6f command sequencer
da_io_pins <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h70); // 0x70 write i/o pins control (for 6 pins to connector J2) - 0x70
da_xjtag <= wr_state[0] && (a_pio_seq_mux[7:0]==8'h74); // 0x74 write to external (sensor board) JTAG
da_extsync <= wr_state[0] && (a_pio_seq_mux[7:2]==6'h1e); // 0x78 - 0x7b control of external sync module
// TODO: add "wnr_seq_mux &&" where appropriate, otherwise pulse is generated on read with CE1 ! *****************
da_extio <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:1]==7'h3e); // external I/O (motor control 0x7c-0x7d)
da_imu <= wr_state[0] && wnr_seq_mux && (a_pio_seq_mux[7:1]==7'h3f); // IMU control (0x7e-0x7f)
end
bpadql i_a0 (.g(cwr),.q(ia[ 0]),.qr(ial[ 0]),.io(a[ 0]),.t(!drv_bus),.d(ao[ 0]));
bpadql i_a1 (.g(cwr),.q(ia[ 1]),.qr(ial[ 1]),.io(a[ 1]),.t(!drv_bus),.d(ao[ 1]));
bpadql i_a2 (.g(cwr),.q(ia[ 2]),.qr(ial[ 2]),.io(a[ 2]),.t(!drv_bus),.d(ao[ 2]));
bpadql i_a3 (.g(cwr),.q(ia[ 3]),.qr(ial[ 3]),.io(a[ 3]),.t(!drv_bus),.d(ao[ 3]));
bpadql i_a4 (.g(cwr),.q(ia[ 4]),.qr(ial[ 4]),.io(a[ 4]),.t(!drv_bus),.d(ao[ 4]));
bpadql i_a5 (.g(cwr),.q(ia[ 5]),.qr(ial[ 5]),.io(a[ 5]),.t(!drv_bus),.d(ao[ 5]));
bpadql i_a6 (.g(cwr),.q(ia[ 6]),.qr(ial[ 6]),.io(a[ 6]),.t(!drv_bus),.d(ao[ 6]));
bpadql i_a7 (.g(cwr),.q(ia[ 7]),.qr(ial[ 7]),.io(a[ 7]),.t(!drv_bus),.d(ao[ 7]));
bpadql i_a8 (.g(cwr),.q(), .qr(), .io(a[ 8]),.t(!drv_bus),.d(ao[ 8]));
bpadql i_a9 (.g(cwr),.q(), .qr(), .io(a[ 9]),.t(!drv_bus),.d(ao[ 9]));
bpadql i_a10(.g(cwr),.q(), .qr(), .io(a[10]),.t(!drv_bus),.d(ao[10]));
bpadql i_a11(.g(cwr),.q(), .qr(), .io(a[11]),.t(!drv_bus),.d(ao[11]));
bpadql i_a12(.g(cwr),.q(), .qr(), .io(a[12]),.t(!drv_bus),.d(ao[12]));
// inter-clock synchronization
FDCE i_sync0 (.Q(sync0), .C(cwr),.CE(1'b1),.CLR(sync2),.D(1'b1));
FD_1 i_sync1 (.Q(sync1), .C(clk),.D(sync0 && ! sync1));
FD i_sync2 (.Q(sync2), .C(clk),.D(sync1));
FDCE_1 i_sync_cwr_start0 (.Q(sync_cwr_start0),.C(cwr),.CE(1'b1),.CLR(sync_cwr_start2),.D(1'b1));
FD_1 i_sync_cwr_start1 (.Q(sync_cwr_start1),.C(clk),.D(sync_cwr_start0 && ! sync_cwr_start1));
FD i_sync_cwr_start2 (.Q(sync_cwr_start2),.C(clk),.D(sync_cwr_start1));
FD i_sync_cwr_on (.Q(sync_cwr_on), .C(clk),.D(sync_cwr_start1 || (sync_cwr_on && !sync1)));
LUT4 i_dataouten ( .I0(1'b1), .I1(ice1), .I2(ice), .I3(ioe), .O(t));
//synthesis translate_off
defparam i_dataouten.INIT = 16'hAA80;
//synthesis translate_on
//synthesis attribute INIT of i_dataouten is "AA80"
dpads32 i_dmapads32(.c(cwr),.t(t),.d(iod[31:0]),.q(id0[31:0]),.dq(d[31:0]));
endmodule
module dpads32(c,t,d,q,dq);
input c,t;
input [31:0] d;
output [31:0] q;
inout [31:0] dq;
wire t0, t1;
// s---ynthesis attribute KEEP_HIERARCHY of i_t0 is true
// s---ynthesis attribute KEEP_HIERARCHY of i_t1 is true
BUF i_t0 (.I(t), .O(t0));
BUF i_t1 (.I(t), .O(t1));
dio1 i_d0 (.c(c),.t(t0),.d(d[ 0]),.q(q[ 0]),.dq(dq[ 0]));
dio1 i_d1 (.c(c),.t(t0),.d(d[ 1]),.q(q[ 1]),.dq(dq[ 1]));
dio1 i_d2 (.c(c),.t(t0),.d(d[ 2]),.q(q[ 2]),.dq(dq[ 2]));
dio1 i_d3 (.c(c),.t(t0),.d(d[ 3]),.q(q[ 3]),.dq(dq[ 3]));
dio1 i_d4 (.c(c),.t(t0),.d(d[ 4]),.q(q[ 4]),.dq(dq[ 4]));
dio1 i_d5 (.c(c),.t(t0),.d(d[ 5]),.q(q[ 5]),.dq(dq[ 5]));
dio1 i_d6 (.c(c),.t(t0),.d(d[ 6]),.q(q[ 6]),.dq(dq[ 6]));
dio1 i_d7 (.c(c),.t(t0),.d(d[ 7]),.q(q[ 7]),.dq(dq[ 7]));
dio1 i_d8 (.c(c),.t(t0),.d(d[ 8]),.q(q[ 8]),.dq(dq[ 8]));
dio1 i_d9 (.c(c),.t(t0),.d(d[ 9]),.q(q[ 9]),.dq(dq[ 9]));
dio1 i_d10 (.c(c),.t(t1),.d(d[10]),.q(q[10]),.dq(dq[10]));
dio1 i_d11 (.c(c),.t(t1),.d(d[11]),.q(q[11]),.dq(dq[11]));
dio1 i_d12 (.c(c),.t(t1),.d(d[12]),.q(q[12]),.dq(dq[12]));
dio1 i_d13 (.c(c),.t(t1),.d(d[13]),.q(q[13]),.dq(dq[13]));
dio1 i_d14 (.c(c),.t(t1),.d(d[14]),.q(q[14]),.dq(dq[14]));
dio1 i_d15 (.c(c),.t(t1),.d(d[15]),.q(q[15]),.dq(dq[15]));
dio1 i_d16 (.c(c),.t(t1),.d(d[16]),.q(q[16]),.dq(dq[16]));
dio1 i_d17 (.c(c),.t(t0),.d(d[17]),.q(q[17]),.dq(dq[17]));
dio1 i_d18 (.c(c),.t(t1),.d(d[18]),.q(q[18]),.dq(dq[18]));
dio1 i_d19 (.c(c),.t(t1),.d(d[19]),.q(q[19]),.dq(dq[19]));
dio1 i_d20 (.c(c),.t(t1),.d(d[20]),.q(q[20]),.dq(dq[20]));
dio1 i_d21 (.c(c),.t(t1),.d(d[21]),.q(q[21]),.dq(dq[21]));
dio1 i_d22 (.c(c),.t(t0),.d(d[22]),.q(q[22]),.dq(dq[22]));
dio1 i_d23 (.c(c),.t(t1),.d(d[23]),.q(q[23]),.dq(dq[23]));
dio1 i_d24 (.c(c),.t(t0),.d(d[24]),.q(q[24]),.dq(dq[24]));
dio1 i_d25 (.c(c),.t(t1),.d(d[25]),.q(q[25]),.dq(dq[25]));
dio1 i_d26 (.c(c),.t(t0),.d(d[26]),.q(q[26]),.dq(dq[26]));
dio1 i_d27 (.c(c),.t(t0),.d(d[27]),.q(q[27]),.dq(dq[27]));
dio1 i_d28 (.c(c),.t(t0),.d(d[28]),.q(q[28]),.dq(dq[28]));
dio1 i_d29 (.c(c),.t(t0),.d(d[29]),.q(q[29]),.dq(dq[29]));
dio1 i_d30 (.c(c),.t(t1),.d(d[30]),.q(q[30]),.dq(dq[30]));
dio1 i_d31 (.c(c),.t(t1),.d(d[31]),.q(q[31]),.dq(dq[31]));
endmodule
module sddrio16(c0,/*c90,*/c270,d,t,q,dq); //added an extra FF for the t signal
input c0,/*c90,*/c270;
input [31:0] d;
input t;
output [31:0] q;
inout [15:0] dq;
wire [31:0] q;
sddrio0 i_dq0 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[16],d[ 0]}),.t(t),.q({q[16],q[ 0]}),.dq(dq[ 0]));
sddrio0 i_dq1 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[17],d[ 1]}),.t(t),.q({q[17],q[ 1]}),.dq(dq[ 1]));
sddrio0 i_dq2 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[18],d[ 2]}),.t(t),.q({q[18],q[ 2]}),.dq(dq[ 2]));
sddrio0 i_dq3 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[19],d[ 3]}),.t(t),.q({q[19],q[ 3]}),.dq(dq[ 3]));
sddrio0 i_dq4 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[20],d[ 4]}),.t(t),.q({q[20],q[ 4]}),.dq(dq[ 4]));
sddrio0 i_dq5 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[21],d[ 5]}),.t(t),.q({q[21],q[ 5]}),.dq(dq[ 5]));
sddrio0 i_dq6 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[22],d[ 6]}),.t(t),.q({q[22],q[ 6]}),.dq(dq[ 6]));
sddrio0 i_dq7 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[23],d[ 7]}),.t(t),.q({q[23],q[ 7]}),.dq(dq[ 7]));
sddrio0 i_dq8 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[24],d[ 8]}),.t(t),.q({q[24],q[ 8]}),.dq(dq[ 8]));
sddrio0 i_dq9 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[25],d[ 9]}),.t(t),.q({q[25],q[ 9]}),.dq(dq[ 9]));
sddrio0 i_dq10 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[26],d[10]}),.t(t),.q({q[26],q[10]}),.dq(dq[10]));
sddrio0 i_dq11 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[27],d[11]}),.t(t),.q({q[27],q[11]}),.dq(dq[11]));
sddrio0 i_dq12 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[28],d[12]}),.t(t),.q({q[28],q[12]}),.dq(dq[12]));
sddrio0 i_dq13 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[29],d[13]}),.t(t),.q({q[29],q[13]}),.dq(dq[13]));
sddrio0 i_dq14 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[30],d[14]}),.t(t),.q({q[30],q[14]}),.dq(dq[14]));
sddrio0 i_dq15 (.c0(c0),/*.c90(c90),*/.c270(c270),.d({d[31],d[15]}),.t(t),.q({q[31],q[15]}),.dq(dq[15]));
// s---ynthesis attribute KEEP_HIERARCHY of i_dq0 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq1 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq2 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq3 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq4 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq5 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq6 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq7 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq8 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq9 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq10 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq11 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq12 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq13 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq14 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_dq15 is "TRUE"
endmodule
// Made for CL=2.5
// all data to write is expected to be sync to posedge of c0 - phase=0,
// data to sdram is clocked at c270 (LSW) and c90 (MSW)
// MSB will be delayed by half-cycle internally
// tristate will be clocked at rising edge of c270
// All data read will be also sync to rising edge of c0 (LSB will be delayed internally)
module sddrio0(c0,/*c90,*/c270,d,t,q,dq); // made for CL=2.5, LSB first - c0 falling edge is before rising, gets LSB
input c0,/*c90,*/c270;
input [1:0] d;
input t;
output [1:0] q;
inout dq;
wire dr,t0,t1,tr,qp,q00,d1d;
wire [1:0] d0;
FD i_d00 (.C(c0), .D(d[0]), .Q(d0[0])); //regular FF, not IOB
FD i_d01 (.C(c0), .D(d[1]), .Q(d0[1])); //regular FF, not IOB
FD i_d1d (.C(c270),.D(d0[1]),.Q(d1d)); //regular FF, not IOB
FD_1 i_q0 (.C(c0),.D(q00),.Q(q[0])); //regular FF, not IOB
IOBUF i_dq (.I(dr), .T(tr),.O(qp), .IO(dq));
FDDRCPE i_dr (.Q(dr),.C0(c270),.C1(!c270),.D0(d0[0]),.D1(d1d),.CE(1'b1),.CLR(1'b0),.PRE(1'b0));
FD_1 i_t0 (.C(c0), .D(t), .Q(t0));
FD i_t1 (.C(c0), .D(t0), .Q(t1));
FD i_tr (.C(c270), .D(t1), .Q(tr));
IDDR2 i_qq(.Q0(q00),.Q1(q[1]),.C0(c0),.C1(!c0),.CE(1'b1), .D(qp), .R(1'b0), .S(1'b0) );
// synthesis translate_off
defparam i_t0.INIT = 1'b1;
defparam i_t1.INIT = 1'b1;
defparam i_tr.INIT = 1'b1;
// synthesis translate_on
// synthesis attribute INIT of i_t0 is "1"
// synthesis attribute INIT of i_t1 is "1"
// synthesis attribute INIT of i_tr is "1"
// synthesis attribute IOB of i_dr is "TRUE"
// synthesis attribute IOB of i_tr is "TRUE"
// synthesis attribute NODELAY of i_dq is "TRUE"
endmodule
module dqs2 (c0,/*c90,*/c270,
t, // 1.5 cycles before cmd "write" sent out to the SDRAM, sync to sclk180
UDQS, // UDQS I/O pin
LDQS, // LDQS I/O pin
udqsr90, // data from SDRAM interface pin UDQS strobed at rising sclk90
ldqsr90, // data from SDRAM interface pin LDQS strobed at rising sclk90
udqsr270, // data from SDRAM interface pin UDQS strobed at rising sclk270
ldqsr270 // data from SDRAM interface pin UDQS strobed at rising sclk270
);
input c0,/*c90,*/c270,t;
inout UDQS, LDQS;
output udqsr90,ldqsr90,udqsr270,ldqsr270;
wire t0,t1,t2,tr;
FD_1 i_t0 (.C(c0),.D(t),.Q(t0));
FD i_t1 (.C(c0),.D(t0),.Q(t1));
FD i_t2 (.C(c270),.D(t0),.Q(t2));
// FDDRCPE i_tr (.Q(tr),.C0(c0),.C1(c270),.D0(t),.D1(t | t0),.CE(1'b1),.CLR(1'b0),.PRE(1'b0));
// FDDRCPE i_tr (.Q(tr),.C0(c0),.C1(c270),.D0(t0),.D1(t0 | t1),.CE(1'b1),.CLR(1'b0),.PRE(1'b0));
// assign tr= t1 || t2; // ************** try this later if delays will be too high ***********************
assign tr= t1;
dqs2_0 i_dqsu(.c0(c0),/*.c90(c90),*/.c270(c270),.t(tr),.q({udqsr270,udqsr90}),.dq(UDQS));
dqs2_0 i_dqsl(.c0(c0),/*.c90(c90),*/.c270(c270),.t(tr),.q({ldqsr270,ldqsr90}),.dq(LDQS));
// synthesis translate_off
defparam i_t0.INIT = 1'b1;
defparam i_t1.INIT = 1'b1;
defparam i_t2.INIT = 1'b1;
// synthesis translate_on
// synthesis attribute INIT of i_t0 is "1"
// synthesis attribute INIT of i_t1 is "1"
// synthesis attribute INIT of i_t2 is "1"
// s---ynthesis attribute KEEP_HIERARCHY of i_t0 is "TRUE"
// s---ynthesis attribute KEEP_HIERARCHY of i_tr is "TRUE"
endmodule
module dqs2_0(c0,/*c90,*/c270,t,q,dq);
input c0,/*c90,*/c270;
input t;
output [1:0] q;
inout dq;
wire qp;
wire virtc0; // sync to c0
IOBUF i_dq (.I(virtc0), .T(t),.O(qp), .IO(dq));
// reset DQS when tristated
FDDRCPE i_dr (.Q(virtc0),.C0(c0),.C1(!c0),.D0(1'b1),.D1(1'b0),.CE(1'b1),.CLR(t),.PRE(1'b0));
// as in IFDDRCPE.v
// FDCPE i_q0 (.C(c90), .CE(1'b1),.CLR(1'b0),.D(qp),.PRE(1'b0),.Q(q[0]));
FDCPE_1 i_q0 (.C(c270), .CE(1'b1),.CLR(1'b0),.D(qp),.PRE(1'b0),.Q(q[0]));
defparam i_q0.INIT = 1'b0;
FDCPE i_q1 (.C(c270),.CE(1'b1),.CLR(1'b0),.D(qp),.PRE(1'b0),.Q(q[1]));
// defparam i_q1.INIT = 1'b0;
// synthesis attribute IOB of i_q0 is "TRUE"
// synthesis attribute IOB of i_q1 is "TRUE"
// synthesis attribute FAST of i_dq is "TRUE"
// synthesis attribute NODELAY of i_dq is "TRUE"
endmodule
//both bits are strobed at rising c270
module sddrdm(c0,/*c90,*/c270,d,dq);
input c0,/*c90,*/c270;
input [1:0] d;
inout dq;
sddrdm0 i_dq (.c0(c0),/*.c90(c90),*/.c270(c270),.d(d),.dq(dq));
// s--ynthesis attribute KEEP_HIERARCHY of i_dq is "TRUE"
endmodule
module sddrdm0(c0,/*c90,*/c270,d,dq);
input c0,/*c90,*/c270;
input [1:0] d;
output dq;
wire dr,d1d;
wire [1:0] d0;
OBUF i_dq (.I(dr), .O(dq));
// FDDRCPE i_dr (.Q(dr),.C0(c270),.C1(c90),.D0(d0[0]),.D1(d1d),.CE(1'b1),.CLR(1'b0),.PRE(1'b0));
FDDRCPE i_dr (.Q(dr),.C0(c270),.C1(!c270),.D0(d0[0]),.D1(d1d),.CE(1'b1),.CLR(1'b0),.PRE(1'b0));
FD i_d00(.C(c0),.D(d[0]),.Q(d0[0])); //regular FF, not IOB
FD i_d01(.C(c0),.D(d[1]),.Q(d0[1])); //regular FF, not IOB
FD i_d1d(.C(c270),.D(d0[1]),.Q(d1d)); //regular FF, not IOB
// synthesis attribute IOB of i_dr is "TRUE"
// synthesis attribute NODELAY of i_dq is "TRUE"
endmodule
// SDRAM address and ras/cas/we
module sdo15_2(c,d,q); // inputs at rising edge, resyncs to falling edge, all go high at reset
input c;
input [14:0] d;
output [14:0] q;
sdo1_2 i_q0 (.c(c),.d(d[ 0]),.q(q[ 0]));
sdo1_2 i_q1 (.c(c),.d(d[ 1]),.q(q[ 1]));
sdo1_2 i_q2 (.c(c),.d(d[ 2]),.q(q[ 2]));
sdo1_2 i_q3 (.c(c),.d(d[ 3]),.q(q[ 3]));
sdo1_2 i_q4 (.c(c),.d(d[ 4]),.q(q[ 4]));
sdo1_2 i_q5 (.c(c),.d(d[ 5]),.q(q[ 5]));
sdo1_2 i_q6 (.c(c),.d(d[ 6]),.q(q[ 6]));
sdo1_2 i_q7 (.c(c),.d(d[ 7]),.q(q[ 7]));
sdo1_2 i_q8 (.c(c),.d(d[ 8]),.q(q[ 8]));
sdo1_2 i_q9 (.c(c),.d(d[ 9]),.q(q[ 9]));
sdo1_2 i_q10 (.c(c),.d(d[10]),.q(q[10]));
sdo1_2 i_q11 (.c(c),.d(d[11]),.q(q[11]));
sdo1_2 i_q12 (.c(c),.d(d[12]),.q(q[12]));
sdo1_2 i_q13 (.c(c),.d(d[13]),.q(q[13]));
sdo1_2 i_q14 (.c(c),.d(d[14]),.q(q[14]));
endmodule
module sdo1_2(c,d,q); // input at rising edge, resyncs to falling
input c;
input d;
output q;
sdo0_2 i_q (.c(c),.d(d),.q(q));
// s--ynthesis attribute KEEP_HIERARCHY of i_q is "TRUE"
endmodule
module sdo0_2(c,d,q); // input at rising edge, resyncs to falling, initializes to "1"
input c;
input d;
output q;
wire d0, dr;
OBUF i_q (.I(dr), .O(q));
FD i_d0 (.C(c), .D(d), .Q(d0));
//FD_1 i_dr (.C(c), .D(d), .Q(dr));
FD_1 i_dr (.C(c), .D(d0), .Q(dr));
//synthesis translate_off
defparam i_dr.INIT = 1'b1;
//synthesis translate_on
//synthesis attribute INIT of i_dr is "1"
// synthesis attribute IOB of i_dr is "TRUE"
//synthesis attribute INIT of i_d0 is "1"
endmodule
module ipadql(g,q,qr,d); //
input g;
output q;
output qr;
input d;
ipadql0 i_q (.g(g),.q(q),.qr(qr),.d(d));
// s--ynthesis attribute KEEP_HIERARCHY of i_q is "TRUE"
endmodule
module ipadql0(g,q,qr,d);
input g;
output q;
output qr;
input d;
IBUF i_q (.I(d), .O(q));
LD i_qr (.G(g), .D(q), .Q(qr));
// synthesis attribute IOB of i_qr is "TRUE"
// synthesis attribute NODELAY of i_q is "TRUE"
endmodule
module bpadql(g,q,qr,io,t,d); //
input g;
output q;
output qr;
inout io;
input t;
input d;
bpadql0 i_q (.g(g),.q(q),.qr(qr),.io(io),.t(t),.d(d));
// s--ynthesis attribute KEEP_HIERARCHY of i_q is "TRUE"
endmodule
module bpadql0(g,q,qr,io,t,d);
input g;
output q;
output qr;
inout io;
input t;
input d;
IOBUF i_q (.I(d), .T(t),.O(q), .IO(io));
LD i_qr (.G(g), .D(q), .Q(qr));
// synthesis attribute IOB of i_qr is "TRUE"
// synthesis attribute NODELAY of i_q is "TRUE"
endmodule
module dio1(c,t,d,q,dq);
input c;
input t;
input d;
output q;
inout dq;
dio0 i_dq (.c(c),.t(t),.d(d),.q(q),.dq(dq));
// s--ynthesis attribute KEEP_HIERARCHY of i_dq is "TRUE"
endmodule
module dio0(c,t,d,q,dq);
input c;
input t;
input d;
output q;
inout dq;
wire q0;
IOBUF i_dq (.I(d), .T(t),.O(q0), .IO(dq));
FD i_q (.C(c), .D(q0), .Q(q));
// synthesis attribute IOB of i_q is "TRUE"
// synthesis attribute NODELAY of i_dq is "TRUE"
endmodule
/*
** -----------------------------------------------------------------------------**
** irq_smart.v
**
** making a simgle interrupt that combines frame sync and compressor done
** waiting for the latest of the 2
**
** Copyright (C) 2008-2010 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.wpage0_inc
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// control bits:
// [1:0] : 3 - enable waiting for frame sync if compressor done comes earlier
// 2 - disable waiting F.S. (should be disabled for single-frame acquisitions where no frame sync will follow the first frame)
// 1, 0 - don't change F.S. waiting
// [3:2] : 3 - wait for DMA FIFO to be transferred to the system before generating interrupt
// 2 - don't wait for the DMA FIFO to be emptied
// 1, 0 - don't change DMA FIFO waiting
// [15] ; reset requests (mostly fro simulation
// NOTE: now if wait_fs is off, IRQ will be on either FS or done (may be twice)
module irq_smart (sclk, // @negedge
wen, // sync to address and d[0:15]
di, // [15:0] data in, only [3:0] are currently used
frame_sync, // frame sync, single pulse @ negedge sclk
is_compressing, // @posedge clk, needs re-sync
compressor_done, // single pulse @ negedge sclk - compressor finished (some data is still in DMA FIFO)
fifo_empty, // DMA FIFO empty (no gaps between compressor_done and !fifo_empty)
irq); // single cycle $ negedge sclk output to be used as IRQ source
input sclk;
input wen;
input [15:0] di;
input frame_sync; // frame sync, single pulse @ negedge sclk
input is_compressing; // @posedge clk, needs re-sync
input compressor_done; // single pulse @ negedge sclk - compressor finished (some data is still in DMA FIFO)
input fifo_empty; // DMA FIFO empty (no gaps between compressor_done and !fifo_empty)
output irq; // single cycle $ negedge sclk output to be used as IRQ source
reg [2:0] is_compressing_s;
reg is_finishing=0; /// no gap with is_compressing_s[2]
reg was_finishing;
// together they provide number of frames currently being processed (0/1/2)
reg wait_frame_sync;
reg wait_fifo;
reg compressor_fifo_done; // single cycle - compressor and and fifo done (next after done if !wait_fifo)
reg done_request = 0;
reg irq;
reg rst;
wire will_postpone_fs;
wire end_postpone_fs;
wire finished;
reg fs_postponed;
wire will_delay_done_irq;
reg delaying_done_irq;
assign will_postpone_fs=wait_frame_sync && (is_compressing_s[2] || is_finishing) ;
assign finished=was_finishing && ! is_finishing;
assign end_postpone_fs=finished || frame_sync;
assign will_delay_done_irq=wait_frame_sync && (finished && !fs_postponed);
always @ (negedge sclk) begin
//control interface
if (wen & di[1]) wait_frame_sync <= di[0];
if (wen & di[3]) wait_fifo <= di[2];
rst <=wen & di[15];
// process frame sync postponed - wait for the compression to finish if it was started during previous frame
fs_postponed <= !rst && ((will_postpone_fs && frame_sync) || (fs_postponed && !end_postpone_fs));
delaying_done_irq <= !rst && (will_delay_done_irq || (delaying_done_irq && !frame_sync));
is_compressing_s[2:0]<={is_compressing_s[1:0],is_compressing} ; // re-sync from posedge xclk to negedge clk
done_request <= !rst && (compressor_done || (done_request && !compressor_fifo_done));
compressor_fifo_done <= done_request && (!wait_fifo || fifo_empty) && !compressor_fifo_done;
is_finishing <= !rst && ((is_compressing_s[2] && !is_compressing_s[1]) ||
(is_finishing && !compressor_fifo_done));
was_finishing <= is_finishing;
irq <= !rst && ((frame_sync && (!will_postpone_fs || delaying_done_irq)) ||
(fs_postponed && end_postpone_fs) || // will include frame_sync if compression did not finish
(!will_delay_done_irq && finished));
end
endmodule
/*
** -----------------------------------------------------------------------------**
** lens_flat.v
**
** Correction of lens+sensor vignetting. Initially it is just a quadratic function
** that can be improved later by a piece-linear table function T() of the calculated
** f(x,y)=p*(x-x0)^2 + q(y-yo)^2 + c.
** T(f(x,y)) can be used to approximate cos^4). or other vignetting functions
**
** This function - f(x,y) or T(f(x,y)) here deal with full sensor data before
** gamma-tables are applied and the data is compressed to 8 bits
**
** Copyright (C) 2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
/*
F2(x,y)=p*(x-x0)^2 + q(y-yo)^2 + c=
p*x^2 - (2*p*x0) * x + p* (x0*x0) + q*y^2 - (2*q*y0) * y + q* (y0*y0) + c=
p* x^2 - (2*p*x0) * x + q* y^2 -(2*q)* y + (p* (x0*x0)+q* (y0*y0) + c)
Final:
F2(X,Y)=p* x^2 - (2*p*x0) * x + q* y^2 -(2*q)* y + (p* (x0*x0)+q* (y0*y0) + c):
Ax(Y)= p
Bx(Y)=-(2*p)
F(0,Y)= q*y^2 - (2*q*y0) * y + (q* (y0*y0) + c + p* (x0*x0))
C= (q* (y0*y0) + c + p* (x0*x0));
BY= - (2*q*y0)
AY= q
AX= p
BX= -2*p*x0
*/
`timescale 1ns / 1ps
module lens_flat (sclk, /// system clock @negedge
wen, /// write LSW from di
di, /// [15:0] data in
pclk, /// pixel clock (@pclk)
fstart, // frame start - single clock (will have frame latency as coefficients are written after the fstart)
newline, // start of scan line - ahead of linerun
linerun, // active pixel output - latency will be = 4 clocks
bayer,
pixdi, // pixel data in, 16 bit unsigned
pixdo // pixel data out, 16 bit unsigned
);
input sclk;
input wen;
input [15:0] di;
input pclk;
input fstart;
input newline;
input linerun;
input [1:0] bayer;
input [15:0] pixdi;
output[15:0] pixdo;
// output [18:0] lens_corr;
reg [ 1:0] wen_d;
reg [23:0] did;
reg [23:0] didd;
// reg we_AA,we_AB,we_AC,we_BA,we_BB,we_BC,we_CA,we_CB,we_CC;
reg we_AX,we_BX,we_AY,we_BY,we_C;
reg we_scales;/// write additional individual per-color scales (17 bits each)
reg we_fatzero_in,we_fatzero_out; ///
reg we_post_scale;
//F(x,y)=Ax*x^2+Bx*x+Ay*y^2+By*y+C
reg [18:0] AX; /// Ax
reg [18:0] AY; /// Ax
reg [20:0] BX; /// Bx
reg [20:0] BY; /// By
reg [18:0] C; /// C
reg [16:0] scales[0:3]; // per-color coefficients
reg [16:0] scales_r;
reg [15:0] fatzero_in; /// zero level to subtract before multiplication
reg [15:0] fatzero_out; /// zero level to add after multiplication
reg [ 3:0] post_scale; /// shift product after first multiplier - maybe needed when using decimation
wire [18:0] FY; /// F(0,y)
wire [23:0] ERR_Y; /// running error for the first column
wire [18:0] FXY; /// F(x,y)
reg [18:0] FXY_sat;
reg [ 4:0] lens_corr_out; /// lens correction out valid (first clock from column0 )
/// copied form sensorpix353.v
reg bayer_nset;
reg bayer0_latched;
reg [1:0] color;
wire [35:0] mult_first_res;
reg [17:0] mult_first_scaled; /// scaled multiplication result (to use with decimation to make parabola 'sharper')
wire [35:0] mult_second_res;
reg [15:0] pixdo; /// output pixel data, 16 bits, saturated at positive
wire [20:0] pre_pixdo_with_zero= mult_second_res[35:15] + {{5{fatzero_out[15]}},fatzero_out[15:0]};
wire sync_bayer=linerun && ~lens_corr_out[0];
wire [17:0] pix_zero = {2'b0,pixdi[15:0]}-{{2{fatzero_in [15]}},fatzero_in [15:0]};
always @ (negedge sclk) begin
wen_d[1:0] <= {wen_d[0],wen};
if (wen) did[15: 0] <= di[15:0];
if (wen_d[0]) did[23:16] <= di[ 7:0];
didd[23:0] <= did[23:0];
we_AX <= wen_d[1] && (did[23:19]==5'h00); /// 00000
we_AY <= wen_d[1] && (did[23:19]==5'h01); /// 00001
we_C <= wen_d[1] && (did[23:19]==5'h02); /// 00010
we_BX <= wen_d[1] && (did[23:21]==3'h1 ); /// 001
we_BY <= wen_d[1] && (did[23:21]==3'h2 ); /// 010
we_scales <= wen_d[1] && (did[23:19]==5'h0c); /// 01100NN
we_fatzero_in <= wen_d[1] && (did[23:16]==8'h68); /// 01101000
we_fatzero_out <= wen_d[1] && (did[23:16]==8'h69); /// 01101001
we_post_scale <= wen_d[1] && (did[23:16]==8'h6a); /// 01101010
if (we_AX) AX[18:0] <= didd[18:0];
if (we_AY) AY[18:0] <= didd[18:0];
if (we_BX) BX[20:0] <= didd[20:0];
if (we_BY) BY[20:0] <= didd[20:0];
if (we_C) C[18:0] <= didd[18:0];
if (we_scales) scales[didd[18:17]] <= didd[16:0];
if (we_fatzero_in) fatzero_in [15:0] <= didd[15:0];
if (we_fatzero_out) fatzero_out[15:0] <= didd[15:0];
if (we_post_scale) post_scale [ 3:0] <= didd[ 3:0];
end
//reg color[1:0]
always @ (posedge pclk) begin
lens_corr_out[4:0]<={lens_corr_out[3:0],linerun};
bayer_nset <= !fstart && (bayer_nset || linerun);
bayer0_latched<= bayer_nset? bayer0_latched:bayer[0];
color[1:0] <= { bayer_nset? (sync_bayer ^ color[1]):bayer[1] ,
(bayer_nset &&(~sync_bayer))?~color[0]:bayer0_latched };
/// now scale the result (normally post_scale[2:0] ==1)
case (post_scale [2:0])
3'h0:mult_first_scaled[17:0]<= (~mult_first_res[35] & |mult_first_res[34:33]) ? 18'h1ffff:mult_first_res[33:16]; /// only limit positive overflow
3'h1:mult_first_scaled[17:0]<= (~mult_first_res[35] & |mult_first_res[34:32]) ? 18'h1ffff:mult_first_res[32:15];
3'h2:mult_first_scaled[17:0]<= (~mult_first_res[35] & |mult_first_res[34:31]) ? 18'h1ffff:mult_first_res[31:14];
3'h3:mult_first_scaled[17:0]<= (~mult_first_res[35] & |mult_first_res[34:30]) ? 18'h1ffff:mult_first_res[30:13];
3'h4:mult_first_scaled[17:0]<= (~mult_first_res[35] & |mult_first_res[34:29]) ? 18'h1ffff:mult_first_res[29:12];
3'h5:mult_first_scaled[17:0]<= (~mult_first_res[35] & |mult_first_res[34:28]) ? 18'h1ffff:mult_first_res[28:11];
3'h6:mult_first_scaled[17:0]<= (~mult_first_res[35] & |mult_first_res[34:27]) ? 18'h1ffff:mult_first_res[27:10];
3'h7:mult_first_scaled[17:0]<= (~mult_first_res[35] & |mult_first_res[34:26]) ? 18'h1ffff:mult_first_res[26: 9];
endcase
if (lens_corr_out[4]) pixdo[15:0]=pre_pixdo_with_zero[20]? 16'h0: /// negative - use 0
((|pre_pixdo_with_zero[19:16])?16'hffff: ///>0xffff - limit by 0xffff
pre_pixdo_with_zero[15:0]);
end
MULT18X18SIO #(
.AREG(1), // Enable the input registers on the A port (1=on, 0=off)
.BREG(1), // Enable the input registers on the B port (1=on, 0=off)
.B_INPUT("DIRECT"), // B cascade input "DIRECT" or "CASCADE"
.PREG(1) // Enable the input registers on the P port (1=on, 0=off)
) i_mult_first (
.BCOUT(), // 18-bit cascade output
.P(mult_first_res[35:0]), // 36-bit multiplier output
// .A(FXY[17]?18'h1ffff:FXY[17:0]), // 18-bit multiplier input
.A((FXY[18]==FXY[17])?FXY[17:0]:(FXY[18]?18'h20000:18'h1ffff)), // 18-bit multiplier input
.B({1'b0,scales[~color[1:0]]}), // 18-bit multiplier input
.BCIN(0), // 18-bit cascade input
.CEA(lens_corr_out[0]), // Clock enable input for the A port
.CEB(lens_corr_out[0]), // Clock enable input for the B port
.CEP(lens_corr_out[1]), // Clock enable input for the P port
.CLK(pclk), // Clock input
.RSTA(0), // Synchronous reset input for the A port
.RSTB(0), // Synchronous reset input for the B port
.RSTP(0) // Synchronous reset input for the P port
);
MULT18X18SIO #(
.AREG(1), // Enable the input registers on the A port (1=on, 0=off)
.BREG(0), // Enable the input registers on the B port (1=on, 0=off)
.B_INPUT("DIRECT"), // B cascade input "DIRECT" or "CASCADE"
.PREG(1) // Enable the input registers on the P port (1=on, 0=off)
) i_mult_second (
.BCOUT(), // 18-bit cascade output
.P(mult_second_res[35:0]), // 36-bit multiplier output
.A(pix_zero[17:0]), // 18-bit multiplier input
.B(mult_first_scaled[17:0]), // 18-bit multiplier input - always positive
.BCIN(0), // 18-bit cascade input
.CEA(lens_corr_out[2]), // Clock enable input for the A port
.CEB(lens_corr_out[0]), // Clock enable input for the B port
.CEP(lens_corr_out[3]), // Clock enable input for the P port
.CLK(pclk), // Clock input
.RSTA(0), // Synchronous reset input for the A port
.RSTB(0), // Synchronous reset input for the B port
.RSTP(0) // Synchronous reset input for the P port
);
lens_flat_line #(.F_WIDTH(19), /// number of bits in the output result (signed)
.F_SHIFT(22), /// shift ~2*log2(width/2), for 4K width
.B_SHIFT(12), ///(<=F_SHIFT) shift b- coeff (12 is 2^12 - good for lines <4096, 1 output count per width)
.A_WIDTH(19), /// number of bits in a-coefficient (signed). Just to match the caller - MSBs will be anyway discarded
.B_WIDTH(21)) /// number of bits in b-coefficient (signed).
i_fy( .pclk(pclk), /// pixel clock
.first(fstart), /// initialize running parameters from the inputs (first column). Should be at least 1-cycle gap between "first" and first "next"
.next(newline), /// calcualte next pixel
.F0(C[18:0]), /// value of the output in the first column (before saturation), 18 bit, unsigned
.ERR0(0), /// initial value of the running error (-2.0<err<+2.0), scaled by 2^22, so 24 bits
.A0(AY[18:0]), /// Ay
.B0(BY[20:0]), /// By, signed
.F(FY[18:0]),
.ERR(ERR_Y[23:0]));
lens_flat_line #(.F_WIDTH(19), /// number of bits in the output result
.F_SHIFT(22), /// shift ~2*log2(width/2), for 4K width
.B_SHIFT(12), ///(<=F_SHIFT) shift b- coeff (12 is 2^12 - good for lines <4096, 1 output count per width)
.A_WIDTH(19), /// number of bits in a-coefficient (unsigned). Just to match the caller - MSBs will be anyway discarded
.B_WIDTH(21)) /// number of bits in b-coefficient (signed).
i_fxy( .pclk(pclk), /// pixel clock
.first(newline), /// initialize running parameters from the inputs (first column). Should be at least 1-cycle gap between "first" and first "next"
.next(linerun), /// calcualte next pixel
.F0(FY[18:0]), /// value of the output in the first column (before saturation), 18 bit, unsigned
.ERR0(ERR_Y[23:0]), /// initial value of the running error (-2.0<err<+2.0), scaled by 2^22, so 24 bits
.A0(AX[18:0]), /// Ax(Y), signed
.B0(BX[20:0]), /// Bx(Y), signed
.F(FXY[18:0]),
.ERR());
endmodule
module lens_flat_line(
pclk, /// pixel clock
first, /// initialize running parameters from the inputs (first column). Should be at least 1-cycle gap between "first" and first "next"
next, /// calcualte next pixel
F0, /// value of the output in the first column (before saturation), 18 bit, unsigned
ERR0, /// initial value of the running error (-2.0<err<+2.0), scaled by 2^22, so 24 bits
A0, /// a - fixed for negative values
B0,
F,
ERR); // output - 18 bits, unsigned (not saturated)
parameter F_WIDTH= 18; /// number of bits in the output result
parameter F_SHIFT=22; /// shift ~2*log2(width/2), for 4K width
parameter B_SHIFT=12; ///(<=F_SHIFT) shift b- coeff (12 is 2^12 - good for lines <4096, 1 output count per width)
parameter A_WIDTH=18; /// number of bits in a-coefficient (unsigned). Just to match the caller - MSBs will be anyway discarded
parameter B_WIDTH=21; // number of bits in b-coefficient (signed).
parameter DF_WIDTH=B_WIDTH-F_SHIFT+B_SHIFT; //21-22+12 11; /// number of bits in step of F between (df/dx), signed
input pclk;
input first;
input next;
input [F_WIDTH-1:0] F0;
input [F_SHIFT+1:0] ERR0;
input [A_WIDTH-1:0] A0;
input [B_WIDTH-1:0] B0;
output [F_WIDTH-1:0] F;
output [F_SHIFT+1:0] ERR;
reg [F_SHIFT+1:0] ERR; /// running difference between ax^2+bx+c and y, scaled by 2^22, signed, should never overflow
reg [F_SHIFT+1:0] ApB; /// a+b, scaled by 2 ^22, high bits ignored (not really needed - can use ApB0
reg [F_SHIFT+1:1] A2X; /// running value for 2*a*x, scaled by 2^22, high bits ignored
reg [(DF_WIDTH)-1:0] dF; /// or [9:0] - anyway only lower bits will be used in comparison operations
reg [F_WIDTH-1:0] F; /// Running value of the output
reg next_d, first_d; // delayed by 1 cycle
reg [F_WIDTH-1:0] F1;
reg [A_WIDTH-1:0] A;
wire [F_SHIFT+1:0] preERR={A2X[F_SHIFT+1:1],1'b0}+ApB[F_SHIFT+1:0]-{dF[1:0],{F_SHIFT{1'b0}}};
/// Increment can be 0 or +/-1, depending on the required correction
/// It relies on the facts that:
/// - the output F(x) is integer
/// - dF/dx does not chnage by more than +/-1 when x is incremented (abs (d2f/dx2)<1), so the algorithm to get
/// y=round(F(x)) is simple :
/// At each step x, try to chnage y by the same amount as was done at the previous step, adding/subtracting 1 if needed
/// and updating the new running error (difference between the current (integer) value of y and the precise value of F(x)
/// This error is calculated here with the 22 binary digits after the point.
///f=ax^2+bx+c
///
///1) f <= f+ df +1
/// df <= df+1;
/// err+= (2ax+a+b-df) -1
///2) f <= f+ df
/// err+= (2ax+a+b-df)
///3) f <= f+ df -1
/// df <= df-1;
/// err+= (2ax+a+b-df) +1
///preERR->inc:
/// 100 -> 11
/// 101 -> 11
/// 110 -> 11
/// 111 -> 00
/// 000 -> 00
/// 001 -> 01
/// 010 -> 01
/// 011 -> 01
wire [1:0] inc= {preERR[F_SHIFT+1] & (~preERR[F_SHIFT] | ~preERR[F_SHIFT-1]),
(preERR[F_SHIFT+1:F_SHIFT-1] != 3'h0) &
(preERR[F_SHIFT+1:F_SHIFT-1] != 3'h7)};
always @(posedge pclk) begin
first_d <=first;
next_d <=next;
if (first) begin
F1 [F_WIDTH-1:0] <= F0[ F_WIDTH-1:0];
dF[(DF_WIDTH)-1:0] <= B0[B_WIDTH-1: (F_SHIFT-B_SHIFT)];
ERR[F_SHIFT+1:0] <= ERR0[F_SHIFT+1:0];
ApB[F_SHIFT+1:0] <= {{F_SHIFT+2-A_WIDTH{A0[A_WIDTH-1]}},A0[A_WIDTH-1:0]}+{B0[B_WIDTH-1:0],{F_SHIFT-B_SHIFT{1'b0}}}; /// high bits from B will be discarded
A [A_WIDTH-1:0] <= A0[A_WIDTH-1:0];
end else if (next) begin
dF[(DF_WIDTH)-1:0] <= dF[(DF_WIDTH)-1:0]+{{((DF_WIDTH)-1){inc[1]}},inc[1:0]};
ERR[F_SHIFT-1:0]<= preERR[F_SHIFT-1:0];
ERR[F_SHIFT+1:F_SHIFT]<= preERR[F_SHIFT+1:F_SHIFT]-inc[1:0];
end
if (first_d) F[F_WIDTH-1:0] <= F1[ F_WIDTH-1:0];
else if (next_d) F[F_WIDTH-1:0] <= F[F_WIDTH-1:0]+{{(F_WIDTH-(DF_WIDTH)){dF[(DF_WIDTH)-1]}},dF[(DF_WIDTH)-1:0]};
if (first_d) A2X[F_SHIFT+1:1] <= {{F_SHIFT+2-A_WIDTH{A[A_WIDTH-1]}},A[A_WIDTH-1:0]};
else if (next) A2X[F_SHIFT+1:1] <= A2X[F_SHIFT+1:1] + {{F_SHIFT+2-A_WIDTH{A[A_WIDTH-1]}},A[A_WIDTH-1:0]};
end
endmodule
000 004 008 00c 010 014 018 01c 020 024 028 02c 030 034 038 03c
040 044 048 04c 050 054 058 05c 060 064 068 06c 070 074 078 07c
080 084 088 08c 090 094 098 09c 0a0 0a4 0a8 0ac 0b0 0b4 0b8 0bc
0c0 0c4 0c8 0cc 0d0 0d4 0d8 0dc 0e0 0e4 0e8 0ec 0f0 0f4 0f8 0fc
100 104 108 10c 110 114 118 11c 120 124 128 12c 130 134 138 13c
140 144 148 14c 150 154 158 15c 160 164 168 16c 170 174 178 17c
180 184 188 18c 190 194 198 19c 1a0 1a4 1a8 1ac 1b0 1b4 1b8 1bc
1c0 1c4 1c8 1cc 1d0 1d4 1d8 1dc 1e0 1e4 1e8 1ec 1f0 1f4 1f8 1fc
200 204 208 20c 210 214 218 21c 220 224 228 22c 230 234 238 23c
240 244 248 24c 250 254 258 25c 260 264 268 26c 270 274 278 27c
280 284 288 28c 290 294 298 29c 2a0 2a4 2a8 2ac 2b0 2b4 2b8 2bc
2c0 2c4 2c8 2cc 2d0 2d4 2d8 2dc 2e0 2e4 2e8 2ec 2f0 2f4 2f8 2fc
300 304 308 30c 310 314 318 31c 320 324 328 32c 330 334 338 33c
340 344 348 34c 350 354 358 35c 360 364 368 36c 370 374 378 37c
380 384 388 38c 390 394 398 39c 3a0 3a4 3a8 3ac 3b0 3b4 3b8 3bc
3c0 3c4 3c8 3cc 3d0 3d4 3d8 3dc 3e0 3e4 3e8 3ec 3f0 3f4 3f8 3fc
3ff
000 004 008 00c 010 014 018 01c 020 024 028 02c 030 034 038 03c
040 044 048 04c 050 054 058 05c 060 064 068 06c 070 074 078 07c
080 084 088 08c 090 094 098 09c 0a0 0a4 0a8 0ac 0b0 0b4 0b8 0bc
0c0 0c4 0c8 0cc 0d0 0d4 0d8 0dc 0e0 0e4 0e8 0ec 0f0 0f4 0f8 0fc
100 104 108 10c 110 114 118 11c 120 124 128 12c 130 134 138 13c
140 144 148 14c 150 154 158 15c 160 164 168 16c 170 174 178 17c
180 184 188 18c 190 194 198 19c 1a0 1a4 1a8 1ac 1b0 1b4 1b8 1bc
1c0 1c4 1c8 1cc 1d0 1d4 1d8 1dc 1e0 1e4 1e8 1ec 1f0 1f4 1f8 1fc
200 204 208 20c 210 214 218 21c 220 224 228 22c 230 234 238 23c
240 244 248 24c 250 254 258 25c 260 264 268 26c 270 274 278 27c
280 284 288 28c 290 294 298 29c 2a0 2a4 2a8 2ac 2b0 2b4 2b8 2bc
2c0 2c4 2c8 2cc 2d0 2d4 2d8 2dc 2e0 2e4 2e8 2ec 2f0 2f4 2f8 2fc
300 304 308 30c 310 314 318 31c 320 324 328 32c 330 334 338 33c
340 344 348 34c 350 354 358 35c 360 364 368 36c 370 374 378 37c
380 384 388 38c 390 394 398 39c 3a0 3a4 3a8 3ac 3b0 3b4 3b8 3bc
3c0 3c4 3c8 3cc 3d0 3d4 3d8 3dc 3e0 3e4 3e8 3ec 3f0 3f4 3f8 3fc
3ff
000 004 008 00c 010 014 018 01c 020 024 028 02c 030 034 038 03c
040 044 048 04c 050 054 058 05c 060 064 068 06c 070 074 078 07c
080 084 088 08c 090 094 098 09c 0a0 0a4 0a8 0ac 0b0 0b4 0b8 0bc
0c0 0c4 0c8 0cc 0d0 0d4 0d8 0dc 0e0 0e4 0e8 0ec 0f0 0f4 0f8 0fc
100 104 108 10c 110 114 118 11c 120 124 128 12c 130 134 138 13c
140 144 148 14c 150 154 158 15c 160 164 168 16c 170 174 178 17c
180 184 188 18c 190 194 198 19c 1a0 1a4 1a8 1ac 1b0 1b4 1b8 1bc
1c0 1c4 1c8 1cc 1d0 1d4 1d8 1dc 1e0 1e4 1e8 1ec 1f0 1f4 1f8 1fc
200 204 208 20c 210 214 218 21c 220 224 228 22c 230 234 238 23c
240 244 248 24c 250 254 258 25c 260 264 268 26c 270 274 278 27c
280 284 288 28c 290 294 298 29c 2a0 2a4 2a8 2ac 2b0 2b4 2b8 2bc
2c0 2c4 2c8 2cc 2d0 2d4 2d8 2dc 2e0 2e4 2e8 2ec 2f0 2f4 2f8 2fc
300 304 308 30c 310 314 318 31c 320 324 328 32c 330 334 338 33c
340 344 348 34c 350 354 358 35c 360 364 368 36c 370 374 378 37c
380 384 388 38c 390 394 398 39c 3a0 3a4 3a8 3ac 3b0 3b4 3b8 3bc
3c0 3c4 3c8 3cc 3d0 3d4 3d8 3dc 3e0 3e4 3e8 3ec 3f0 3f4 3f8 3fc
3ff
000 004 008 00c 010 014 018 01c 020 024 028 02c 030 034 038 03c
040 044 048 04c 050 054 058 05c 060 064 068 06c 070 074 078 07c
080 084 088 08c 090 094 098 09c 0a0 0a4 0a8 0ac 0b0 0b4 0b8 0bc
0c0 0c4 0c8 0cc 0d0 0d4 0d8 0dc 0e0 0e4 0e8 0ec 0f0 0f4 0f8 0fc
100 104 108 10c 110 114 118 11c 120 124 128 12c 130 134 138 13c
140 144 148 14c 150 154 158 15c 160 164 168 16c 170 174 178 17c
180 184 188 18c 190 194 198 19c 1a0 1a4 1a8 1ac 1b0 1b4 1b8 1bc
1c0 1c4 1c8 1cc 1d0 1d4 1d8 1dc 1e0 1e4 1e8 1ec 1f0 1f4 1f8 1fc
200 204 208 20c 210 214 218 21c 220 224 228 22c 230 234 238 23c
240 244 248 24c 250 254 258 25c 260 264 268 26c 270 274 278 27c
280 284 288 28c 290 294 298 29c 2a0 2a4 2a8 2ac 2b0 2b4 2b8 2bc
2c0 2c4 2c8 2cc 2d0 2d4 2d8 2dc 2e0 2e4 2e8 2ec 2f0 2f4 2f8 2fc
300 304 308 30c 310 314 318 31c 320 324 328 32c 330 334 338 33c
340 344 348 34c 350 354 358 35c 360 364 368 36c 370 374 378 37c
380 384 388 38c 390 394 398 39c 3a0 3a4 3a8 3ac 3b0 3b4 3b8 3bc
3c0 3c4 3c8 3cc 3d0 3d4 3d8 3dc 3e0 3e4 3e8 3ec 3f0 3f4 3f8 3fc
3ff
\ No newline at end of file
/*
** -----------------------------------------------------------------------------**
** macros353.v
**
** I/O pads related circuitry
**
** Copyright (C) 2002 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// just make more convenient A[3:0] instead of 4 one-bit inputs
// TODO: Replace direct instances of SRL16 to imporve portability
module MSRL16 (Q, A, CLK, D);
output Q;
input [3:0] A;
input CLK, D;
SRL16 i_q(.Q(Q), .A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .CLK(CLK), .D(D));
endmodule
module MSRL16_1 (Q, A, CLK, D);
output Q;
input [3:0] A;
input CLK, D;
SRL16_1 i_q(.Q(Q), .A0(A[0]), .A1(A[1]), .A2(A[2]), .A3(A[3]), .CLK(CLK), .D(D));
endmodule
module myRAM_WxD_D(D,WE,clk,AW,AR,QW,QR);
parameter DATA_WIDTH=16;
parameter DATA_DEPTH=4;
parameter DATA_2DEPTH=(1<<DATA_DEPTH)-1;
input [DATA_WIDTH-1:0] D;
input WE,clk;
input [DATA_DEPTH-1:0] AW;
input [DATA_DEPTH-1:0] AR;
output [DATA_WIDTH-1:0] QW;
output [DATA_WIDTH-1:0] QR;
reg [DATA_WIDTH-1:0] ram [0:DATA_2DEPTH];
always @ (posedge clk) if (WE) ram[AW] <= D;
assign QW= ram[AW];
assign QR= ram[AR];
endmodule
module myRAM_WxD_D_1(D,WE,clk,AW,AR,QW,QR);
parameter DATA_WIDTH=16;
parameter DATA_DEPTH=4;
parameter DATA_2DEPTH=(1<<DATA_DEPTH)-1;
input [DATA_WIDTH-1:0] D;
input WE,clk;
input [DATA_DEPTH-1:0] AW;
input [DATA_DEPTH-1:0] AR;
output [DATA_WIDTH-1:0] QW;
output [DATA_WIDTH-1:0] QR;
reg [DATA_WIDTH-1:0] ram [0:DATA_2DEPTH];
always @ (negedge clk) if (WE) ram[AW] <= D;
assign QW= ram[AW];
assign QR= ram[AR];
endmodule
/*
** -----------------------------------------------------------------------------**
** mcontr353.v
**
** 4 channel block access SDRAM controller
**
** Copyright (C) 2002-2010 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
/*
SDRAM controller supports 4 channels to access memory in parallel. Data is transferred in pages 256x16 (or 512x8)- for sequentional access
(i.e. written by sensor) or in square (for 8bit mode) tiles of 18x18x8bits. This mode is needed by JPEG
encoder - each 16x16 MCU will be bayer-decoded to 4 8x8 Y (intensity) blocks, one 8x8 Cr and one 8x8 Cb (4:2:0).
Each scan line is aligned to 128x16-bit page boundary.
SDRAM chip itself is 16-bit wide (16Mx16), data channels have different widths. system is little endian, so LSB has lower address
Three of data channels have predefined transfer direction and the control registers should be written accordingly,
the last one is bidirectional for PIO acces to SDRAM from CPU.
Channel 0 provides data from the sensor (it can be combined with FPN correction data) to the SDRAM in either 8-bit mode or 16-bit.
If the data is to be JPEG compressed it should be in 8-bit mode.
Channel 1 reads FPN data from SDRAM (8bit - subtract, 8 bit - scale) and feeds it to FPGA for FPN correction of the data on the way
from sensor to SDRAM (through channel 0)
Channel 2 provides data to JPEG encoder in 16x16x8bit MCUs. It can also provide data dirsectly to CPU through DMA bypassing any compression
Channel 3 provides bidirectional access from CPU through 8x32 bit window. To read/write more there is a special command to proceed to next
page and a status bit to test if data is ready. After writing data it is needed to go through the whole page (or just issue "next page") command
as the data transfer to CPU takes place only when the whole page is filled (total of 8 8x32 subpages). There is also a special status bit
to determine if the data is actually written to sdram and the channel may be reprogrammed (i.e. for reading)
*/
module mcontr(
clk0, // SDRAM clocks (hope to get 120MHz)
restart_en, // enable restarting selected channels
restart, // reinitialize channels (posedge-sensitive, masked by enXfer0
bonded, //[3:0] - channel bonded with the other (just for channel 2), make it TIG
nextBlocksEn, // enable read blocks to FIFO. disabled when init or roll over, enable by confirmRead
// mclk, // modified CPU global clock - write and read with a7==1 (for block memory R/W)
//descriptor memory and channel 3
ia, // internal 4-bit address bus (fast - directly from I/O pads)
as, // 4 bit address to select descriptor address and data word (3 bits)
am, // switching between ia (async read) and as (sync write)
dscs, // WE for descriptor memory
mwnr, // CPU write, not read (valid for 2 cycles at negedge mclk)
init_ch3, // write to init cnhannel 3 (will reset address r/w)
next_ch3, // advance to the next channel3 page, reset address
readNextFrame3, //enable reading to the SDRAM buffer (after channel init or frame over), set to 1'b1 if not needed
menrw, // enable CPU read/write 32-bit word from buffer(valid @ mweoe)
di, // 32-bit data from CPU (descriptor and channel 3)
dsdo, // [31:0] data out from descriptor memory
do, // 32-bit data to CPU (channel 3)
rdy, // ready to r/w next 128x32 page (channel 3)
wrempty, // write buffer empty (valid only in write mode).
ch0clk,// clock for channel0
ch0we, // channel 0 (sensor->SDRAM) WE
ch0a, // [7:0] channel 0 address (MSB - block #)
ch0di, // [15:0] channel 0 data in
stch0, // start channel 0 transfer (up to 2 w/o confirmation)
ch0rdy, // channel 0 ready
readNextFrame0, //enable reading to the SDRAM buffer (after channel init or frame over), set to 1'b1 if not needed
ch1clk,// clock for channel1
ch1a, // [7:0] channel 1 (SDRAM -> sensor calibration data) address (MSB - block #)
ch1do, // [15:0] channel 1 data out
stch1, // start channel 1 transfer (up to 2 w/o confirmation)
ch1rdy, // channel 1 ready
readNextFrame1, //enable reading to the SDRAM buffer (after channel init or frame over), set to 1'b1 if not needed
ch2clk,// clock for channel2
ch2a, // [10:0] channel 2 (SDRAM -> compressor MCU) address (MSB - block #)
ch2do, // [7:0] channel 2 data out
stch2, // start channel 2 transfer (up to 2 w/o confirmation)
ench2, // enable read from channel 2 buffer to compressor
ch2rdy, // channel 2 ready
readNextFrame2, //enable reading to the SDRAM buffer (after channel init or frame over), set to 1'b1 if not needed
nextFrame,// (level) generated before actual block is filled - needed to be combined with the pulse from buffer control
chInitOnehot, //[3:0] decoded channel init pulses, 2 cycles behind chInit
//SDRAM intefrace
sddi, // [15:0] data from SDRAM (1 cycle delayed)
sddo, // [15:0] data to SDRAM (1 cycle ahead)
sda, // [12:0] address to SDRAM (1 cycle ahead)
sdba, // [ 1:0] bank address to SDRAM (1 cycle ahead)
sdwe, // WE command bit to SDRAM (1 cycle ahead)
sdras, // RAS command bit to SDRAM (1 cycle ahead)
sdcas, // CAS command bit to SDRAM (1 cycle ahead)
trist, // tristate data to SDRAM (2 cycles ahead)
predqt, // tristate DQ outputs (one extra for FF in output buffer)
dmask, // [1:0] - now both the same (even number of words written)
dqs_re // enable read from DQS i/o-s for phase adjustments (latency 2 from the SDRAM RD command)
);
input clk0;
input restart_en; // enable restarting selected channels
input [ 3:0] restart; // reinitialize channels (posedge-sensitive, masked by enXfer0
output [ 3:0] bonded; //[3:0] - channel bonded with the other (just for channel 2), make it TIG
output [ 3:0] nextBlocksEn; // enable read blocks to FIFO. disabled when init or roll over, enable by confirmRead
input [ 3:0] ia;
input [ 3:0] as;
input [ 3:0] am;
input dscs;
input mwnr;
input init_ch3;
input next_ch3;
input readNextFrame3; //enable reading to the SDRAM buffer (after channel init or frame over), set to 1'b1 if not needed
input menrw;
input [31:0] di;
output [31:0] dsdo;
output [31:0] do;
output rdy;
output wrempty;
input ch0clk;
input ch0we;
input [ 9:0] ch0a;
input [15:0] ch0di;
input stch0;
output ch0rdy;
input readNextFrame0; //enable reading to the SDRAM buffer (after channel init or frame over), set to 1'b1 if not needed
input ch1clk;
input [ 9:0] ch1a;
output [15:0] ch1do;
input stch1;
output ch1rdy;
input readNextFrame1; //enable reading to the SDRAM buffer (after channel init or frame over), set to 1'b1 if not needed
input ch2clk;
input [10:0] ch2a;
output [ 7:0] ch2do;
input stch2;
input ench2;
output ch2rdy;
input readNextFrame2; //enable reading to the SDRAM buffer (after channel init or frame over), set to 1'b1 if not needed
output [ 3:0] nextFrame;
output [ 3:0] chInitOnehot;// decoded channel init pulses, 2 cycles behind chInit
input [31:0] sddi;
output [31:0] sddo;
output [12:0] sda;
output [ 1:0] sdba;
output sdwe;
output sdras;
output sdcas;
output trist;
output predqt; // enable DQ outputs (one extra for FF in output buffer)
output [ 1:0] dmask; // [1:0] - now both the same (even number of words written)
output dqs_re; // enable read from DQS i/o-s for phase adjustments (latency 2 from the SDRAM RD command)
// photofinish hack
wire [24:8] sfa; // start address of a frame - ugly hack to roll over the last (extra) 4 lines of a frame
// to the beginning of a frame - used in photofinish mode.
wire rovr; // roll over mode (photofinish, cntrl0[12]==1
wire [ 3:0] nextBlocksEn; // enable read blocks to FIFO. disabled when init or roll over, enable by confirmRead
// block RAM modules
// channel 0: 256x16in, 256x16 out
wire [31:0] ch0rd; // read data from ch0 buffer
wire [31:0] ch3rd; // read data from ch3 buffer (CPU->SDRAM)
wire [ 8:0] bmad0; // buffer memory address channel 0 (SDRAM side)
wire [ 8:0] bmad1; // buffer memory address channel 1 (SDRAM side)
wire [ 8:0] bmad2; // buffer memory address channel 2 (SDRAM side)
wire [ 8:0] bmad3; // buffer memory address channel 3 (SDRAM side)
wire ch0en; // channel 0 buffer EN (buffer->SDRAM)
wire ch1we; // channel 1 buffer WE (SDRAM->buffer)
wire ch2we; // channel 2 buffer WE (SDRAM->buffer)
wire ch3owe; // channel 3 buffer WE (SDRAM->buffer)
wire ch3en; // channel 3 buffer EN (SDRAM<->buffer)
wire wrempty; // channel3 ch3Access->output
wire rdy;
wire [4:0] curChan; // 1-hot servicing channel
wire ch_drun_rd; // enable read data (SDRAM->block RAM buffer)
wire ch_drun_wr; // enable write data (SDRAM<-block RAM buffer)
wire ch_dlast; //last cycle of drun active for read, 1 cycle later for write
wire ch_prefirstdrun; // 1 cycle ahead of the first drun_rd/drun_wr to be used by bufCntr256 to sample channel enable
reg [3:0] curChanLate; // will be valid at the ch_prefirstdrun
// SDRAM side of data buffers control
wire chSt1; // chArbit -> descript.
wire chSt2; // descript -> sdseq
wire chInit; // chArbit -> descript.
wire [ 1:0] chNum; // chArbit -> descript.
// wire [23:3] startAddr; // descript. -> sdseq
wire [24:3] startAddr; // descript. -> sdseq
wire mode; // descript. -> sdseq
wire WnR; // descript. -> sdseq and arbit.? and main?
wire [ 5:0] param; // descript. -> sdseq
wire [ 1:0] nBuf; // descript. -> bufCntr
wire [17:0] mancmd; // descript. -> sdseq
wire enSDRAM; // descript. -> sdseq +??
wire disSDRAM=!enSDRAM; // descript. -> sdseq +??
wire enRefresh; // descript. -> refreshRequest)
wire [ 3:0] chReqInit; // descript. -> channelRequest(i)
wire [ 3:0] nextFrame; // descript. -> out
wire [ 3:0] enXfer; // descript. -> channelRequest<i>
wire [ 3:0] dnch; // bufCntr<i> -> channelRequest<i>
wire [ 4:0] chnReq; // request SDRAM access from channel ([4] - refresh) +++ channelRequest<i>, refreshRequest -> chArbit
wire [ 3:0] chnReqInit;// request Initialization of tile number for channel +++ channelRequest<i> -> chArbit
wire [ 3:0] chnAckn; // chArbit -> channelRequest<i>
wire refrStart; // chArbit -> sdseq
// Now the I/O buffers. Will use just 2-to-1 MUXes for data out to SDRAM (channel 0 and channel3)
reg [31:0] sddo_reg;
wire nextReq; // sdseq -> chArbit
wire [ 1:0] dsel;
reg [ 1:0] ch3page;
reg [ 6:0] ch3maddr;
always @ (negedge clk0)sddo_reg[31:0] <= dsel[1]? ch3rd[31:0]:ch0rd[31:0];
assign sddo[31:0]= sddo_reg[31:0];
// generate single-cycle pulses after leading edges of dcc-related strobes
// posoneshot i_dccstb(dccvld,clk0,dccstb);
// posoneshot i_finish_dcc_pulse(finish_dcc,clk0,finish_dcc_pulse);
RAMB16_S18_S36 i_chan0buf (
.DOA(), // Port A 16-bit Data Output - sensor side
.DOB(ch0rd[31:0]), // Port B 32-bit Data Output - SDRAM side
.DOPA(), // Port A 2-bit Parity Output
.DOPB(), // Port B 4-bit Parity Output
.ADDRA(ch0a[9:0]), // Port A 10-bit Address Input
.ADDRB(bmad0[8:0]), // Port B 9-bit Address Input
.CLKA(ch0clk), // Port A Clock
.CLKB(!clk0), // Port B Clock
.DIA(ch0di[15:0]), // Port A 16-bit Data Input
.DIB(32'b0), // Port B 32-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.DIPB(4'b0), // Port-B 4-bit parity Input
.ENA(ch0we), // Port A RAM Enable Input
.ENB(ch0en), // PortB RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEA(1'b1), // Port A Write Enable Input
.WEB(1'b0) // Port B Write Enable Input
);
/*
defparam i_chan0buf.INIT_A = 18'h0; // Value of output RAM registers on Port A at startup
defparam i_chan0buf.INIT_B = 18'h0; // Value of output RAM registers on Port B at startup
defparam i_chan0buf.SRVAL_A = 18'h0; // Port A ouput value upon SSR assertion
defparam i_chan0buf.SRVAL_B = 18'h0; // Port B ouput value upon SSR assertion
defparam i_chan0buf.WRITE_MODE_A = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
defparam i_chan0buf.WRITE_MODE_B = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
*/
RAMB16_S18_S36 i_chan1buf (
.DOA(ch1do[15:0]), // Port A 16-bit Data Output - FPN (sensor) side
.DOB(), // Port B 32-bit Data Output - SDRAM side
.DOPA(), // Port A 2-bit Parity Output
.DOPB(), // Port B 4-bit Parity Output
.ADDRA(ch1a[9:0]), // Port A 10-bit Address Input
.ADDRB(bmad1[8:0]), // Port B 9-bit Address Input
.CLKA(ch1clk), // Port A Clock
.CLKB(!clk0), // Port B Clock
.DIA(16'b0), // Port A 16-bit Data Input
.DIB(sddi[31:0]), // Port B 32-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.DIPB(4'b0), // Port-B 4-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.ENB(ch1we), // PortB RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.WEB(1'b1) // Port B Write Enable Input
);
/*
defparam i_chan1buf.INIT_A = 18'h0; // Value of output RAM registers on Port A at startup
defparam i_chan1buf.INIT_B = 18'h0; // Value of output RAM registers on Port B at startup
defparam i_chan1buf.SRVAL_A = 18'h0; // Port A ouput value upon SSR assertion
defparam i_chan1buf.SRVAL_B = 18'h0; // Port B ouput value upon SSR assertion
defparam i_chan1buf.WRITE_MODE_A = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
defparam i_chan1buf.WRITE_MODE_B = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
*/
RAMB16_S9_S36 i_chan2buf (
.DOA(ch2do[ 7:0]), // Port A 8-bit Data Output - compressor side
.DOB(), // Port B 32-bit Data Output - SDRAM side
.DOPA(), // Port A 1-bit Parity Output
.DOPB(), // Port B 4-bit Parity Output
.ADDRA(ch2a[10:0]), // Port A 11-bit Address Input
.ADDRB(bmad2[8:0]), // Port B 9-bit Address Input
.CLKA(ch2clk), // Port A Clock
.CLKB(!clk0), // Port B Clock
.DIA(8'b0), // Port A 8-bit Data Input
.DIB(sddi[31:0]), // Port B 32-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.DIPB(4'b0), // Port-B 4-bit parity Input
.ENA(ench2), // Port A RAM Enable Input
.ENB(ch2we), // PortB RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.WEB(1'b1) // Port B Write Enable Input
);
/*
defparam i_chan2buf.INIT_A = 18'h0; // Value of output RAM registers on Port A at startup
defparam i_chan2buf.INIT_B = 18'h0; // Value of output RAM registers on Port B at startup
defparam i_chan2buf.SRVAL_A = 18'h0; // Port A ouput value upon SSR assertion
defparam i_chan2buf.SRVAL_B = 18'h0; // Port B ouput value upon SSR assertion
defparam i_chan2buf.WRITE_MODE_A = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
defparam i_chan2buf.WRITE_MODE_B = "WRITE_FIRST"; // WRITE_FIRST, READ_FIRST or NO_CHANGE
*/
// as it is 32-bit wide it will go directly to CPU interface, not intemediate 32/16 buffer
// read will have latency of 1
RAMB16_S36_S36 i_chan3buf (
.DOA(do[31:0]), // Port A 32-bit Data Output - CPU side
.DOB(ch3rd[31:0]), // Port B 32-bit Data Output - SDRAM side
.DOPA(), // Port A 4-bit Parity Output
.DOPB(), // Port B 4-bit Parity Output
// .ADDRA({ch3page[1:0],ma[6:0]}), // Port A 9-bit Address Input
.ADDRA({ch3page[1:0],ch3maddr[6:0]}), // Port A 9-bit Address Input
.ADDRB(bmad3[8:0]), // Port B 9-bit Address Input
// .CLKA(mclk), // Port A Clock
.CLKA(!clk0), // Port A Clock
.CLKB(!clk0), // Port B Clock
.DIA(di[31:0]), // Port A 32-bit Data Input
// .DIA(d_late[31:0]), // Port A 32-bit Data Input
.DIB(sddi[31:0]), // Port B 32-bit Data Input
.DIPA(4'b0), // Port A 4-bit parity Input
.DIPB(4'b0), // Port-B 4-bit parity Input
.ENA(menrw), // Port A RAM Enable Input
.ENB(ch3en), // PortB RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEA(mwnr), // Port A Write Enable Input
.WEB(ch3owe) // Port B Write Enable Input
);
// now bmad addresses 32-bit words
always @ (negedge clk0) if (chSt2) curChanLate[3:0] <= curChan[3:0];
bufCntr256 i_bufCntr0 (.clk(clk0), .rst(!enSDRAM), .cs(curChanLate[0]), .init(ch_prefirstdrun), .bank(nBuf[1:0]),
.drun_rd(1'b0), .drun_wr(ch_drun_wr), .dlast(ch_dlast),
.a(bmad0[8:0]), .en(ch0en), .done(dnch[0]));
bufCntr256 i_bufCntr1 (.clk(clk0), .rst(!enSDRAM), .cs(curChanLate[1]), .init(ch_prefirstdrun), .bank(nBuf[1:0]),
.drun_rd(ch_drun_rd), .drun_wr(1'b0), .dlast(ch_dlast),
.a(bmad1[8:0]), .we(ch1we), .done(dnch[1]));
bufCntr256 i_bufCntr2 (.clk(clk0), .rst(!enSDRAM), .cs(curChanLate[2]), .init(ch_prefirstdrun), .bank(nBuf[1:0]),
.drun_rd(ch_drun_rd), .drun_wr(1'b0), .dlast(ch_dlast),
.a(bmad2[8:0]), .we(ch2we), .done(dnch[2]));
bufCntr256 i_bufCntr3 (.clk(clk0), .rst(!enSDRAM), .cs(curChanLate[3]), .init(ch_prefirstdrun), .bank(nBuf[1:0]),
.drun_rd(ch_drun_rd), .drun_wr(ch_drun_wr), .dlast(ch_dlast),
.a(bmad3[8:0]), .en (ch3en), .we(ch3owe), .done(dnch[3])
);
// synchronizing readNextFrame[3:0] (sync to channel clock)
// with the system clock, making sure the pulse will be at least one clk0 long, level -> level
wire [3:0] readNextFrame_rst; // async reset for readNextFrame0[3:0]
reg [3:0] readNextFrameS; // sync to ext clock
reg [3:0] confirmRead0; // 1-st stage of sync
reg [3:0] confirmRead; // second stage of sync
assign readNextFrame_rst[3:0] = confirmRead[3:0] & ~{readNextFrame3,readNextFrame2,readNextFrame1,readNextFrame0};
always @ (posedge ch0clk or posedge readNextFrame_rst[0])
if (readNextFrame_rst[0]) readNextFrameS[0] <= 1'b0;
else readNextFrameS[0] <= readNextFrame0;
always @ (posedge ch1clk or posedge readNextFrame_rst[1])
if (readNextFrame_rst[1]) readNextFrameS[1] <= 1'b0;
else readNextFrameS[1] <= readNextFrame1;
always @ (posedge ch2clk or posedge readNextFrame_rst[2])
if (readNextFrame_rst[2]) readNextFrameS[2] <= 1'b0;
else readNextFrameS[2] <= readNextFrame2;
always @ (posedge clk0 or posedge readNextFrame_rst[3]) // posedge here is OK
if (readNextFrame_rst[3]) readNextFrameS[3] <= 1'b0;
else readNextFrameS[3] <= readNextFrame3;
always @ (negedge clk0) begin
if (!enSDRAM) begin // just for simulation
confirmRead0[3:0] <= 4'h0;
end else begin
confirmRead0[3:0] <= readNextFrameS[3:0];
end
confirmRead[3:0] <= confirmRead0[3:0];
end
descrproc i_descrproc(.clk(clk0), // change later to clk0 (negedge)?
.ia(ia[3:0]), // internal 4-bit address bus (fast - directly from I/O pads)
.as(as[3:0]), // 4 bit address to select descriptor address and data word (3 bits)
.am(am[3:0]), // switching between ia (async read) and as (sync write)
.mcs(dscs), // write descriptor memory (from CPU)
.mdi(di[17:0]), // 16-bit (of 32) data from CPU to descriptor memory
.mdo(dsdo[31:0]), // 31-bit data from descriptor memory to CPU (lower 16 - same as written, high 15 - readonly current state
.chStIn(chSt1), // data channel start (generated by arbiter)
.chInit(chInit), // will be generated by arbiter, arbiter will not wait for confiramtion
.chNum(chNum[1:0]), // 2-bit channel number. Is set by arbiter at chStIn or chInit (is zero when SDRAM is disabled)
.chStOut(chSt2), // channel start output (to sequencer). Delayed by 6 tacts from chStIn
.sa(startAddr[24:3]),// start address of the block
.sfa(sfa[24:8]), // start address of a frame - ugly hack to roll over the last (extra) 4 lines of a frame
// to the beginning of a frame - used in photofinish mode.
.rovr(rovr), // roll over mode (photofinish, cntrl0[12]==1, last line of tiles)
.mode(mode), // mode (0 - 128x1, 1 - 16x8)
.WnR(WnR), // write /not read
// .blkSz(blkSz[6:3]), // block size (4 bits), 0 - all 128
.nBuf(nBuf[1:0]), // buffer page to use
// .nam(nam[6:0]), // address modifier after the group of 8 words is processed. 6 MSBs should go to bits [12..7] of adder input. LSB - to bit [3]
.seq_par(param[5:0]), // [5:0] sequencer parameters
// dual-purpose parameter. In 128x1 mode specifies (4 LSBs) number of 8-word long groups to r/w (0- all 16),
// actually for all but 0 (when exactly 128 words a xfered) will transfer one word more
// In 18x9 mode specifies bits 12:7 of address increment between lines
.mancmd(mancmd[17:0]),// 17-bit manual command for SDRAM (when writig data to RO location 4'h3
.enSDRAM(enSDRAM), // output that enables SDRAM auto access. When 0 - only manual commands are allowed. Written at address 0'h7, bit 0
.enRefresh(enRefresh),// written at address 0'h7, bit 1
.enXfer(enXfer[3:0]), // enable trasfer through channel (will add dependency later)
.chReqInit(chReqInit[3:0]),// request (to arbiter) init channel
.nextFrame(nextFrame[3:0]),// (level) generated before actual block is filled - needed to be combined with the pulse from buffer control
.confirmRead(confirmRead[3:0]), // confirm channel read (level OK), needed after start or roll over, FIFO will not be filled otherwise - should be sync to clk
.bonded (bonded[3:0]), //[3:0] - channel bonded with the other (just for channel 2), make it TIG
.restart_en(restart_en), // enable restarting selected channels
.restart(restart[3:0]), // reinitialize channels (posedge-sensitive, masked by enXfer0
.nextBlocksEn(nextBlocksEn[3:0]) // enable read blocks to FIFO. disabled when init or roll over, enable by confirmRead
// .ch3next(ch3next), // software generated request for the channel 3 xfer (will be OR-ed with hw input) - when writig data to RO location 4'hf);
// .initch3(initch3), // decoded write to channel 3 mode (valid @ MWCLK)
// .wnrbit(wnrbit)
); // data to descriptor memory bit matching wnr (write-not-read)
channelRequest i_channelRequest0 (.rst(!enSDRAM), // probably for simulation only...
.init(chReqInit[0]), // 1 cycle long, sync to iclk
.eclk(ch0clk), // external clock (posedge)
.start(stch0), // sync to eclk start command
.iclk(clk0), // internal clk (negedge)
.enXfer(enXfer[0]), // enable xfer request
.ackn(chnAckn[0]), // acknowledge pulse (sync to iclk)
.wnr(WnR), // will be valid next cycle after ackn (if it was ackn to rqInit)
.done(dnch[0]), // data transfer over
.rq(chnReq[0]), // request (level, sync to iclk)
.rqInit(chnReqInit[0]), // request to Init channel (level, sync to iclk)
.rdy(ch0rdy)); // external ready output
channelRequest i_channelRequest1 (.rst(!enSDRAM), // probably for simulation only...
.init(chReqInit[1]), // 1 cycle long, sync to iclk
.eclk(ch1clk), // external clock (posedge)
.start(stch1), // sync to eclk start command
.iclk(clk0), // internal clk (negedge)
.enXfer(enXfer[1]), // enable xfer request
.ackn(chnAckn[1]), // acknowledge pulse (sync to iclk)
.wnr(WnR), // will be valid next cycle after ackn (if it was ackn to rqInit)
.done(dnch[1]), // data transfer over
.rq(chnReq[1]), // request (level, sync to iclk)
.rqInit(chnReqInit[1]), // request to Init channel (level, sync to iclk)
.rdy(ch1rdy)); // external ready output
channelRequest i_channelRequest2 (.rst(!enSDRAM), // probably for simulation only...
.init(chReqInit[2]), // 1 cycle long, sync to iclk
.eclk(ch2clk), // external clock (negedge)
.start(stch2), // sync to eclk start command
.iclk(clk0), // internal clk (negedge)
.enXfer(enXfer[2]), // enable xfer request
.ackn(chnAckn[2]), // acknowledge pulse (sync to iclk)
.wnr(WnR), // will be valid next cycle after ackn (if it was ackn to rqInit)
.done(dnch[2]), // data transfer over
.rq(chnReq[2]), // request (level, sync to iclk)
.rqInit(chnReqInit[2]), // request to Init channel (level, sync to iclk)
.rdy(ch2rdy)); // external ready output
channelRequest_1 i_channelRequest3 (.rst(!enSDRAM), // probably for simulation only...
.init(chReqInit[3]), // 1 cycle long, sync to iclk. For now - do nothing in dcc mode
.eclk(clk0), // external clock, here the same clk0.
// .start(ch3next), // sync to eclk start command (maybe OR hw & SW ?)
.start(next_ch3), // sync to eclk start command (maybe OR hw & SW ?)
.iclk(clk0), // internal clk (negedge)
.enXfer(enXfer[3]), // enable xfer request
.ackn(chnAckn[3]), // acknowledge pulse (sync to iclk)
.wnr(WnR), // will be valid next cycle after ackn (if it was ackn to rqInit)
.done(dnch[3]), // data transfer over
.rq(chnReq[3]), // request (level, sync to iclk)
.rqInit(chnReqInit[3]), // request to Init channel (level, sync to iclk)
.rdy(), // external ready output
.rdy_async(rdy), // external ready output
.wrempty(wrempty)); // write buffer empty (may reprogram channel)
always @ (posedge disSDRAM or negedge clk0)
if (disSDRAM) ch3page <= 2'b0;
else if (init_ch3) ch3page <= 2'b0;
else if (next_ch3) ch3page <= ch3page+1;
always @ (posedge disSDRAM or negedge clk0)
if (disSDRAM) ch3maddr <=7'b0;
else if (init_ch3 || next_ch3) ch3maddr <=7'b0;
else if (menrw) ch3maddr <= ch3maddr + 1;
// wire ch3wnr;
// reg [ 6:0] ch3maddr;
// FDE i_ch3wnr (.C(mclk),.CE(initch3),.D(wnrbit),.Q(ch3wnr));
refreshRequest i_refreshRequest (.enable(enRefresh), // enable autorefresh
.clk(clk0), //
.ackn(refrStart), // acknowledge pulse (sync to clk)
.rq(chnReq[4])); // request (level, sync to clk)
chArbit i_chArbit(.clk(clk0), // clk0
.rst(!enSDRAM), // disable SDRAM automatic access ("manual" for initialization is still enabled)
.rq(chnReq[4:0]), // request for channels 0..3 and auto refresh
.rqInit(chnReqInit[3:0]), // request init for channels 0..3
.ch(curChan[4:0]), // 1-hot active channel (incl. auto refresh)
.chNum(chNum[1:0]), // [1:0] channel number (to access descriptor memory). SDRAM write mux should register.
.chStart(chSt1), // start data channel (read descriptor,...). Also acknowledge selected channel
.chInit(chInit), // Init channel descriptor (chStart will be also active, but ignored)
.chInitOnehot(chInitOnehot[3:0]), // decoded channel init pulses, 2 cycles behind chInit
.ackn(chnAckn[3:0]), // request acknowledge for channels 0..3
.refrStart(refrStart), // start auto refresh cycle
.next(nextReq)); // from SDRAM sequencer - enable next channel in que.
sdseq i_sdseq (.clk0(clk0), // global clock 75-100MHz (hope to get to 120MHz with Spartan3)
.rst(!enSDRAM), // when active will use mancmd as a source for ras,cas,we,ba,a
.xfer(chSt2), // start block transfer (=stepsEn[2]) - when address is ready
.mode(mode), // 0 - 128x1, 1 - 18x9 (will work only in read mode, channnel 2)
.wnr(WnR),
.refr(refrStart), // start auto refresh (should be delayed same time as read/write)
.sa(startAddr[24:3]), // block start address
.chsel(chNum[1:0]), // channel number (0..3) - used to generate delayed dsel;
.param(param[5:0]), // dual-purpose parameter. In 256x1 mode specifies (5 LSBs) number of 8-word long groups to r/w (0- all 32),
// actually for all but 0 (when exactly 256 words are xfered) will transfer one word more
// In 18x9 mode specifies bits 13:8 of address increment between lines
.mancmd(mancmd[17:0]),// always high except 1 cycle long when it sources {ras,cas,we,ba[1:0],a[11:0]}. Works only whe rst is active
// Will use 18 bits from unused descriptor cell , a[11] will be skipped and set to 1'b0????
.sfa(sfa[24:8]), // start address of a frame - ugly hack to roll over the last (extra) 4 lines of a frame
// to the beginning of a frame - used in photofinish mode.
.rovr(rovr), // roll over mode (photofinish, cntrl0[12]==1, last line of tiles)
.drun_rd(ch_drun_rd), // enable read data (from SDRAM) to blockRAM buffer
.drun_wr(ch_drun_wr), // enable write data (to SDRAM) from blockRAM buffer
.prefirstdrun(ch_prefirstdrun), // 1 cycle ahead of the first drun_rd/drun_wr to be used by bufCntr256 to sample channel enable
.dlast(ch_dlast), //last cycle of drun active for read, 1 cycle later for write
.precmd({sdras,
sdcas,
sdwe}), // 1 cycle ahead {ras,cas,we} command bits to be registered at the output pads
.prea(sda[12:0]), // 13 bits (including ba) 1 cycle ahead of output A[12:0]
.preb(sdba[1:0]), // 2 bits of bank address 1 cycle ahead of output BA[1:0]
.next(nextReq), // get next request from que.
.pre2trist(trist), // tristate data outputs (two ahead).
.predqt(predqt), // tristate DQ outputs (one extra for FF in output buffer)
.dmask(dmask[1:0]), // [1:0] - now both the same (even number of words written)
.dqs_re(dqs_re), // enable read from DQS i/o-s for phase adjustments (latency 2 from the SDRAM RD command)
.dsel(dsel[1:0])); // data buffer select (number of buffer to source SDRAM data in), so it is needed only for WRITE to SDRAM
endmodule
// To add extra register layer between blockRAM and SDRAM modify sdseq to generate run8, last 1 cycle earlier in write mode,
// modify bufCntr, bufCntr3 to delay done output in write mode.
module bufCntr256 (clk, // SDRAM clock (negedge)
rst, // needed for simulation only...
cs, // enables init and xfer commands
init, // 1-cycle cmd: reset address to 9'h00/9'h80/9'h100/9'h180 depending on bank, store wnr.
bank, // quater of buffer to use
drun_rd, // enable write data to buffer (read from SDRAM)
drun_wr, // enable read data from buffer (write to SDRAM)
dlast,// accompanies the last cycle of drun - will generate done and skip to next bank. Delayed by 1 for buff->SDRAM
// Not needed for full block transfers
a, // buffer address
en, // buffer r/w enable
we, // buffer write enable
done);
input clk;
input rst;
input cs;
input init;
input [1:0] bank;
input drun_rd;
input drun_wr;
input dlast;
output [8:0] a;
output en;
output we;
output done;
reg we;
reg en;
reg [8:0] a;
reg done;
reg cs_r;
wire sinit= cs && init;
always @ (negedge clk) begin
if (rst) cs_r <= 1'b0;
else if (init) cs_r <= cs;
en <= cs_r && (drun_rd || drun_wr);
we <= cs_r && drun_rd;
done <= cs_r && dlast; // dlast should be already delayed by 1 cycle for buff->SDRAM
if (rst || sinit || done) a[6:0] <=7'b0;
else if (en) a[6:0] <= a[6:0]+1;
a[8:7] <= {~rst,~rst} & (sinit ? bank[1:0]: (a[8:7]+ done));
end
endmodule
module channelRequest (rst, // only for simulation?
init, // 1 cycle long, sync to iclk
eclk, // external clock (posedge)
start, // sync to eclk start command
iclk, // internal clk (negedge)
enXfer,// enable xfer request
ackn, // acknowledge pulse (sync to iclk)
wnr, // will be valid skipping 2 cycles (better - 3) ackn (if it was ackn to rqInit)
done, // data transfer over
rq, // request (level, sync to iclk)
rqInit,// request to Init channel (level, sync to iclk)
rdy, // external ready output - valid with continuous eclk only
rdy_async, // w/o eclk
wrempty);// nothing left to write (may reprogram channel). Now in read mode indicates that there are no pending reads
input rst;
input init;
input eclk;
input start;
input iclk;
input ackn;
input wnr;
input done;
input enXfer;
output rq;
output rqInit;
output rdy;
output rdy_async;
output wrempty;
reg [2:0] ecnt; // gray, 0->1->3->2->6->7->5->4
reg [2:0] icnt; // gray, 0->1->3->2->6->7->5->4
reg [2:0] rcnt; // gray, 0->1->3->2->6->7->5->4
wire[2:0] next_ecnt;
wire[2:0] next_icnt;
wire[2:0] next_rcnt;
wire cntrsInit;
reg cntrsValid;
reg rq;
reg rqInit;
wire ready_off; // counter comparison, goes active with eclk, inactive - with iclk
reg rdy;
reg en_done; // to disable done initiated by previous activity
reg current_wnr;
wire rdy_async;
assign rdy_async=!ready_off;
// async clock metastability (ecnt[2:0]!=rcnt[2:0]) and (ecnt[2:0]!=icnt[2:0]) should not be a problem
// as "other" clock may only change from rq inactive to rq active (reverse is done by "this" clock), so
// there will be no false rq, only may be missed - and it is OK, it will be served later.
// rq may have a one-cycle glitch from "active" to "inactive" it should not cause problems in chArbit
// same is valid for "rdy" output - it may only be pessimistic, no false rdy.
assign next_ecnt={ecnt[2]^ ((ecnt==3'b010)||(ecnt==3'b100)),
ecnt[1]^ ((ecnt==3'b001)||(ecnt==3'b111)),
~ecnt[2] ^ ecnt[1]};
assign next_icnt={icnt[2]^ ((icnt==3'b010)||(icnt==3'b100)),
icnt[1]^ ((icnt==3'b001)||(icnt==3'b111)),
~icnt[2] ^ icnt[1]};
assign next_rcnt={rcnt[2]^ ((rcnt==3'b010)||(rcnt==3'b100)),
rcnt[1]^ ((rcnt==3'b001)||(rcnt==3'b111)),
~rcnt[2] ^ rcnt[1]};
always @ (negedge iclk) en_done <= !rqInit && (en_done || ackn);
assign ready_off= !cntrsValid || (ecnt[2:0] == rcnt[2:0]);
always @ (posedge eclk or posedge rst)
if (rst) ecnt <= 2'b0;
else if (start) ecnt[2:0] <= next_ecnt;
// reduce latency of rdy - valid next cycle after start
always @ (posedge eclk or posedge ready_off)
if (ready_off) rdy <= 1'b0;
else rdy <= 1'b1;
assign wrempty= cntrsValid && (current_wnr?(ecnt[2:0]=={!rcnt[2],!rcnt[1],rcnt[0]}):(icnt[2:0] != ecnt[2:0]));
always @ (negedge iclk) begin
cntrsValid <= cntrsInit || (cntrsValid && ! init);
rqInit <= !rst && (init || (rqInit && !ackn));
if (cntrsInit) current_wnr <=wnr;
icnt[2:0] <= cntrsInit? {ecnt[2]^(!wnr),ecnt[1]^(!wnr),ecnt[0]}: ((ackn && cntrsValid)? next_icnt[2:0]: icnt[2:0]);
rcnt[2:0] <= cntrsInit? {ecnt[2]^( wnr),ecnt[1]^( wnr),ecnt[0]}: ((en_done && done && cntrsValid)? next_rcnt[2:0]: rcnt[2:0]);
rq <= rqInit || (enXfer && cntrsValid && (icnt[2:0] != ecnt[2:0]));
end
// SRL16_1 i_cntrsInit (.Q(cntrsInit), .A0(1'b1), .A1(1'b1), .A2(1'b0), .A3(1'b0), .CLK(iclk), .D(ackn && rqInit)); // dly=3+1
MSRL16_1 i_cntrsInit (.Q(cntrsInit), .A(4'h3), .CLK(iclk), .D(ackn && rqInit));// dly=3+1
endmodule
module channelRequest_1 (rst, // only for simulation?
init, // 1 cycle long, sync to iclk
eclk, // external clock (negedge)
start, // sync to eclk start command
iclk, // internal clk (negedge)
enXfer,// enable xfer request
ackn, // acknowledge pulse (sync to iclk)
wnr, // will be valid skipping 2 cycles (better - 3) ackn (if it was ackn to rqInit)
done, // data transfer over
rq, // request (level, sync to iclk)
rqInit,// request to Init channel (level, sync to iclk)
rdy, // external ready output - valid with continuous eclk only
rdy_async, // w/o eclk
wrempty);// nothing left to write (may reprogram channel). Now in read mode indicates that there are no pending reads
input rst;
input init;
input eclk;
input start;
input iclk;
input ackn;
input wnr;
input done;
input enXfer;
output rq;
output rqInit;
output rdy;
output rdy_async;
output wrempty;
reg [2:0] ecnt; // gray, 0->1->3->2->6->7->5->4
reg [2:0] icnt; // gray, 0->1->3->2->6->7->5->4
reg [2:0] rcnt; // gray, 0->1->3->2->6->7->5->4
wire[2:0] next_ecnt;
wire[2:0] next_icnt;
wire[2:0] next_rcnt;
wire cntrsInit;
reg cntrsValid;
reg rq;
reg rqInit;
wire ready_off; // counter comparison, goes active with eclk, inactive - with iclk
reg rdy;
reg en_done; // to disable done initiated by previous activity
reg current_wnr;
wire rdy_async;
assign rdy_async=!ready_off;
// async clock metastability (ecnt[2:0]!=rcnt[2:0]) and (ecnt[2:0]!=icnt[2:0]) should not be a problem
// as "other" clock may only change from rq inactive to rq active (reverse is done by "this" clock), so
// there will be no false rq, only may be missed - and it is OK, it will be served later.
// rq may have a one-cycle glitch from "active" to "inactive" it should not cause problems in chArbit
// same is valid for "rdy" output - it may only be pessimistic, no false rdy.
assign next_ecnt={ecnt[2]^ ((ecnt==3'b010)||(ecnt==3'b100)),
ecnt[1]^ ((ecnt==3'b001)||(ecnt==3'b111)),
~ecnt[2] ^ ecnt[1]};
assign next_icnt={icnt[2]^ ((icnt==3'b010)||(icnt==3'b100)),
icnt[1]^ ((icnt==3'b001)||(icnt==3'b111)),
~icnt[2] ^ icnt[1]};
assign next_rcnt={rcnt[2]^ ((rcnt==3'b010)||(rcnt==3'b100)),
rcnt[1]^ ((rcnt==3'b001)||(rcnt==3'b111)),
~rcnt[2] ^ rcnt[1]};
always @ (negedge iclk) en_done <= !rqInit && (en_done || ackn);
assign ready_off= !cntrsValid || (ecnt[2:0] == rcnt[2:0]);
always @ (negedge eclk or posedge rst)
if (rst) ecnt <= 2'b0;
else if (start) ecnt[2:0] <= next_ecnt;
// reduce latency of rdy - valid next cycle after start
always @ (negedge eclk or posedge ready_off)
if (ready_off) rdy <= 1'b0;
else rdy <= 1'b1;
assign wrempty= cntrsValid && (current_wnr?(ecnt[2:0]=={!rcnt[2],!rcnt[1],rcnt[0]}):(icnt[2:0] != ecnt[2:0]));
always @ (negedge iclk) begin
cntrsValid <= cntrsInit || (cntrsValid && ! init);
rqInit <= !rst && (init || (rqInit && !ackn));
if (cntrsInit) current_wnr <=wnr;
icnt[2:0] <= cntrsInit? {ecnt[2]^(!wnr),ecnt[1]^(!wnr),ecnt[0]}: ((ackn && cntrsValid)? next_icnt[2:0]: icnt[2:0]);
rcnt[2:0] <= cntrsInit? {ecnt[2]^( wnr),ecnt[1]^( wnr),ecnt[0]}: ((en_done && done && cntrsValid)? next_rcnt[2:0]: rcnt[2:0]);
rq <= rqInit || (enXfer && cntrsValid && (icnt[2:0] != ecnt[2:0]));
end
// SRL16_1 i_cntrsInit (.Q(cntrsInit), .A0(1'b1), .A1(1'b1), .A2(1'b0), .A3(1'b0), .CLK(iclk), .D(ackn && rqInit)); // dly=3+1
MSRL16_1 i_cntrsInit (.Q(cntrsInit), .A(4'h3), .CLK(iclk), .D(ackn && rqInit));// dly=3+1
endmodule
module refreshRequest (enable,// enable autorefresh
clk, //
ackn, // acknowledge pulse (sync to clk)
rq); // request (level, sync to clk)
parameter REFRESHPERIOD=11'h400;
input enable;
input clk;
input ackn;
output rq;
reg [12:0] nRefrDue;
reg [10:0] rcntr;
reg rtim;
reg rq;
always @ (negedge clk)
if (!enable) nRefrDue <= {1'b1,12'b0};
else if (ackn) nRefrDue <= nRefrDue - 1;
else if (rtim) nRefrDue <= nRefrDue + 1;
always @ (negedge clk) begin
if (!enable | rtim) rcntr[10:0] <= REFRESHPERIOD;
else rcntr[10:0] <= rcntr-1;
rtim <= !nRefrDue[12] && !(|rcntr[10:0]); // nRefrDue[12] to "saturate" number of refr. cycles due to 4096
end
always @ (negedge clk) rq <= enable && |nRefrDue[12:0];
endmodule
///Adding chInitOnehot output
module chArbit (clk, // SDCLK
rst, // disable SDRAM automatic access ("manual" for initialization is still enabled)
rq, // request for channels 0..3 and auto refresh
rqInit, // request init for channels 0..3
ch, // 1-hot active channel (incl. auto refresh)
chNum, // [1:0] channel number (to access descriptor memory). SDRAM write mux should register.
chStart, // start data channel (read descriptor,...). Also acknowledge selected channel
chInit, // Init channel descriptor (chStart will be also active, but ignored)
chInitOnehot, // decoded channel init pulses, 2 cycles behind chInit
ackn, // request acknowledge for channels 0..3
refrStart, // start auto refresh cycle
next); // from SDRAM sequencer - enable next channel in que.
input clk,rst;
input [4:0] rq;
input [3:0] rqInit;
output [4:0] ch;
output [1:0] chNum;
output chStart;
output chInit;
output [3:0] chInitOnehot;
output [3:0] ackn;
output refrStart;
input next;
reg [4:0] ch;
reg [3:0] chInitOnehot;
reg [3:0] ch_d; /// ch[3:0] delayed by 1 clock;
reg chInit_d; /// chInit delayed by 1 clock;
reg [4:0] prq; /// priority applied
reg [1:0] chNum;
reg chStart;
reg chInit;
wire wasChInit;
reg refrStart;
wire eqZero=(ch[4:0]==5'b0);
reg [3:0] ackn;
always @ (negedge clk )
prq[4:0]<={rq[4:0]==5'b10000,
rq[3:0]==4'b1000,
rq[2:0]==3'b100,
rq[1:0]==2'b10,
rq[0] ==1'b1
};
always @ (negedge clk or posedge rst)
if (rst) begin
ch[4:0] <= 5'b0;
chStart <= 1'b0;
chInit <= 1'b0;
ackn[3:0] <= 4'b0;
refrStart <= 1'b0;
chNum[1:0] <= 2'b0;
end else begin
if (next || eqZero) ch[4:0] <= prq[4:0];
else if (wasChInit) ch[4:0] <= 5'b0;
chStart <= (next || eqZero) && (prq[3:0]!=0);
ackn[3:0] <= {(next || eqZero) && prq[3],
(next || eqZero) && prq[2],
(next || eqZero) && prq[1],
(next || eqZero) && prq[0]};
chInit <= (next || eqZero) && ((prq[3:0] & rqInit[3:0])!=0);
refrStart <= (next || eqZero) && prq[4];
if (chStart) chNum[1:0] <= {ch[2] || ch[3], ch[1] || ch[3]};
end
MSRL16_1 i_wasChInit (.Q(wasChInit), .A(4'h1), .CLK(clk), .D(chInit));// dly=1+1
always @ (negedge clk) begin
ch_d[3:0] <= ch[3:0];
chInit_d <= chInit;
chInitOnehot <= {4{chInit_d}} & ch_d[3:0];
end
endmodule
88888888 88888888 88888888 88888888 88888888 88888888 88888888 88888888
ffffffff ffffffff eeeeeeef fdddddde 11257777 bbbaa990 dddccccc fddddddd
ffffffff ffffffff ffffffff ffffffff 99126777 eeddccba fffffffe ffffffff
ffffffff ffffffff ffffffff ffffffff ba914777 ffffeedc ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff dba03777 fffffffd ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff edb91777 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff feda1777 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffeb0777 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffd9577 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffea477 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffb377 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffc277 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffc277 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffd177 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffe177 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffff077 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffff977 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffff977 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffff977 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffffa77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffffb77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffffb77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffffc77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffffd77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffffd77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff fffffe77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffff77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffff77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffff77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffff77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffff77 ffffffff ffffffff ffffffff
ffffffff ffffffff ffffffff ffffffff ffffff77 ffffffff ffffffff ffffffff
88888888 88888888 88888888 88888888 88888888 88888888 88888888 88888888
99adffff 33322110 55544444 75555555 77777777 77777777 66666667 75555556
119aefff 66554432 77777776 77777777 77777777 77777777 77777777 77777777
3219cfff 77776654 77777777 77777777 77777777 77777777 77777777 77777777
5320bfff 77777775 77777777 77777777 77777777 77777777 77777777 77777777
65319fff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
76529fff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
77630fff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
77751dff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
77762cff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
77773bff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
77774aff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
77774aff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777759ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777769ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777770ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777771ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777771ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777771ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777772ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777773ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777773ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777774ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777775ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777775ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777776ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777777ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777777ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777777ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777777ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777777ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
777777ff 77777777 77777777 77777777 77777777 77777777 77777777 77777777
#!/bin/sh
UNISIMS="../unisims"
rm -vf motors.lxt
echo "Using UNISIM library $UNISIMS"
time iverilog -Dlegacy_model -gno-specify -v -o motors_test -sglbl -stestbench \
-y$UNISIMS \
motors_tb.v \
10364.v \
macros353.v \
glbl.v \
|| { echo "iverilog failed"; exit 1; }
time vvp -v motors_test -lxt2 || { echo "vvp failed"; exit 1; }
gtkwave motors.lxt motors2.sav &
exit 0
`timescale 1ns/1ps
/*
* It is just a placeholder for a real testbench. Made from 333, not everything updated
*/
module testbench();
parameter CLK_PER = 6.25;// 160MHz
parameter CLK2WA= 1;
parameter WA2WD= 1;
parameter aaaa=0;
parameter aaaa=1;
reg sclk,xclk;
reg [15:0] wd;
reg wa;
reg we;
wire [15:0] rd;
// reg [1:0] encod1;
// reg [1:0] encod2;
// reg [1:0] encod3;
wire [1:0] encod1;
wire [1:0] encod2;
wire [1:0] encod3;
wire [1:0] mot1;
wire [1:0] mot2;
wire [1:0] mot3;
reg sim_mot_en;
three_motor_driver i_three_motor_driver(
.clk(sclk), // system clock, negedge
.xclk(xclk), // half frequency (80 MHz nominal)
.we(we), // write enable (lower 16 bits, high - next cycle)
.wa(wa), // write address(1)/data(0)
.di(wd), // 16-bit data in (32 multiplexed)
.do(rd), // 16-bit data output
.encod1(encod1[1:0]), // 2-bit encoder data input, motor1
.encod2(encod2[1:0]), // 2-bit encoder data input, motor2
.encod3(encod3[1:0]), // 2-bit encoder data input, motor3
.mot1(mot1[1:0]), // 2 bits motor1 control output (11 - shorted, 00 - stop)
.mot2(mot2[1:0]), // 2 bits motor1 control output (11 - shorted, 00 - stop)
.mot3(mot3[1:0]) // 2 bits motor1 control output (11 - shorted, 00 - stop)
);
motor i_motor1 (.clk(xclk),
.en(sim_mot_en),
.pwr(mot1[1:0]),
.enc(encod1[1:0]));
motor i_motor2 (.clk(xclk),
.en(sim_mot_en),
.pwr(mot2[1:0]),
.enc(encod2[1:0]));
motor i_motor3 (.clk(xclk),
.en(sim_mot_en),
.pwr(mot3[1:0]),
.enc(encod3[1:0]));
initial begin
$dumpfile("motors.lxt");
$dumpvars(0,testbench.i_three_motor_driver);
/*
$dumpvars(0,testbench.i_three_motor_driver.addr);
$dumpvars(0,testbench.i_three_motor_driver.reg_addr);
$dumpvars(0,testbench.i_three_motor_driver.inc);
$dumpvars(0,testbench.i_three_motor_driver.dec);
$dumpvars(0,testbench.i_three_motor_driver.inc_dec);
$dumpvars(0,testbench.i_three_motor_driver.minus_diff);
$dumpvars(0,testbench.i_three_motor_driver.position_err);
$dumpvars(0,testbench.i_three_motor_driver.dir_this);
$dumpvars(0,testbench.i_three_motor_driver.enc_period_this);
$dumpvars(0,testbench.i_three_motor_driver.pwm_code);
$dumpvars(0,testbench.i_three_motor_driver.sequence);
$dumpvars(0,testbench.i_three_motor_driver.position_diff);
$dumpvars(0,testbench.i_three_motor_driver.i_motor_pwm);
*/
$dumpvars(0,testbench.rd);
$dumpvars(0,testbench.i_motor1);
$dumpvars(0,testbench.i_motor2.position);
$dumpvars(0,testbench.i_motor2.speed);
$dumpvars(0,testbench.i_motor3.position);
$dumpvars(0,testbench.i_motor3.speed);
$dumpvars(0,testbench.encod1);
$dumpvars(0,testbench.encod2);
$dumpvars(0,testbench.encod3);
sclk<=0;
xclk<=0;
// encod1 <= 0;
// encod2 <= 0;
// encod3 <= 0;
sim_mot_en <=0;
wait (~glbl.GSR);
// sclk<=1;
$display ("reset done at %t",$time);
#10;
write_ad (1,4);
write_ad (0,6);
write_ad (0,'h7243); ///pwm_cycle=0x43, pwm_delay=2, deglitch_div=7
write_ad (0,'h457); ///enc_period_cycle=0x457
write_ad (0,'h2); ///decrement_on_pulse
write_ad (1,1); // target position
write_ad (0,0); // target position1
write_ad (0,0); // target position2
write_ad (0,0); // target position3
program_table;
write_ad (1,4);
write_ad (0,7); // reset, then enable motors
#1000; // wait 1 usec
write_ad (1,1);
write_ad (0,32'hffffffce); // write motor1 target - -50
write_ad (0,10); // write motor2 target - +10
write_ad (0,1); // write motor3 target - +1
write_ad (1,1); // point data out to motor1 position
sim_mot_en <= 1'b1;
#10000000;
$finish;
#60000000;
write_ad (1,1); // target position
write_ad (0,0); // target position1
write_ad (0,0); // target position2
write_ad (0,0); // target position3
write_ad (1,4);
write_ad (0,2); // disable motors
#1000000;
// #21000000;
$finish;
end
// always #(CLK_PER/2) if (~glbl.GSR) sclk <= ~sclk;
always #(CLK_PER/2) sclk <= ~sclk;
always @ (posedge sclk) xclk <= ~xclk;
task write_ad;
input a;
input [31:0] d;
begin
wait(sclk);wait(~sclk);
#CLK2WA;
wa=a;
we=1'b1;
#WA2WD;
wd=d[15:0];
wait(sclk);wait(~sclk);
#CLK2WA;
wa=1'bx;
we=1'b0;
#WA2WD;
wd=d[31:16];
wait(sclk);wait(~sclk);
#CLK2WA;
#WA2WD;
wd=16'bx;
end
endtask
task program_table;
reg [31:0] data[0:511];
integer i;
begin
$readmemh("motor.dat",data);
write_ad (1,512);
for (i=0;i<512;i=i+1) begin
write_ad (0,data[i]);
end
end
endtask
endmodule
module motor (clk,
en,
pwr,
enc);
parameter SAMPLE_PERIOD=100; // ns
parameter VMAX=1000.0; /// pulses/sec
parameter EMF= 0.5; /// part of the voltage that is caused by rotation (remaining goes to current -> force->acceleration). Not yet used
// parameter ACCEL=10.0; /// number of VMAX/sec if full power is applied, speed==0
parameter ACCEL=300.0; /// number of VMAX/sec if full power is applied, speed==0
// no simulation of friction yet
input clk;
input en;
input [1:0] pwr;
output [1:0] enc;
reg mclk;
real position, position0;
real speed, speed0;
// time t,t0;
integer itime;
real rtime;
reg [1:0] enc;
reg [1:0] enc_bin;
real t,t0, dt, e,f;
initial begin
position0=0;
speed0=0;
t0=$time;
mclk=0;
end
always #(SAMPLE_PERIOD/2) mclk <= ~mclk;
// always @ (posedge clk) begin
always @ (posedge mclk) begin
t=$time;
dt=(t-t0)/1000000000; // in seconds
case (pwr)
0: f<=(speed>0)?-1.0:1.0;
1: f<=1.0;
2: f<=-1.0;
3: f<=0.0;
endcase
e=f-speed/VMAX;
speed=speed0+ACCEL*VMAX*e*dt;
position=position0+(speed+speed0)*dt/2;
enc_bin[1:0]=position;
#1;
// itime=sim_time;
// rtime=sim_time;
enc[1:0] <= {enc_bin[1],enc_bin[1] ^ enc_bin[0]};
t0=t;
speed0=speed;
position0=position;
end
endmodule
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
5550 8000 8000 5550 8000 8000 5550 5550
5550 5550 4000 5550 5550 4000 3330 2000
3330 3330 4000 4000 3330 19a0 2490 2490
2ab0 2000 1550 19a0 1550 1550 1740 19a0
1740 1740 13b0 1250 e40 1000 13b0 1250
f10 1250 1740 1740 1000 ba0 1000 f10
d80 cd0 c30 c30 c30 1550 1110 b20
ab0 ba0 cd0 ab0 e40 cd0 c30 cd0
5550 4000 4000 3330 4000 3330 1c70 3330
3330 1c70 cd0 13b0 1740 13b0 cd0 cd0
cd0 cd0 cd0 cd0 cd0 cd0 cd0 cd0
cd0 cd0 cd0 cd0 cd0 cd0 cd0 cd0
cd0 cd0 cd0 cd0 cd0 cd0 cd0 cd0
cd0 cd0 cd0 cd0 cd0 cd0 cd0 cd0
cd0 cd0 cd0 cd0 cd0 cd0 cd0 cd0
cd0 cd0 cd0 cd0 cd0 cd0 cd0 cd0
/*
** -----------------------------------------------------------------------------**
** quantizator353.v
**
** Quantizator module for JPEG compressor
**
** Copyright (C) 2002-2010 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
`timescale 1ns/1ps
// will add extracted DC (8 bits) to data from DCT here that will make data 12 bits (signed) long.
// It will be possible to make a sequincial multiplier for DC - but I'll skip this opportunity now.
//********** TODO: switch to 16-bit tables instead of the 12-bit ones **************
module quantizator(clk, // pixel clock
en, // enable (0 resets counter)
sclk, // system clock, twqe, twce, ta,tdi - valid @negedge (ra, tdi - 2 cycles ahead
twqe, // enable write to a quantization table
twce, // enable write to a coring table
ta, // [6:0] table address
tdi, // [15:0] table data in (8 LSBs - quantization data)
// readback, // readback data
ctypei, // component type input (Y/C)
dci, // [7:0] - average value in a block - subtracted before DCT
first_stb, //this is first stb pulse in a frame
stb, // strobe that writes ctypei, dci
tsi, // table (quality) select [2:0]
pre_start,// marks first input pixel (one before)
first_in, // first block in (valid @ start)
first_out, // valid @ ds
di, // [11:0] pixel data in (signed)
do, // [11:0] pixel data out (AC is only 9 bits long?) - changed to 10
dv, // data out valid
ds, // data out strobe (one ahead of the start of dv)
dc_tdo, //[15:0], MSB aligned coefficient for the DC component (used in focus module)
// dc_tdo_stb,
dcc_en, // enable dcc (sync to beginning of a new frame)
hfc_sel, // hight frequency components select [2:0] (includes components with both numbers >=hfc_sel
// hfc_sel == 3'h7 - now high frequency output - just 3 words - brightness and 2 color diffs
color_first, // first MCU in a frame
coring_num, // coring table pair number (0..7)
dcc_vld, // single cycle when dcc_data is valid
dcc_data, // [15:0] dc component data out (for reading by software)
n000, // input [7:0] number of zero pixels (255 if 256) - to be multiplexed with dcc
n255); // input [7:0] number of 0xff pixels (255 if 256) - to be multiplexed with dcc
input clk;
input en;
input sclk;
input twqe;
input twce;
input [ 8:0] ta;
input [15:0] tdi;
input ctypei;
input [ 8:0] dci; // now normal signed number
input first_stb; //this is first stb pulse in a frame
input stb;
input [ 2:0] tsi;
input pre_start;
input first_in; // first block in (valid @ start)
output first_out; // valid @ ds
input [12:0] di;
output[12:0] do;
output dv;
output ds;
output [15:0] dc_tdo;
input dcc_en;
input [2:0] hfc_sel;
input color_first;
input [2:0] coring_num; // Coring table number (0..7)
output dcc_vld;
output[15:0] dcc_data;
input [7:0] n000;
input [7:0] n255;
wire [3:0] tdco; // coring table output
reg [3:0] tbac; // coring memory table number (LSB - color)
reg coring_range; // input <16, use coring LUT
wire [15:0] tdo;
reg [ 9:0] tba; // table output (use) address
wire [15:0] zigzag_q;
reg wpage,
rpage;
wire [5:0] zwa;
reg [5:0] zra;
reg [12:0] qdo;
reg [12:0] qdo0;
reg zwe;
reg [12:0] d1;
reg [12:0] d2,d3; // registered data in, converted to sign+ absolute value
wire [27:0] qmul;
wire start_a;
reg [15:0] tdor;
reg [20:0] qmulr; // added 7 bits to total8 fractional for biasing/zero bin
wire start_out;
wire start_z;
reg ds;
reg dv;
reg [ 8:0] dc1; // registered DC average - with restored sign
// for fifo for ctype, dc
wire ctype;
wire [8:0] dc;
wire next_dv;
reg [ 5:0] start;
wire [15:0] dcc_data;
wire dcc_stb;
reg dcc_vld;
reg dcc_run;
reg dcc_first;
reg dcc_Y;
reg [1:0] ctype_prev;
reg [12:0] dcc_acc;
reg [12:0] hfc_acc;
wire hfc_en;
reg hfc_copy; // copy hfc_acc to dcc_acc
wire [10:0] d2_dct; // 11 bits enough, convetred to positive (before - 0 was in the middle - pixel value 128) - dcc only
reg sel_satnum; // select saturation numbers - dcc only
reg twqe_d; //twqe delayed (write MSW)
reg twce_d; //twce delayed (write MSW)
reg [15:0] dc_tdo;
reg [15:0] pre_dc_tdo;
wire copy_dc_tdo;
wire first_in; // first block in (valid @ pre_start)
reg first_interm, first_out; // valid @ ds
wire [2:0] ts;
wire [2:0] coring_sel;
reg [2:0] block_mem_ra;
reg [2:0] block_mem_wa;
reg [2:0] block_mem_wa_save;
reg [15:0] block_mem[0:7];
wire [15:0] block_mem_o=block_mem[block_mem_ra[2:0]];
assign dc[8:0]= block_mem_o[8:0];
assign ctype= block_mem_o[9];
assign ts[2:0]= block_mem_o[12:10];
assign coring_sel[2:0]= block_mem_o[15:13];
assign start_a=start[5];
assign start_z=start[4];
assign dcc_stb=start[2];
always @ (posedge clk) begin
if (stb) block_mem[block_mem_wa[2:0]] <= {coring_num[2:0],tsi[2:0], ctypei, dci[8:0]};
if (!en) block_mem_wa[2:0] <= 3'h0;
else if (stb) block_mem_wa[2:0] <= block_mem_wa[2:0] +1;
if (stb && first_stb) block_mem_wa_save[2:0] <= block_mem_wa[2:0];
if (!en) block_mem_ra[2:0] <= 3'h0;
else if (pre_start) block_mem_ra[2:0] <= first_in?block_mem_wa_save[2:0]:(block_mem_ra[2:0] +1);
end
assign d2_dct[10:0]={!d2[11] ^ ctype_prev[0], d2[9:0]};
assign dcc_data[15:0]=sel_satnum?
{n255[7:0],n000[7:0]}:
{dcc_first || (!dcc_Y && dcc_acc[12]) ,(!dcc_Y && dcc_acc[12]), (!dcc_Y && dcc_acc[12]), dcc_acc[12:0]};
assign do[12:0]=zigzag_q[12:0];
// assign qmul[23:0]=tdor[11:0]*d3[11:0];
assign qmul[27:0]=tdor[15:0]*d3[11:0];
assign start_out = zwe && (zwa[5:0]== 6'h3f); //adjust?
assign copy_dc_tdo = zwe && (zwa[5:0]== 6'h37); // not critical
assign next_dv=en && (ds || (dv && (zra[5:0]!=6'h00)));
always @ (posedge clk) begin
d1[12:0] <= di[12:0];
//inv_sign
// dc1[8:0] <= start[0]?{{2{~dc[7]}},dc[6:0]}:9'b0; // sync to d1[8:0]ctype valid at start, not later
dc1[8:0] <= start[0]?dc[8:0]:9'b0; // sync to d1[8:0]ctype valid at start, not later
d2[12:0] <= {dc1[8],dc1[8:0],3'b0} + d1[12:0];
d3[12] <= d2[12];
d3[11:0] <= d2[12]? -d2[11:0]:d2[11:0];
if (start[0] || !en) tba[9:6] <= {ts[2:0],ctype};
/// TODO - make sure ctype switches at needed time (compensate if needed) *****************************************
if (start[3] || !en) tbac[3:0] <= {coring_sel[2:0],ctype}; // table number to use
if (start[0]) tba[5:0] <= 6'b0;
else if (tba[5:0]!=6'h3f) tba[5:0] <= tba[5:0]+1;
tdor[15:0] <= tdo[15:0]; // registered table data out
if (start[3]) pre_dc_tdo[15:0] <= tdor[15:0]; //16-bit q. tables)
if (copy_dc_tdo) dc_tdo[15:0] <= pre_dc_tdo[15:0];
qmulr[19:0] <= qmul[27:8]; // absolute value
qmulr[20] <= d3[12]; // sign
qdo0[12] <= qmulr[20]; // sign
// tdco[3:0] - same timing as qdo0;
// use lookup table from 8 bits of absolute value (4.4 - 4 fractional) to calculate 4 bit coring output that would replace output
// if input is less thahn 16. For larger values the true rounding will be used.
// Absolute values here have quantization coefficients already applied, so we can use the same coring table for all DCT coefficients.
// there are be 16 tables - 8 Y/C pairs to switch
qdo0[11:0] <= qmulr[19:8] + qmulr[7]; // true rounding of the absolute value
coring_range<= !(|qmulr[19:12]) && !(&qmulr[11:7]) ; // valid with qdo0
// qdo[11:0] <= coring_range? {8'h0,tdco[3:0]}:qdo0[11:0];
qdo[11:0] <= coring_range? (qdo0[12]?-{8'h0,tdco[3:0]}:{8'h0,tdco[3:0]}):(qdo0[12]?-qdo0[11:0]:qdo0[11:0]);
qdo[12] <= qdo0[12] && (!coring_range || (tdco[3:0]!=4'h0));
if (start_out) rpage <= wpage;
if (start_out) zra[5:0] <= 6'b0;
else if (zra[5:0]!=6'h3f) zra[5:0] <=zra[5:0]+1; // conserving energy
ds <= start_out;
dv <= next_dv;
if (start_a) first_interm <= first_in;
if (start_out) first_out <=first_interm;
// zwe???
zwe <= en && (start_a || (zwe && (zwa[5:0]!=6'h3f)));
if (!en) wpage <= 1'b0;
else if (start_a) wpage <= ~wpage;
end
always @ (posedge clk) begin
sel_satnum <= dcc_run && (start[0]? (ctype_prev[1:0]==2'b10): sel_satnum);
hfc_copy <= dcc_run && (hfc_sel[2:0]!=3'h7) && (tba[5:0]==6'h1f) && ctype_prev[0] && ctype_prev[1];
start[5:0] <= {start[4:0], pre_start}; // needed?
if (!dcc_en) dcc_run <= 1'b0;
else if (start[0]) dcc_run <= 1'b1;
if (!dcc_en) ctype_prev[1:0] <= 2'b11;
else if (start[0]) ctype_prev[1:0] <= {ctype_prev[0],ctype && dcc_run};
if (dcc_stb || hfc_copy) dcc_acc[12:0] <= hfc_copy?
hfc_acc[12:0]:
{(d2_dct[10]&&ctype_prev[0]),(d2_dct[10]&&ctype_prev[0]),d2_dct[10:0]}+((ctype_prev[0] || ctype_prev[1])?13'h0:dcc_acc[12:0]);
if (!dcc_run || hfc_copy) hfc_acc <=13'b0;
else if (hfc_en) hfc_acc <= hfc_acc + {2'b0, d3[10:0]};
if (dcc_stb) dcc_first <= color_first && dcc_run && dcc_stb && ctype && !ctype_prev[0];
if (dcc_stb) dcc_Y <= dcc_run && dcc_stb && ctype && !ctype_prev[0];
dcc_vld <= (dcc_run && dcc_stb && (ctype || ctype_prev[0] || sel_satnum)) || hfc_copy;
end
SRL16 i_hfc_en (.Q(hfc_en), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0), .CLK(clk),
.D(((tba[2:0]>hfc_sel[2:0]) || (tba[5:3]>hfc_sel[2:0])) && dcc_run && !ctype_prev[0])); // dly=1+1
zigzag i_zigzag( .clk(clk),
.start(start_z),
.q(zwa[5:0]));
always @ (negedge sclk) twqe_d <= twqe;
always @ (negedge sclk) twce_d <= twce;
RAMB16_S18_S18 i_quant_table (
.DOA(tdo[15:0]), // Port A 16-bit Data Output
.DOPA(), // Port A 2-bit Parity Output
.ADDRA({tba[9:6],tba[2:0],tba[5:3]}), // Port A 10-bit Address Input
.CLKA(clk), // Port A Clock
.DIA(16'b0), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.DOB(), // Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.ADDRB({ta[8:0],twqe_d}), // Port B 10-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB(tdi[15:0]), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(1'b1), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(twqe || twqe_d) // Port B Write Enable Input
);
RAMB16_S4_S18 i_coring_table (
.DOA(tdco[3:0]), // Port A 4-bit Data Output
.ADDRA({tbac[3:0],qmulr[11:4]}), // Port A 12-bit Address Input
.CLKA(clk), // Port A Clock
.DIA(4'b0), // Port A 4-bit Data Input
.ENA(1'b1), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.DOB(), // Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.ADDRB({ta[8:0],twce_d}), // Port B 10-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB(tdi[15:0]), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(1'b1), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(twce || twce_d) // Port B Write Enable Input
);
RAMB16_S18_S18 i_zigzagbuf (
.DOA(), // Port A 16-bit Data Output
.DOPA(), // Port A 2-bit Parity Output
.ADDRA({3'b0,wpage,zwa[5:0]}), // Port A 10-bit Address Input
.CLKA(clk), // Port A Clock
.DIA({3'b0,qdo[12:0]}), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(zwe), // Port A Write Enable Input
.DOB(zigzag_q[15:0]), // Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.ADDRB({3'b0,rpage,zra[5:0]}), // Port B 10-bit Address Input
.CLKB(clk), // Port B Clock
.DIB(16'b0), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(next_dv), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
endmodule
// Alternative ZigZag distributed ROM. More convinient, but extra resources. Use upper half of quantization table to save slices.
module zigzag (clk,
start,
q);
input clk, start;
output [5:0] q;
reg [5:0] a;
reg [5:0] q;
wire [4:0] rom_a;
wire [5:0] rom_q;
assign rom_a[4:0]=a[5]?(~a[4:0]):a[4:0];
always @ (posedge clk) begin
if (start) a[5:0] <= 6'b0;
// else a[5:0] <= a[5:0]+1; // may add if (a[5:0]!=6'h3f) to make cleaner simulation and conserve energy
else if (a[5:0]!=6'h3f) a[5:0] <= a[5:0]+1;
q[5:0] <= a[5]? (~rom_q[5:0]):rom_q[5:0];
end
ROM32X1 i_z0 ( .A0(rom_a[0]), .A1(rom_a[1]), .A2(rom_a[2]), .A3(rom_a[3]), .A4(rom_a[4]), .O(rom_q[0]));
ROM32X1 i_z1 ( .A0(rom_a[0]), .A1(rom_a[1]), .A2(rom_a[2]), .A3(rom_a[3]), .A4(rom_a[4]), .O(rom_q[1]));
ROM32X1 i_z2 ( .A0(rom_a[0]), .A1(rom_a[1]), .A2(rom_a[2]), .A3(rom_a[3]), .A4(rom_a[4]), .O(rom_q[2]));
ROM32X1 i_z3 ( .A0(rom_a[0]), .A1(rom_a[1]), .A2(rom_a[2]), .A3(rom_a[3]), .A4(rom_a[4]), .O(rom_q[3]));
ROM32X1 i_z4 ( .A0(rom_a[0]), .A1(rom_a[1]), .A2(rom_a[2]), .A3(rom_a[3]), .A4(rom_a[4]), .O(rom_q[4]));
ROM32X1 i_z5 ( .A0(rom_a[0]), .A1(rom_a[1]), .A2(rom_a[2]), .A3(rom_a[3]), .A4(rom_a[4]), .O(rom_q[5]));
//C67319CC 611A7896 6357A260 4A040C18 8C983060 F0E0C080
// transposed! (old was 93D94C66 16A1A578 D0244EBC 7BF6E8F0 9C3870C0 E0C08000
//synthesis translate_off
/* defparam i_z0.INIT = 32'h93D94C66;
defparam i_z1.INIT = 32'h16A1A578;
defparam i_z2.INIT = 32'hD0244EBC;
defparam i_z3.INIT = 32'h7BF6E8F0;
defparam i_z4.INIT = 32'h9C3870C0;
defparam i_z5.INIT = 32'hE0C08000;
*/
defparam i_z0.INIT = 32'hC67319CC;
defparam i_z1.INIT = 32'h611A7896;
defparam i_z2.INIT = 32'h6357A260;
defparam i_z3.INIT = 32'h4A040C18;
defparam i_z4.INIT = 32'h8C983060;
defparam i_z5.INIT = 32'hF0E0C080;
//synthesis translate_on
//synthesis attribute INIT of i_z0 is "C67319CC"
//synthesis attribute INIT of i_z1 is "611A7896"
//synthesis attribute INIT of i_z2 is "6357A260"
//synthesis attribute INIT of i_z3 is "4A040C18"
//synthesis attribute INIT of i_z4 is "8C983060"
//synthesis attribute INIT of i_z5 is "F0E0C080"
endmodule
/*
** -----------------------------------------------------------------------------**
** rtc353.v
**
** Real time clock, counts seconds (32 bit), microseconds (20 bits)
** allows fine adjustment (0.1 ppm to =/- 0.3%), used in timestamping images.
**
** Copyright (C) 2005-2007 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 rtc353 (mclk, // system clock (negedge)
pre_we, // 1 cycle ahead of writing data
wa, // [1:0] write address
// 0 - write microseconds (actual write will happen after writing seconds)
// 1 - write seconds
// 2 - write correction (16 bit, signed
// 3 - nop, just latch the output 32+20 bits to read to CPU). Maybe nop (or 2 writes) are needed between read.
wd, // [31:0] data to write, valid 1 cycle after pre_we, wa
musec, // [19:0] usec output (register is latched by writing), 0..999999 (0..0xf423f)
msec, // [31:0] seconds latched counter output
clk12, // 12MHz clock (no PLL, just xtall). will be re-synchronized to mclk to avoid extra GCLK
pclk, // sensor clock (posedge)
platch, // latch counters sync to pclk (up to ~0.5usec delay. Start of first HACT after VACT?
pusec, // [19:0] usec output - sync to sensor clock
psec, // [31:0] seconds counter output
usec, // running usec data out
sec); // running sec data out
// counter is updated each 0.5 (non-compensated) microsecond. Usually counters are incremented each other upd pulse, but an interval
// may be 1 or 3 upd periods (0.5/1.5 usec)
input mclk;
input pre_we;
input [ 1:0] wa;
input [15:0] wd;
output [19:0] musec;
output [31:0] msec;
input clk12;
input pclk;
input platch;
output [19:0] pusec;
output [31:0] psec;
output [19:0] usec;
output [31:0] sec;
reg we_usec;
// reg [ 1:0] we_sec;
reg we_sec;
reg set_cntr;
reg we_corr;
reg [19:0] wusec;
reg [31:0] wsec;
reg [15:0] corr;
reg [19:0] usec;
reg [31:0] sec;
reg [19:0] usec_plus1;
reg [31:0] sec_plus1;
reg [19:0] musec;
reg [31:0] msec;
reg [19:0] pusec;
reg [31:0] psec;
reg [ 2:0] clk12_d; // make a clean 12MHz clock sync to system clock
reg [ 2:0] clk12_s; // make a clean 12MHz clock sync to system clock
reg [ 2:0] cntr6; // divide by 6 (12MHz->2MHz)
reg pend_set_cntr; //ending set_cntr (will be synchronized)
reg [3:0] halfusec;
reg [1:0] inc_usec; // 2 bits - to reduce FO problems
reg [1:0] inc_sec;
reg [23:0] acc;
wire [24:0] next_acc;
reg [2:0] usec_lsb; // usec LSB sampled @posedge pclk, delayed
reg platch_sample; // sample TS until usec LSB does not change (before and after
reg platch_test; // see if need to re_sample;
wire enable_rtc; // for simulation
reg [15:0] wd_r; // delayed data in (low bits)
wire [31:0] wdd={wd[15:0],wd_r[15:0]};
assign next_acc[24:0]= {1'b0,acc[23:0]} + {1'b0,~corr [15], {7{corr [15]}}, corr[15:0]};
always @ (posedge pclk) begin
usec_lsb[2:0] <= {usec_lsb[1:0],usec[0]};
platch_sample <= platch || (platch_test && ((usec_lsb[1]!=usec_lsb[0]) ||(usec_lsb[2]!=usec_lsb[0])));
platch_test<=platch_sample;
if (platch_sample) begin
pusec[19:0] <= usec[19:0];
psec [31:0] <= sec [31:0];
end
end
// FDE_1 i_enable_rtc (.C(mclk),.CE(we_sec[0]),.D(1'b1),.Q(enable_rtc));
FDE_1 i_enable_rtc (.C(mclk),.CE(we_sec),.D(1'b1),.Q(enable_rtc));
always @ (negedge mclk) begin
wd_r[15:0] <= wd[15:0];
clk12_d[2:0] <= {clk12_d[1:0], clk12};
clk12_s[2:0] <= {clk12_s[1] && !clk12_s[0], clk12_s[0], (clk12_d[2:1]==2'h3) || (clk12_s[0] && !(clk12_d[2:1]==2'h0))};
we_usec <= (wa[1:0]==2'h0) && pre_we;
// we_sec[1:0] <= {we_sec[0],(wa[1:0]==2'h1) && pre_we};
we_sec <= (wa[1:0]==2'h1) && pre_we;
// if (we_sec[0]) pend_set_cntr <= 1'b1;
if (we_sec) pend_set_cntr <= 1'b1;
else if (halfusec[3])pend_set_cntr <= 1'b0;
if (!enable_rtc) set_cntr <= 1'b0;
else if (halfusec[3]) set_cntr <= pend_set_cntr;
we_corr <= (wa[1:0]==2'h2) && pre_we;
if (pre_we) begin
musec[19:0] <= usec[19:0];
msec [31:0] <= sec [31:0];
end
if (we_usec) wusec[19:0] <= wdd[19:0];
// if (we_sec[0]) wsec [31:0] <= wdd[31:0];
if (we_sec) wsec [31:0] <= wdd[31:0];
if (we_corr) corr [15:0] <= wdd[15:0];
if (!enable_rtc) cntr6[2:0] <= 3'h5;
else if (clk12_s[2]) cntr6[2:0] <= (cntr6[2:0]==3'h0)?3'h5:(cntr6[2:0] - 1);
halfusec[3:0] <= {halfusec[2:0],clk12_s[2] && (cntr6[2:0]==3'h0)};
if (halfusec[1]) acc[23:0] <= set_cntr?24'h0:next_acc[23:0];
inc_usec[1:0] <= {inc_usec[0],halfusec[1] & next_acc[24]};
inc_sec [1:0] <= {inc_sec[0], halfusec[1] && next_acc[24] && (usec[19:0]==20'hf423f)};
// reducing delay from set_cntr to sec[]. usec[] - don't know how to constraint it really, so adding layer of registers
sec_plus1[31:0] <= sec[31:0] + 1;
usec_plus1[19:0] <= usec[19:0] + 1;
if (set_cntr) usec[19:0] <= wusec[19:0];
else if (inc_sec[1]) usec[19:0] <= 20'h0;
else if (inc_usec[1]) usec[19:0] <= usec_plus1[19:0];
if (set_cntr) sec[31:0] <= wsec[31:0];
else if (inc_sec[1]) sec[31:0] <= sec_plus1[31:0];
end
endmodule
module timestamp353( mclk, // system clock (negedge)
pre_we, // 1 cycle ahead of writing data
wd, // [1:0] data to write, valid 1 cycle after pre_we, wa
pclk, // pixel clock
pxdi, // [15:0] pixel data from sensor
pxdo, // [15:0] data to replace pxdi (next cycle)
vacts, // vertical sync
hacti, // hact input
hacto, // hact output (next cycle)
sec, // [31:0] number of seconds
usec, // [19:0] number of microseconds
tlatch); // latch time - 1-st hact after vact
input mclk;
input pre_we;
input [1:0] wd;
input pclk;
input [15:0] pxdi;
output [15:0] pxdo;
input vacts;
input hacti;
output hacto;
input [31:0] sec;
input [19:0] usec;
output tlatch;
wire ts_active;
reg [15:0] pxdo;
reg hacto;
wire ts_bit;
reg hact_d;
reg vact_pend;
reg odd_line;
// reg [ 3:0] line;
reg [ 2:0] line;
reg ts_line; // line when timestamp is active
reg tlatch;
wire start_ts;
reg pre_start_ts, start_ts_r; // only in normal mode
reg ts_continue;
reg [ 4:0] ts_count;
reg [25:0] ts_data;
reg wr_tsmode;
wire [1:0] tsmode; //[1:0] 0 - off, (pixels/lines below start from 0)
// 1 - 2rd and 3-th lines, from pixel 2 (normal mode, frame not increased)
// 2 - 0 and 1 lines, after pixel data (adds 28 pixels to each line:
// {seconds[31:6],2'b0} MSB first for line 0
// {seconds[5:0],useconds[19:0],2'b0} MSB first for line 1
//delaying ts_data, pxdo by 1 clock
reg [15:0] pxdi_r; // delayed pxdi
reg use_ts; // use timestamp data
reg ts_active_r;
reg ts_line_r;
reg [1:0] wdd;
assign ts_bit=ts_data[25];
assign start_ts = (tsmode[1] && !hacti && hact_d) || start_ts_r;
assign ts_active = ts_continue || start_ts;
FDE_1 i_tsmode_0 (.C(mclk),.CE(wr_tsmode),.D(wdd[0]),.Q(tsmode[0]));
FDE_1 i_tsmode_1 (.C(mclk),.CE(wr_tsmode),.D(wdd[1]),.Q(tsmode[1]));
always @ (negedge mclk) begin
wdd[1:0] <= wd[1:0];
wr_tsmode <= pre_we;
end
always @ (posedge pclk) begin
use_ts <= ts_active || (hact_d && !hacti);
pxdi_r[15:0] <= pxdi[15:0];
if (use_ts) pxdo[15:0] <= {16{ts_bit}};
else if (hact_d) pxdo[15:0] <= pxdi_r[15:0];
hact_d <= hacti;
hacto <= hacti || ts_active;
if (vacts) vact_pend <= 1'b1;
else if (hacti && !hact_d) vact_pend <= 1'b0;
if (hacti && !hact_d) odd_line <= !vact_pend && !odd_line;
// if (hacti && !hact_d) line[3:0] <= vact_pend?4'h1:{line[2:0],1'b0};
if (hacti && !hact_d) line[2:0] <= vact_pend?4'h1:{line[1:0],1'b0};
if (hacti && !hact_d) ts_line <= tsmode[1]? (vact_pend || line[0] ) : (!vact_pend && (line[1] || line[2]));
tlatch <= vact_pend && hacti && !hact_d;
pre_start_ts <= (tsmode[1:0] == 2'h1) &&
hacti && !hact_d && !vact_pend && (line[1] || line[2]);// before line changes
start_ts_r <= pre_start_ts;
if (start_ts) ts_count[4:0] <= tsmode[1]?5'h1a:5'h18;
else if (ts_continue) ts_count[4:0] <= ts_count[4:0] - 1;
if (tsmode[1:0]==2'h0) ts_continue <= 1'b0;
else if (start_ts) ts_continue <= 1'b1;
else if (ts_count[4:0]==5'h0) ts_continue <= 1'b0;
// if (ts_active) ts_data[25:0]<= {ts_data[24:0],1'b0};
// else if (ts_line) ts_data[25:0]<= odd_line?sec[31:6]:{sec[5:0],usec[19:0]};
// else ts_data[25:0]<= 16'h0;
ts_active_r <= ts_active;
ts_line_r <= ts_line;
if (ts_active_r) ts_data[25:0]<= {ts_data[24:0],1'b0};
else if (ts_line_r) ts_data[25:0]<= odd_line?sec[31:6]:{sec[5:0],usec[19:0]};
else ts_data[25:0]<= 16'h0;
end
endmodule
/*
** -----------------------------------------------------------------------------**
** sdram_phase.v
**
** I/O pads related circuitry
**
** Copyright (C) 2002 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// assumed CL=2.5
module sdram_phase (// wclk, // global CPU WE pulse
pre_wcmd, // decoded address - enables wclk
wd, // CPU write data [1:0]
// 0 - nop, just reset status data
// 1 - increase phase shift
// 2 - decrease phase shift
// 3 - reset phase shift to default (preprogrammed in FPGA configuration)
// c - reset phase90
// 4 - incr pahse90
// 8 - decrease phase90
ph_err, // [1:0] 0 - no data (SDRAM reads) since last change (wclk*wcmd)
// 1 - clock is too late
// 2 - clock is too early
// 3 - OK (some measurements show too late, some - too early)
sclk0, // global clock, phase 0
/* sclk90, // global clock, phase 0 */
sclk270, // global clock, phase 0
enrd180, // read enable, latency 2 from the command, sync with sclk falling edge
udqsr90, // data from SDRAM interface pin UDQS strobed at rising sclk90
ldqsr90, // data from SDRAM interface pin LDQS strobed at rising sclk90
udqsr270, // data from SDRAM interface pin UDQS strobed at rising sclk270
ldqsr270, // data from SDRAM interface pin UDQS strobed at rising sclk270
dcm_rst, // set DCM phase to default
dcm_clk, // clock for changing DCM phase (now == sclk0)
dcm_en, // enable inc/dec of the DCM phase
dcm_incdec, // 0 - increment, 1 - decrement DCM phase
phase90sel // add phase 0 - 0, 1 - 90, 2 - 180, 3 - 270
);
input pre_wcmd;
input [ 3:0] wd;
output [ 1:0] ph_err;
input sclk0, /*sclk90, */sclk270;
input enrd180;
input udqsr90, udqsr270, ldqsr90, ldqsr270;
output dcm_rst, dcm_clk, dcm_en, dcm_incdec;
output [ 1:0] phase90sel;
// reg wcmd;
wire wcmd = pre_wcmd;
reg [ 1:0] phase90sel;
reg dcm_rst;
reg [1:0] dcm_drst;
reg dcm_en;
reg dcm_incdec;
reg enrd0, enrd180_d,enrd90,enrd270;
reg waslate90, waslate270, wasearly90, wasearly270;
// generate control pulses from CPU command
always @ (negedge sclk0) begin
// wcmd <=pre_wcmd;
dcm_drst[1:0] <= {dcm_drst[0], (wcmd && (wd[1:0] == 2'b11))};
dcm_rst <= (wcmd && (wd[1:0] == 2'b11)) || dcm_drst[0] || dcm_drst[1] ;
dcm_en <= wcmd && (wd[1]!=wd[0]);
dcm_incdec <= wcmd && wd[0];
if (wcmd && wd[2] && wd[3]) phase90sel[1:0] <= 2'h0;
else if (wcmd && wd[2]) phase90sel[1:0] <= phase90sel[1:0] +1;
else if (wcmd && wd[3]) phase90sel[1:0] <= phase90sel[1:0] -1;
end
// DCM control outputs (use automatic adjustment later?)
// assign dcm_clk=sclk0;
assign dcm_clk=!sclk0; // DCM is triggered by posedge
// generate phase error signals
always @ (posedge sclk0) enrd0 <= enrd180;
always @ (negedge sclk0) enrd180_d <= enrd180;
// always @ (posedge sclk90) enrd90 <= enrd180_d;
always @ (negedge sclk270) enrd90 <= enrd180_d;
always @ (posedge sclk270) enrd270 <= enrd0;
// always @ (posedge sclk90 or posedge wcmd)
always @ (negedge sclk270 or posedge wcmd)
if (wcmd) begin
waslate90 <= 1'b0;
wasearly90 <= 1'b0;
end else begin
waslate90 <= waslate90 || (enrd90 && ( udqsr90 || ldqsr90));
wasearly90 <= wasearly90 || (enrd90 && (!udqsr90 || !ldqsr90));
end
always @ (posedge sclk270 or posedge wcmd)
if (wcmd) begin
waslate270 <= 1'b0;
wasearly270 <= 1'b0;
end else begin
waslate270 <= waslate270 || (enrd270 && (!udqsr270 || !ldqsr270));
wasearly270 <= wasearly270 || (enrd270 && ( udqsr270 || ldqsr270));
end
assign ph_err[1:0]= {(wasearly90 || wasearly270), (waslate90 || waslate270)};
endmodule
/*
** -----------------------------------------------------------------------------**
** sdseq333.v
**
** formely part of mcontr333.v
**
** Copyright (C) 2002-2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// 05/06/2008 - modified to delay precharge after write (tWR) - there was violation with
// clock period less than 7.5ns
// external commands sync to clk180
module sdseq (clk0, // global clock 75-100MHz (hope to get to 120MHz with Spartan3)
rst, // when active will use mancmd as a source for ras,cas,we,ba,a
xfer, // start block transfer (=stepsEn[2]) - when address is ready
mode, // 0 - 128x1, 1 - 18x9 (will work only in read mode, channnel 2)
wnr,
refr, // start auto refresh (should be delayed same time as read/write)
sa, // block start address
chsel, // channel number (0..3) - used to generate delayed dsel;
param, // dual-purpose parameter. In 256x1 mode specifies (5 LSBs) number of 8-word long groups to r/w (0- all 32),
// actually for all but 0 (when exactly 256 words are xfered) will transfer one word more
// In 18x9 mode specifies bits 13:8 of address increment between lines
mancmd,// always high except 1 cycle long when it sources {ras,cas,we,ba[1:0],a[11:0]}. Works only whe rst is active
// Will use 18 bits from unused descriptor cell , a[11] will be skipped and set to 1'b0????
sfa, // [23:8]), start address of a frame - ugly hack to roll over the last (extra) 4 lines of a frame
// to the beginning of a frame - used in photofinish mode.
rovr, // roll over mode (photofinish, cntrl0[12]==1, last line of tiles)
drun_rd, // enable read data (from SDRAM) to blockRAM buffer
drun_wr, // enable write data (to SDRAM) from blockRAM buffer
prefirstdrun, // 1 cycle ahead of the first drun_rd/drun_wr to be used by bufCntr256 to sample channel enable
dlast, //last cycle of drun active for read, 1 cycle later for write **** for the last cycle in multi-drun accesses !
precmd, // 1 cycle ahead {ras,cas,we} command bits to be registered at the output pads
prea, // 13 bits (including ba) 1 cycle ahead of output A[12:0]
preb, // 2 bits of bank address 1 cycle ahead of output BA[1:0]
next, // get next request from que.
pre2trist, // tristate data outputs (two ahead).
predqt, // tristate DQ outputs (one extra for FF in output buffer)
dmask, // [1:0] - now both the same (even number of words written)
dqs_re, // enable read from DQS i/o-s for phase adjustments (latency 2 from the SDRAM RD command)
dsel); // data buffer select (number of buffer to source SDRAM data in), so it is needed only for WRITE to SDRAM
input clk0;
input rst,xfer,mode,wnr,refr;
input [24:3] sa;
input [ 1:0] chsel;
input [ 5:0] param;
input [17:0] mancmd;
input [24:8] sfa; // start frame address - photofinish hack
input rovr; // roll over mode (photofinish, cntrl0[12]==1, last line of tiles)
output drun_rd;
output drun_wr;
output prefirstdrun;
output dlast;
output [ 2:0] precmd;
output [12:0] prea;
output [ 1:0] preb;
output next;
output pre2trist;
output predqt;
output [ 1:0] dmask;
output dqs_re;
output [ 1:0] dsel;
reg [4:0] left; // full page will be 31, not 32 copunts - first delay will just be longer
reg mode_r;//, wnr_r; //after xfer
reg prefirst,first;
reg [1:0] dsel;
reg [12:0] prea;
reg [ 1:0] preb;
wire [2:0] precmd;
reg [1:0] dmask; // for now both bits are the same
reg next;
reg pre2trist;// made 1 extra early - add FF to the i/op module
reg predqt; // will go through additional FF at falling clk0 in I/O module
reg drun_rd;
reg drun_wr; //3 cycles ahead of data out available inside FPGA (before DDR resyncing)
reg dlast;
reg dqs_re;
// internals
reg [24:3] fullAddr; // full SDRAM address;
reg [24:3] nextAddr; // full SDRAM address for the next 10-word block (in next line)
// reg [24:9] nextPageAddr; // used only for the the second access in mode1
reg [24:10] nextPageAddr; // used only for the the second access in mode1
reg start_m1; // start in mode1 - both first and next lines
reg startf_m1; // start in mode1 - only first line !
reg start_m0r; // start in mode0 - read
reg start_m0w; // start in mode0 - write
// wire pre6prech_m; // 6 cycles ahead of precmd "precharge" mode1, single access or second in dual
reg pre6prech_m; // 6 cycles ahead of precmd "precharge" mode1, single access or second in dual
reg [1:0] pre7prech_m; // 7 cycles ahead of precmd "precharge", [0] - read, [1] - write
wire pre2prech_m; // 2 cycles ahead of precmd "precharge" mode1, single access or second in dual
wire pre2prech_m1d1; // 2 cycles ahead of precmd "precharge" mode1, dual access, first cycle
wire pre2act_m1d2; // 2 cycles ahead of precmd "activate" mode1, dual access, second cycle
wire prenext_m1s; // 1 cycle ahead of possible "next" - mode1, single access - starts from start_m1
wire prenext_m1d; // 1 cycle ahead of possible "next" - mode1, dual access
wire precontinue_m1; // 3 cycles ahead of "activate" of continuation cycle
reg continue_m1; // 2 cycles ahead of "activate" of continuation cycle
wire continue_m0; // 2 cycles ahead of "activate" of continuation cycle
reg possible_dual; // lower bits in full address are all ones - possible two acccesses will be needed in the current line
reg setNextAddr; // update nextAddr
reg decLeft;
wire prenext_m0r;
wire prenext_m0w1;
wire prenext_m0;
wire pre2refr;
wire prenext_refr;
reg prerefr;
reg preact;
reg preprech;
reg preread;
reg prewrite;
reg prerw; // for address multiplexor
reg pre1act_m1d2;
wire pre2read;
wire pre2write;
reg predrun_wr;
reg pre4drun_rd;
wire predrun_rd;
wire pre4drun_rd_abort; // in second access of dual-access, where precharge command is later (to meet activate-to-precharge time)
wire predrun_wr_abort; // write nneeds extra NOP befrore precharge
wire predmask;
reg repeat_r;
wire repeat_r_end;
reg repeat_w;
wire pre2read_next8;
wire pre2write_next8;
reg prefirstdrun; // to sample cs in bufCntr256
wire pre2firstdrun_rd;
reg rollover; //photofinish hack
reg prenext_wr; // same timing as it was "next" earlier
wire pre_next_old=(left==5'h1) && (prenext_m1s || prenext_m1d || prenext_m0);
always @ (negedge clk0)
if (rst) begin
mode_r <= 1'b0;
end else if (xfer) begin
mode_r <= mode;
end
always @ (negedge clk0) begin
rollover <= (left[4:0]==5'h4) && rovr;
if (first) fullAddr[ 9:3] <= sa[ 9:3];
else if (pre2act_m1d2) fullAddr[ 9:3] <= 8'h0;
else if (prerw) fullAddr[ 9:3] <= fullAddr[ 9:3]+1;
else if (continue_m1) fullAddr[ 9:3] <= {rollover?sfa[9:8]:nextAddr[9:8],nextAddr[ 7:3]}; // stored from sa[7:3]
if (first) fullAddr[24:10] <= sa[24:10];
else if (continue_m1) fullAddr[24:10] <= rollover?sfa[24:10]:nextAddr[24:10];
else if (pre2act_m1d2) fullAddr[24:10] <= nextPageAddr[24:10];
if (pre2prech_m1d1) nextPageAddr[24:10] <= fullAddr[24:10]+1;
if (rst) possible_dual <= 0;
else if (first) possible_dual <= (sa[ 7:3] == 5'h1f);
start_m1 <= !rst && ((first && mode_r) || continue_m1);
startf_m1 <= !rst && (first && mode_r);
start_m0r <= first && !mode_r && !wnr;
start_m0w <= first && !mode_r && wnr;
setNextAddr <= start_m1;
if (setNextAddr) nextAddr[24:8] <= fullAddr[24:8]+param[5:0]; // 2 cycles after fullAddr was set
if (first) nextAddr[ 7:3] <= sa [7:3];
prenext_wr <= drun_wr && pre_next_old;
next <= prenext_refr || prenext_wr || (!drun_wr && pre_next_old); // add m0 and refr here too
decLeft <= (prenext_m1s || prenext_m1d || prenext_m0); // add m0 and refr here too
if (first) left[4:0] <= (mode)? 5'h14:((param[4:0]==5'b0)?5'h1f:param[4:0]);
else if (decLeft) left[4:0] <= left[4:0] -1;
end
// aHa! Here was the bug!!
// MSRL16_1 i_prenext_m1s (.Q(prenext_m1s), .A(4'h0), .CLK(clk0), .D(start_m1 && ~(possible_dual && fullAddr[8])));
MSRL16_1 i_prenext_m1s (.Q(prenext_m1s), .A(4'h0), .CLK(clk0), .D(start_m1 && ~(possible_dual && &fullAddr[9:8])));
// modified to match tWR (delay precharge after write)
// MSRL16_1 i_pre6prech_m (.Q(pre6prech_m), .A(4'h1), .CLK(clk0), .D(prenext_m1s ||
// prenext_m1d ||
// ((left==5'h1) && prenext_m0)));
MSRL16_1 i_pre2prech_m (.Q(pre2prech_m), .A(4'h3), .CLK(clk0), .D(pre6prech_m));
// MSRL16_1 i_pre2prech_m1d1 (.Q(pre2prech_m1d1), .A(4'h5), .CLK(clk0), .D(start_m1 && (possible_dual && fullAddr[8])));
MSRL16_1 i_pre2prech_m1d1 (.Q(pre2prech_m1d1), .A(4'h5), .CLK(clk0), .D(start_m1 && (possible_dual && &fullAddr[9:8])));
MSRL16_1 i_prenext_m1d (.Q(prenext_m1d), .A(4'h1), .CLK(clk0), .D(pre2prech_m1d1));
MSRL16_1 i_pre2act_m1d2 (.Q(pre2act_m1d2), .A(4'h0), .CLK(clk0), .D(prenext_m1d));
MSRL16_1 i_precontinue_m1 (.Q(precontinue_m1), .A(4'h1), .CLK(clk0), .D((left!=5'h0) && pre2prech_m));
MSRL16_1 i_prenext_m0r (.Q(prenext_m0r), .A((param[4:0]==5'b0)?4'h3:4'h0), .CLK(clk0), .D(start_m0r));
MSRL16_1 i_prenext_m0w1 (.Q(prenext_m0w1), .A((param[4:0]==5'b0)?4'h6:4'h3), .CLK(clk0), .D(start_m0w));
assign prenext_m0=prenext_m0r || prenext_m0w1 || continue_m0;
MSRL16_1 i_continue_m0 (.Q(continue_m0), .A(4'h3), .CLK(clk0), .D(!rst && (left!=5'h1) && prenext_m0));
MSRL16_1 i_pre2refr (.Q(pre2refr), .A(4'h6), .CLK(clk0), .D(refr));
MSRL16_1 i_prenext_refr (.Q(prenext_refr), .A(4'h2), .CLK(clk0), .D(pre2refr));
// secondary signals (just delays from the primary ones)
MSRL16_1 i_pre2read (.Q(pre2read), .A(4'h1), .CLK(clk0), .D(start_m0r || start_m1 || pre1act_m1d2));
MSRL16_1 i_pre2write (.Q(pre2write), .A(4'h1), .CLK(clk0), .D(start_m0w));
MSRL16_1 i_predrun_rd (.Q(predrun_rd), .A(4'h2), .CLK(clk0), .D(pre4drun_rd));
MSRL16_1 i_pre4drun_rd_abort (.Q(pre4drun_rd_abort), .A(4'h4), .CLK(clk0), .D(pre2act_m1d2));
MSRL16_1 i_predrun_wr_abort (.Q(predrun_wr_abort), .A(4'h0), .CLK(clk0), .D((prenext_m0w1 || continue_m0) && (left==5'h1)));
MSRL16_1 i_predlast_rd (.Q(predlast_rd), .A(4'h2), .CLK(clk0), .D(pre4drun_rd && (preprech || pre4drun_rd_abort)));
MSRL16_1 i_predlast_wr (.Q(predlast_wr), .A(4'h0), .CLK(clk0), .D(predrun_wr && predrun_wr_abort));
MSRL16_1 i_predmask (.Q(predmask), .A(4'h2), .CLK(clk0), .D(!predrun_wr));
MSRL16_1 i_predqs_re (.Q(predqs_re), .A(4'h1), .CLK(clk0), .D(pre4drun_rd));
MSRL16_1 i_pre2read_next8 (.Q(pre2read_next8), .A(4'h2), .CLK(clk0), .D(preread));
MSRL16_1 i_pre2write_next8 (.Q(pre2write_next8), .A(4'h2), .CLK(clk0), .D(prewrite));
assign repeat_r_end= pre2prech_m || pre2prech_m1d1; // will work for read - add for write
MSRL16_1 i_pre2firstdrun_rd (.Q(pre2firstdrun_rd), .A(4'h5), .CLK(clk0), .D(start_m0r || startf_m1));
always @ (negedge clk0) begin
pre7prech_m[1:0] <= {pre7prech_m[0],prenext_m1s ||
prenext_m1d ||
(prenext_m0 && (left==5'h1))};
pre6prech_m <= drun_wr?pre7prech_m[1]:pre7prech_m[0];
prefirstdrun <= start_m0w || pre2firstdrun_rd;
continue_m1 <= precontinue_m1;
repeat_r <= !rst && !repeat_r_end && (repeat_r || first || continue_m1);
repeat_w <= !rst && !pre6prech_m && (repeat_w || first);
prefirst <= xfer;
first <= prefirst;
pre1act_m1d2 <= !rst && pre2act_m1d2;
prerefr <= !rst && pre2refr;
preact <= !rst && (first || continue_m1 || pre2act_m1d2);
preprech <= !rst && (pre2prech_m || pre2prech_m1d1);
preread <= !rst && ~(pre2prech_m || pre2prech_m1d1) && (pre2read || (pre2read_next8 && repeat_r));
prewrite <= !rst && (pre2write || (pre2write_next8 && repeat_w));
prerw <= (~(pre2prech_m || pre2prech_m1d1) && (pre2read || (pre2read_next8 && repeat_r))) ||
(pre2write || (pre2write_next8 && repeat_w));
// prea[12:0] <= rst? mancmd[12:0] : (prerw? {4'b0,fullAddr[8:3],3'b0} :(first?sa[21:9] :fullAddr[21:9]));
// preb[ 1:0] <= rst? mancmd[14:13] : (first?sa[23:22]:fullAddr[23:22]);
prea[12:0] <= rst?
mancmd[12:0] :
(prerw?
{3'b0,fullAddr[9:3],3'b0} :
(first?
sa[22:10] :
fullAddr[22:10]));
preb[ 1:0] <= rst?
mancmd[14:13] :
(first?
sa[24:23]:
fullAddr[24:23]);
if (start_m0w) dsel[1:0] <= chsel[1:0];
predrun_wr <= start_m0w || (!rst && predrun_wr && ~predrun_wr_abort);
pre4drun_rd <= preread || (!rst && pre4drun_rd && ~(preprech || pre4drun_rd_abort));
drun_rd <= predrun_rd;
drun_wr <= predrun_wr;
dlast <= (left==5'h0 ) && (predlast_rd || predlast_wr) && !pre1act_m1d2; // !pre1act_m1d2 removes first pulse in dual access lines
dmask <={predmask,predmask};
pre2trist<=rst || preprech || (pre2trist && ~prewrite);
predqt <=rst || (pre2trist && ~prewrite);
dqs_re <=predqs_re;
end
// Use FF for cas, ras, we for correct simulation
FD_1 i_precmd_0 (.D(mancmd[15] && ~(prewrite | preprech)), .C(clk0),.Q(precmd[0])); //WE
FD_1 i_precmd_1 (.D(mancmd[16] && ~(prerefr | preread | prewrite)),.C(clk0),.Q(precmd[1])); //CAS
FD_1 i_precmd_2 (.D(mancmd[17] && ~(prerefr | preact | preprech)), .C(clk0),.Q(precmd[2])); //RAS
//synthesis translate_off
defparam i_precmd_0.INIT = 1'b1;
defparam i_precmd_1.INIT = 1'b1;
defparam i_precmd_2.INIT = 1'b1;
//synthesis translate_on
//synthesis attribute INIT of i_precmd_0 is "1"
//synthesis attribute INIT of i_precmd_1 is "1"
//synthesis attribute INIT of i_precmd_2 is "1"
endmodule
/*
** -----------------------------------------------------------------------------**
** sensdcclk.v
**
** Frame-synchronous DC-DC converter clock
**
** Copyright (C) 2002 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X313
** X313 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 sensdcclk( clk, // sensor clock (may be variable)
frame, // frame sync (1 cycle, sync to sensclk)
d, // [6:0] divider. Nominal 5'h05 for 20MHz pixel rate
// data=(Fpix[MHz]/1.2)-1, if Fpix=20MHz, data=15.7->16=5'h10
sclk, //
pre_we, // write enable to sensdcclk (sync to cwr)
cnvclk, // 625KHz clock to drive DC-DC converter
cnvext); // 0 - DCDC use internal clock, 1 - external
input clk;
input frame;
input [6:0] d;
input sclk;
input pre_we;
output cnvclk;
output cnvext;
wire [6:0] dvs;
reg [4:0] cntr;
reg cnvext;
wire cntr_en= |dvs[4:0]; // clock off if set to 0;
reg cnvclk;
reg fullper; // full cnvclk period since last frame sync
wire sync=fullper && frame;
reg [3:0] div1;
reg [3:0] div2;
reg [3:0] div3;
wire cry1=(div1[3:0]==4'hf);
wire cry2=(div2[3:0]==4'hf);
wire cry3=(div3[3:0]==4'hf);
// wire cry=cry1&& cry2 && cry3;
wire dec=(dvs[6:5]==2'b0) || (cry1 && (!dvs[6] || (cry2 && (!dvs[5] || cry3) )));
wire half= (cntr[4:0]== 5'b0) && dec;
// reg we;
wire we= pre_we;
// always @(negedge sclk) we <= pre_we;
always @ (posedge clk) begin
if (!cntr_en) div1 <= 4'b0;
else div1 <= div1+1;
if (!cntr_en) div2 <= 4'b0;
else if (cry1) div2 <= div2+1;
if (!cntr_en) div3 <= 4'b0;
else if (cry1 && cry2) div3 <= div3+1;
end
FDE_1 i_dvs_0 (.C(sclk), .CE(we), .D(d[0]), .Q(dvs[0]));
FDE_1 i_dvs_1 (.C(sclk), .CE(we), .D(d[1]), .Q(dvs[1]));
FDE_1 i_dvs_2 (.C(sclk), .CE(we), .D(d[2]), .Q(dvs[2]));
FDE_1 i_dvs_3 (.C(sclk), .CE(we), .D(d[3]), .Q(dvs[3]));
FDE_1 i_dvs_4 (.C(sclk), .CE(we), .D(d[4]), .Q(dvs[4]));
FDE_1 i_dvs_5 (.C(sclk), .CE(we), .D(d[5]), .Q(dvs[5]));
FDE_1 i_dvs_6 (.C(sclk), .CE(we), .D(d[6]), .Q(dvs[6]));
always @ (posedge clk) cnvext <= cntr_en;
always @ (posedge clk)
if (sync || !cntr_en || half) cntr[4:0] <= dvs[4:0];
else if (dec) cntr[4:0] <= cntr[4:0]-1;
always @ (posedge clk)
if (sync || !cntr_en) cnvclk <= 1'b0;
else if (half) cnvclk <= ~cnvclk;
always @ (posedge clk)
if (sync || !cntr_en) fullper <= 1'b0;
else if (half) fullper <= fullper | cnvclk;
endmodule
253 165 0ee 067 238 3cb 2c1 096 1af 25b 137 3c2 183 3d6 2e0 179 2e0 179 08e 284 0ea 09a 1a3 3fc 357 1d7 165 355 275 204 147 370 147 370 03f 2ad 2ba 050 314 1f6 283 109 1af 0d4 2e0 20a 167 27e 167 27e 056 3e4 29c 20f 1a8 2c8 265 256 2e8 1c5 236 18b 253 165
292 1dc 227 22f 084 1fc 0f2 3b6 333 122 2e5 0ab 0ed 32d 020 3eb 020 3eb 005 292 166 13a 187 305 220 1d1 07a 10b 077 292 3e2 2d4 3e2 2d4 145 30f 336 1ef 0fa 3f8 160 1c7 37a 367 34a 05f 3ac 3e3 3ac 3e3 23a 2ac 0e9 33d 1e0 2d4 026 367 0b9 146 0d9 238 292 1dc
1d7 2aa 2b6 3df 160 1a4 345 0da 375 15a 34b 055 35b 39e 398 31f 398 31f 33e 341 043 1e1 3e1 314 09e 252 302 14c 01e 259 059 20b 059 20b 119 0ef 184 343 04b 023 28b 141 015 071 39a 12b 011 24d 011 24d 099 3eb 017 0ef 317 04a 06e 08c 358 347 141 1ba 1d7 2aa
1fa 374 313 03b 3f0 309 3da 0ce 27d 395 29d 052 189 2a8 1bd 2e5 1bd 2e5 2da 2e3 203 2b5 328 3f1 1eb 2c1 0bb 316 1e4 39b 0d7 3c3 0d7 3c3 343 1e5 044 216 294 0fa 0eb 373 184 018 0c8 134 13a 306 13a 306 0a1 047 1a7 052 0b3 02a 2b3 011 1cd 0db 1a8 11a 1fa 374
126 324 049 20c 220 18b 119 2c7 376 3fd 369 3e4 0f8 1f0 32a 0d1 32a 0d1 08f 039 2a4 2e6 059 314 068 39c 12d 0b5 02b 359 1df 3e0 1df 3e0 0c6 0d1 125 287 007 055 3bd 052 2ec 3d4 1b7 1fb 02c 264 02c 264 142 2d8 099 391 2b8 2cf 0a9 083 17b 2c5 10f 378 126 324
05b 2b8 358 253 0f2 22a 000 3c5 360 392 2ad 00a 2a7 274 0e1 1e1 0e1 1e1 15c 044 326 374 072 17b 117 1e4 157 329 3f3 295 070 361 070 361 2a1 2b1 127 194 1a3 335 000 0de 14d 0a6 368 07e 1e7 168 1e7 168 37c 09e 1eb 3ae 227 138 350 2e2 362 203 078 1d2 05b 2b8
09a 331 141 20e 165 1e6 191 0c7 33c 354 16b 1c6 398 136 3e0 317 3e0 317 243 005 089 15f 075 027 0f6 29a 23b 372 23d 24e 189 348 189 348 1d6 087 14a 03e 068 29b 2b4 216 1a7 38c 2d9 1be 36b 110 36b 110 04f 299 29e 1a8 3fe 067 3a8 02d 082 397 0e1 129 09a 331
2e1 190 302 23e 078 1be 2ca 2cf 008 043 0a1 217 0ca 334 129 171 129 171 042 07a 3cd 1a7 161 018 107 2bc 0d8 290 007 384 22c 094 22c 094 364 352 28f 386 156 385 0d8 0fc 0fa 187 10b 2bb 1b8 25d 1b8 25d 0bb 1c9 3b3 27e 13e 15b 2b1 166 1db 07f 34c 27d 2e1 190
031 2d3 19c 3e3 32d 2b4 0ac 2dc 2c5 360 151 1fc 33d 170 1ba 1f1 1ba 1f1 05b 2a4 1f2 14c 035 24e 248 34c 22d 183 252 336 358 045 358 045 04b 011 1f4 06a 16d 2f5 36e 28f 046 397 2ff 075 1ce 24f 1ce 24f 1c0 32d 228 332 2e7 113 16b 38c 06e 1bd 0b8 2cf 031 2d3
18a 3fb 210 3fd 283 1c7 038 1ee 073 1a9 079 277 3f1 0e8 295 196 295 196 38c 384 3f7 14e 1f3 3c9 1bb 148 33c 14b 21e 266 20d 35a 20d 35a 18b 3c6 07a 3ec 1ad 1e9 375 3ce 08b 2bc 1b3 3ec 0ad 1e6 0ad 1e6 05e 3c7 2ff 0c2 1f9 091 0d6 39f 139 04f 224 31d 18a 3fb
3ed 208 15c 38c 37a 3f7 26c 105 213 01f 31a 087 3e6 29e 0b8 15f 0b8 15f 2d7 018 2de 2ae 399 18a 05e 1b2 104 2e8 06b 213 34a 2d5 34a 2d5 023 36f 321 30a 316 162 1ed 1bb 2c9 3f7 228 220 355 222 355 222 196 096 336 030 374 0d4 1f2 29f 13d 136 092 068 3ed 208
058 1fb 081 390 311 244 049 121 0a3 3c2 235 12c 01b 390 125 24e 125 24e 33a 161 3a6 26a 229 08f 333 188 084 35a 239 33d 011 3b5 011 3b5 115 00e 2ea 2c5 2a7 261 3d5 155 3ff 046 15f 011 2c6 003 2c6 003 266 29a 3cf 27b 058 2db 1bf 18c 17a 173 100 3b0 058 1fb
3cc 0d2 080 109 24a 1ae 2d0 342 124 192 2c8 165 192 0c0 0da 161 0da 161 1b7 060 34f 183 2a2 1d9 338 1cc 2be 3a1 088 2e3 161 2fa 161 2fa 160 2a2 0d3 01e 162 1e4 22f 39b 12f 0aa 056 2bf 000 089 000 089 3cf 2d3 1c8 0a2 1a5 3a8 13d 166 2f0 204 070 1f6 3cc 0d2
349 38e 257 0f7 224 335 2ff 068 097 290 1d5 234 14a 32c 0d9 39a 0d9 39a 34d 213 2d9 0f9 203 268 16f 37c 0b1 0bd 058 207 03a 1a4 03a 1a4 204 02a 1dd 013 046 0ed 1fa 18f 358 223 00e 32a 003 0b4 003 0b4 2d1 241 223 3a7 05c 03a 16c 32d 29f 3eb 3e1 038 349 38e
3d0 330 307 05a 39e 3d9 1d7 193 3fa 3ba 05a 098 043 3d6 220 1f7 220 1f7 0fb 37b 344 1cc 14e 33c 2d6 399 35c 3ae 2a9 1a8 19b 0b2 19b 0b2 001 1a8 308 3a5 053 07a 036 030 37a 1b2 188 252 3cf 184 3cf 184 06c 1e4 1de 089 17b 190 34c 3e1 188 026 052 377 3d0 330
25f 0b6 390 033 3ba 09a 059 3c3 04e 211 359 191 37d 3bc 1b1 17a 1b1 17a 3c3 199 190 0fc 182 155 06f 324 3c1 174 07b 2c6 286 126 286 126 056 01a 154 3d5 289 18c 1e3 07d 295 055 1c2 137 064 3f9 064 3f9 1a0 2bb 1fb 047 203 0ac 3dd 082 0a9 3b7 2c5 0b3 25f 0b6
3d0 330 307 05a 39e 3d9 1d7 193 3fa 3ba 05a 098 043 3d6 220 1f7 220 1f7 0fb 37b 344 1cc 14e 33c 2d6 399 35c 3ae 2a9 1a8 19b 0b2 19b 0b2 001 1a8 308 3a5 053 07a 036 030 37a 1b2 188 252 3cf 184 3cf 184 06c 1e4 1de 089 17b 190 34c 3e1 188 026 052 377 3d0 330
25f 0b6 390 033 3ba 09a 059 3c3 04e 211 359 191 37d 3bc 1b1 17a 1b1 17a 3c3 199 190 0fc 182 155 06f 324 3c1 174 07b 2c6 286 126 286 126 056 01a 154 3d5 289 18c 1e3 07d 295 055 1c2 137 064 3f9 064 3f9 1a0 2bb 1fb 047 203 0ac 3dd 082 0a9 3b7 2c5 0b3 25f 0b6
043 2a7 242 079 1d3 18a 3d3 270 0f1 225 12a 1f9 0b0 0de 018 0df 018 0df 0af 22f 1ba 2bb 192 13f 05e 051 145 1c4 0f8 10d 07c 0e0 07c 0e0 16e 330 0ff 211 020 3e2 18f 175 3bc 0bc 0f7 254 0d9 336 0d9 336 0d2 281 296 2b1 211 29d 3b6 3f3 162 066 022 256 043 2a7
0f6 1c1 030 025 273 0bf 2f8 2b4 309 330 00c 345 2ee 3b8 2cd 2f6 2cd 2f6 1db 120 18a 15f 36a 26c 0bb 390 28e 0de 2ce 21f 18b 0e7 18b 0e7 128 377 1cf 2b4 0fa 108 300 276 0bb 1b4 235 22d 292 23f 292 23f 26a 22d 236 3e4 23d 2cc 10b 248 368 34b 099 186 0f6 1c1
0b2 3c0 2f6 146 2b4 111 2c7 0fd 312 268 068 027 26d 2d0 0ca 331 0ca 331 11f 1c7 03b 360 32b 1de 248 33b 28f 3cd 125 1ad 323 354 323 354 03a 1b2 0c0 0f5 0fd 0b4 0e1 225 1b3 2c0 335 2c3 214 3ed 214 3ed 09b 00e 338 0f3 2d2 1c1 212 18a 2a6 284 011 3b4 0b2 3c0
077 1a5 395 0dc 395 380 03e 24b 20d 0cd 33c 19e 02d 324 311 292 311 292 37d 122 2cd 1be 1d4 095 207 053 24a 391 0fd 0b9 244 126 244 126 3a6 2e3 2d3 1d2 129 3e4 034 181 3a4 0e1 0f5 116 05f 140 05f 140 065 123 29a 2e0 0d0 07b 3c9 2b9 01d 313 389 1de 077 1a5
146 06e 30e 3e7 218 10c 05e 39e 0f8 35f 18a 0aa 12d 1b6 2a0 217 2a0 217 1f4 032 240 179 067 392 0f6 3d9 2be 12a 356 042 3ed 35d 3ed 35d 06b 009 106 24c 27e 399 1f8 189 38e 117 076 226 273 338 273 338 2c8 26e 15e 2aa 138 3f9 331 2d5 0cd 1f6 003 105 146 06e
01d 11c 25f 367 33c 2b5 028 1f6 0d4 31f 050 24a 26f 384 079 2c2 079 2c2 183 3f8 394 391 3e2 3d3 017 2cb 0eb 198 130 148 120 2f8 120 2f8 389 223 05a 364 1fc 0d4 32d 33f 271 063 2b9 2f3 150 2d5 150 2d5 0c4 0ee 082 150 108 13d 14a 2dd 1b6 02f 27d 229 01d 11c
1fd 0af 289 05c 000 17a 09a 253 2a1 10b 08f 380 0f2 190 19a 192 19a 192 32c 172 3c9 106 147 259 068 22b 1d0 1db 38b 0ca 2dc 0f9 2dc 0f9 200 233 1cf 218 0a3 093 0d2 3a2 14d 3c3 0bc 07d 1f6 117 1f6 117 359 1a3 108 3d4 141 146 314 3d3 3d8 2bc 3f9 24b 1fd 0af
3e6 028 08c 3c7 166 25d 2b5 1b5 360 224 348 14b 1b6 0d8 304 386 304 386 3ed 1a1 3df 2d9 195 024 2eb 2f7 26f 2f3 367 3ca 221 25f 221 25f 0cf 137 265 36a 372 3d8 3e9 3b1 121 038 380 3c4 165 2fe 165 2fe 387 18d 3ee 334 2e3 113 18f 2b6 034 29f 176 269 3e6 028
2d8 085 169 2a6 06d 25d 37a 11c 00f 36a 179 0aa 1bb 25e 1b8 1a0 1b8 1a0 0c8 186 0d6 208 1cb 234 09e 231 3c7 1e0 1c4 347 3ee 02a 3ee 02a 0f8 031 31d 058 36b 3a1 171 06e 2ef 2c2 006 1c8 09d 18a 09d 18a 24e 1ac 236 072 2ee 1a6 1bb 086 3c8 0d6 3f3 384 2d8 085
3d4 2c7 21e 1fa 215 27a 3e7 188 1af 1dd 024 29f 201 320 2b4 0de 2b4 0de 2bb 21f 3ae 394 2eb 189 283 0d7 2d7 3a2 3a2 041 145 35a 145 35a 37a 020 0f5 1e3 18d 0ef 26a 2d8 3b6 061 34c 389 09e 1bb 09e 1bb 0ae 300 0de 08d 262 3fe 098 243 395 263 072 29c 3d4 2c7
3d8 3ef 3ac 2c3 35d 3b4 0fe 3f8 141 27d 047 029 387 020 2fa 242 2fa 242 2c8 06d 167 07d 1f4 323 199 3eb 0a1 139 201 3b7 325 0ee 325 0ee 155 203 0ee 10c 2d8 0c3 3d4 3ee 076 216 253 207 268 091 268 091 3a7 288 0e8 084 23f 11a 326 0ed 09b 044 3f1 0b2 3d8 3ef
3e5 0fb 314 201 147 30b 3bd 16e 3c3 24b 2e4 248 34f 25c 388 2ca 388 2ca 1ed 171 301 1c3 3e5 003 2df 06b 224 3a5 1e1 2ab 28d 1e8 28d 1e8 389 2dc 008 2d1 04c 01b 2ae 0b2 22f 0df 21c 242 2fb 30c 2fb 30c 03a 146 352 159 385 1fc 265 184 3da 37a 372 2c4 3e5 0fb
0fb 2ec 154 0b4 0d2 17f 125 2e9 236 245 0f9 1fb 258 2d6 160 378 160 378 12c 229 17c 066 1c0 127 357 358 05f 3e6 043 21c 07f 347 07f 347 315 3a9 343 034 2e9 3f9 3fa 223 1e1 1bd 3a5 13a 357 22c 357 22c 365 039 11d 00b 334 3a3 355 108 252 106 3f3 1d3 0fb 2ec
01b 2c2 36d 3dc 2fd 010 237 169 19a 36c 387 044 1a2 28c 180 14a 180 14a 183 396 1d8 166 083 390 3ff 1b3 054 2fc 225 30a 1fa 20b 1fa 20b 0fb 16c 3a0 233 3af 15b 0b7 141 08c 1b0 3ef 3ef 07c 2f1 07c 2f1 229 061 34a 199 24d 30e 2f6 079 104 1e6 276 2df 01b 2c2
0fb 2ec 154 0b4 0d2 17f 125 2e9 236 245 0f9 1fb 258 2d6 160 378 160 378 12c 229 17c 066 1c0 127 357 358 05f 3e6 043 21c 07f 347 07f 347 315 3a9 343 034 2e9 3f9 3fa 223 1e1 1bd 3a5 13a 357 22c 357 22c 365 039 11d 00b 334 3a3 355 108 252 106 3f3 1d3 0fb 2ec
01b 2c2 36d 3dc 2fd 010 237 169 19a 36c 387 044 1a2 28c 180 14a 180 14a 183 396 1d8 166 083 390 3ff 1b3 054 2fc 225 30a 1fa 20b 1fa 20b 0fb 16c 3a0 233 3af 15b 0b7 141 08c 1b0 3ef 3ef 07c 2f1 07c 2f1 229 061 34a 199 24d 30e 2f6 079 104 1e6 276 2df 01b 2c2
3ae 3a3 2cf 212 347 270 161 107 36d 3f0 009 09c 305 31e 198 3a0 198 3a0 320 21c 031 095 044 069 11f 350 088 33b 2d1 0c1 1a0 0b4 1a0 0b4 2c3 272 17a 1df 0f6 0a0 193 2a8 063 208 354 07c 2a1 11f 2a1 11f 20b 216 215 173 20b 1ef 3ff 05a 06d 286 004 3f2 3ae 3a3
0f2 10e 24c 10e 1f6 375 316 19b 095 3cb 27b 339 153 1c8 0dc 006 0dc 006 1dc 05e 211 109 0ac 1e7 08b 15f 161 3a5 0b7 1a3 33f 30c 33f 30c 00c 208 05b 052 060 217 214 279 0f2 04f 0a3 025 0ea 278 0ea 278 133 112 3c6 076 0c7 26f 064 17f 202 2ba 08a 2f2 0f2 10e
13e 15d 2a3 180 047 197 174 034 3af 1d3 267 16b 0e2 0b0 36a 292 36a 292 2b0 054 2d2 0da 2fc 1a9 129 3da 0f2 3e4 31e 101 167 3c9 167 3c9 0af 394 15c 063 2f3 212 306 0f8 17a 2ab 1b2 08b 0fc 276 0fc 276 0f4 243 2d7 355 3ec 1b4 07a 391 0d1 344 012 0f0 13e 15d
193 191 0d2 066 339 1d6 17c 1d2 1b9 308 0cb 031 2b2 0d5 240 043 240 043 29e 2ff 374 108 036 0b0 3f7 3c3 03d 0f8 306 3dd 117 3ea 117 3ea 1ab 015 17e 310 1af 192 168 324 2fb 21d 382 2ae 3d7 219 3d7 219 24e 2a9 04a 312 07a 0bd 141 390 1d8 122 39b 2ea 193 191
2f1 2aa 1da 2c1 3cb 132 02c 375 3b4 06a 2a8 08d 3c3 336 260 218 260 218 2a4 160 0f7 293 159 3fc 1f7 218 041 3e1 16f 336 351 071 351 071 000 08a 1c1 15b 194 198 23c 1fc 274 3a3 314 38e 27b 261 27b 261 241 344 11d 0ac 371 08c 3b9 27c 218 156 024 1e1 2f1 2aa
259 1a9 2bc 191 2ff 0ab 286 21c 2a1 2fa 0ff 37e 115 0d5 0c8 113 0c8 113 3c4 075 05b 27b 364 08d 027 3da 1fd 19f 359 00c 114 25d 114 25d 0ae 1f5 325 042 3a2 322 281 282 0e7 03e 166 02b 1e8 04e 1e8 04e 1cd 114 252 122 1d1 220 0e2 155 291 0de 2af 2d5 259 1a9
0c9 38c 076 1d6 1d4 140 188 2c9 37e 3b6 0ce 204 3a7 2b0 27a 232 27a 232 2fc 140 2a0 1c0 359 363 389 20a 273 332 1c4 35e 360 2ae 360 2ae 0b4 154 2ab 0c6 0d8 332 337 1b5 353 0ee 379 185 31e 0e0 31e 0e0 1f2 119 0e7 176 09b 278 1bc 11a 043 0bc 03a 2c7 0c9 38c
342 154 009 090 14a 3f3 233 27b 34c 39f 317 11e 07b 1c9 074 277 074 277 14e 0bf 0c6 163 236 17f 11b 1a6 2a2 19a 1b0 22e 334 264 334 264 114 3a9 151 3e8 238 2c6 15e 094 2b8 2b4 24e 09c 31d 117 31d 117 3b0 052 1dd 2a7 0cd 296 347 2cd 02e 1ee 1c7 2b5 342 154
2c4 002 276 2bf 260 1c3 188 232 30b 3b5 0d8 1ce 090 31e 3b8 2e0 3b8 2e0 3b9 3f3 3cd 262 0fd 3df 1df 3b0 389 1d7 01d 17b 192 27e 192 27e 2cd 1f3 018 2a6 0c1 2e0 1f5 021 016 28e 2e3 270 2e5 1f3 2e5 1f3 007 3c1 235 1b4 368 379 283 36d 353 176 054 3a0 2c4 002
050 094 0bb 163 218 3b0 085 2ee 3bc 0f8 313 113 0e6 3b1 144 06f 144 06f 33c 3dd 0b5 1be 0ad 384 2d3 126 22a 0e9 20c 245 379 3fe 379 3fe 2df 131 000 201 173 07e 1fe 15b 06d 17d 239 001 376 074 376 074 3f7 065 2ed 39f 16c 220 070 3fa 2b0 052 0e3 288 050 094
0e4 00b 3d9 17c 171 2ba 02b 1af 25d 069 2c6 3ec 27d 080 21a 022 21a 022 0d9 17b 07e 077 245 16e 0f9 30a 384 3d0 07b 18b 1e9 3e3 1e9 3e3 24a 265 209 2fa 14e 0a1 278 142 0bd 081 151 24f 1d0 19a 1d0 19a 080 33e 107 166 3d9 38d 20e 174 346 384 073 06e 0e4 00b
181 367 0d0 00a 16a 3e1 17b 375 3ef 306 0f2 35b 255 28d 338 2fb 338 2fb 18e 1ce 028 38d 2c7 29d 14f 25a 096 38c 06b 04f 1e1 32d 1e1 32d 20d 28d 334 28f 152 04a 063 0d5 206 09a 129 25a 2f3 265 2f3 265 2a2 14c 181 00b 3af 0bf 05d 0db 215 00a 003 250 181 367
327 3a9 0a1 20e 305 025 173 140 172 1d0 298 05f 16d 2d6 1a0 1f8 1a0 1f8 25d 1d7 0b3 000 332 011 0d7 018 262 11d 2dc 390 063 2db 063 2db 32a 2ab 07f 1c2 27f 077 0be 116 148 2c9 2c2 122 3df 3d5 3df 3d5 35d 38f 15d 08d 1ee 2b5 05d 32f 01d 2e5 095 12f 327 3a9
2d7 1cf 04a 086 341 086 114 010 3e7 1c7 0b6 3f8 0c7 25d 250 21b 250 21b 044 294 31f 2d0 085 2cb 08f 142 1e7 183 0ce 04e 26e 3ef 26e 3ef 2a0 3be 2eb 191 1d4 22a 08b 304 383 00c 31d 3a7 194 2ea 194 2ea 3b1 307 199 3eb 396 271 30e 170 25e 116 327 20b 2d7 1cf
327 3a9 0a1 20e 305 025 173 140 172 1d0 298 05f 16d 2d6 1a0 1f8 1a0 1f8 25d 1d7 0b3 000 332 011 0d7 018 262 11d 2dc 390 063 2db 063 2db 32a 2ab 07f 1c2 27f 077 0be 116 148 2c9 2c2 122 3df 3d5 3df 3d5 35d 38f 15d 08d 1ee 2b5 05d 32f 01d 2e5 095 12f 327 3a9
2d7 1cf 04a 086 341 086 114 010 3e7 1c7 0b6 3f8 0c7 25d 250 21b 250 21b 044 294 31f 2d0 085 2cb 08f 142 1e7 183 0ce 04e 26e 3ef 26e 3ef 2a0 3be 2eb 191 1d4 22a 08b 304 383 00c 31d 3a7 194 2ea 194 2ea 3b1 307 199 3eb 396 271 30e 170 25e 116 327 20b 2d7 1cf
01a 1a0 05c 0ac 1ba 056 3ef 09d 2e9 2bb 3e7 040 25b 25e 018 360 018 360 291 30a 3a9 36f 3f6 094 2df 34f 0cb 1b3 1aa 175 3c4 189 3c4 189 117 2b3 2f6 2ad 2cc 25f 297 0db 20a 054 2b2 3a4 169 007 169 007 044 2ac 295 135 305 242 147 1c1 078 1a5 0e5 28e 01a 1a0
1ed 15a 169 2f8 27a 32b 034 181 322 166 1ea 02d 0b9 0d9 3ec 217 3ec 217 2dc 09b 399 1b3 2ee 261 15b 02e 133 36d 3a0 227 1f3 230 1f3 230 3f1 19a 3e6 2f0 0c6 025 228 37c 229 3eb 010 31d 042 3b0 042 3b0 0fc 0f8 255 208 051 312 0bc 1b6 19d 32a 17c 15e 1ed 15a
2ca 3f9 350 2b9 2da 31d 122 06a 14b 23e 165 3ae 057 390 30a 2f3 30a 2f3 141 3e2 26a 354 3ce 273 109 179 055 0fc 217 155 0aa 13d 0aa 13d 224 276 2f7 0d1 1e9 071 22a 0cb 240 397 12f 353 0e4 1fe 0e4 1fe 24d 179 376 2b7 206 2a6 3e2 298 3fb 103 113 32c 2ca 3f9
3af 27e 30f 0ef 3dc 12c 3ba 258 265 243 35a 3c5 237 385 270 2f3 270 2f3 2bf 1dd 11c 152 398 1ca 2e8 032 330 360 20f 001 0eb 3af 0eb 3af 0b0 246 129 14e 335 041 39d 1c7 351 058 310 146 04f 3f1 04f 3f1 137 12f 2f9 044 124 200 3b9 167 092 032 0ac 0f6 3af 27e
19d 1e7 1a7 29a 27f 258 0fa 04b 371 275 0c7 171 358 1b6 320 319 320 319 055 38d 0af 0ad 34a 167 3f7 157 2c3 399 088 32a 3b5 286 3b5 286 095 20c 37c 169 1aa 096 381 36f 25b 32e 2b1 1f6 383 289 383 289 2ba 119 1dc 3ae 2ab 21f 141 323 063 1b5 145 3bd 19d 1e7
194 335 018 0ba 3c2 3a1 1e3 343 16d 3d5 2ae 1b1 0ba 325 218 063 218 063 305 1f3 222 265 3e6 248 138 1e9 010 2a7 283 3d0 208 2c2 208 2c2 2d2 2c6 2f1 220 247 271 2d5 2c5 05e 11a 113 263 380 2c6 380 2c6 3d6 239 121 1f4 39b 002 17a 0cc 06c 28e 3e0 081 194 335
095 369 363 050 0a7 207 376 040 15a 361 20d 187 35d 0d0 05a 3d3 05a 3d3 3cd 20d 277 37b 26b 16e 3a9 2e9 016 18a 0fe 2f2 0e3 162 0e3 162 069 176 086 074 20e 2d0 29b 0c8 25a 31a 337 38d 146 1a8 146 1a8 18b 18e 1c6 018 0f4 0ab 164 362 1ae 3bb 17c 043 095 369
39e 381 086 25a 22d 289 2b1 042 038 21a 3e5 1f2 041 3b9 2e4 267 2e4 267 3af 0dc 2ad 0ed 3d8 3d9 04c 155 3d4 142 0fa 192 148 368 148 368 259 31b 13c 166 1fe 2b5 3d2 278 14f 22f 21b 274 1d5 02f 1d5 02f 0d9 018 0cd 319 3b6 119 1ff 3e4 129 23e 318 001 39e 381
3b0 07e 082 3d9 154 229 095 049 308 100 137 3f2 065 0de 2b8 121 2b8 121 3a9 361 3c4 3bc 12f 289 01f 22f 04c 2cf 377 0af 036 1d3 036 1d3 1a2 0b4 213 1f4 317 31e 37a 0d4 23d 359 2c0 018 22d 35b 22d 35b 2c0 2d7 334 3f6 0e2 24b 04b 354 3dd 315 1b6 0bc 3b0 07e
1cb 360 058 1cd 31b 1e6 223 155 2c8 113 301 086 0cb 141 0d4 0ff 0d4 0ff 0bd 29a 2bc 0e8 36f 27e 024 275 27d 331 175 149 2ad 1a3 2ad 1a3 344 343 00b 320 259 10d 292 0de 224 399 227 179 34e 02c 34e 02c 040 2cb 1fd 3b1 176 143 148 2b1 2cb 342 254 374 1cb 360
2f0 128 106 136 084 2c0 059 066 079 354 245 0b0 272 1e0 23a 303 23a 303 3e9 388 095 171 397 0b9 159 329 367 368 3f4 060 1ac 3d7 1ac 3d7 03e 3c6 025 1e8 0c4 180 21c 395 204 3ed 14e 397 238 3a2 238 3a2 259 0f4 226 349 273 300 1f6 2fb 2f1 3c3 1f4 12a 2f0 128
01d 2d4 38d 314 28e 1b7 039 27c 11b 0c1 001 16f 25a 3bd 3e8 02b 3e8 02b 22f 32c 24f 257 2a9 238 0c0 149 009 074 3f4 2f3 235 171 235 171 192 33f 35f 34d 358 178 317 1f8 2dd 156 136 372 3eb 2bd 3eb 2bd 20b 251 0b1 3bd 0d9 081 355 132 150 19a 194 2dc 01d 2d4
253 165 0ee 067 238 3cb 2c1 096 1af 25b 137 3c2 183 3d6 2e0 179 2e0 179 08e 284 0ea 09a 1a3 3fc 357 1d7 165 355 275 204 147 370 147 370 03f 2ad 2ba 050 314 1f6 283 109 1af 0d4 2e0 20a 167 27e 167 27e 056 3e4 29c 20f 1a8 2c8 265 256 2e8 1c5 236 18b 253 165
292 1dc 227 22f 084 1fc 0f2 3b6 333 122 2e5 0ab 0ed 32d 020 3eb 020 3eb 005 292 166 13a 187 305 220 1d1 07a 10b 077 292 3e2 2d4 3e2 2d4 145 30f 336 1ef 0fa 3f8 160 1c7 37a 367 34a 05f 3ac 3e3 3ac 3e3 23a 2ac 0e9 33d 1e0 2d4 026 367 0b9 146 0d9 238 292 1dc
module sensor12bits (MCLK, // Master clock
MRST, // Master Reset - active low
ARO, // Array read Out.
ARST, // Array Reset. Active low
OE, // output enable active low
SCL, // I2C clock
SDA, // I2C data
OFST, // I2C address ofset by 2: for simulation 0 - still mode, 1 - video mode.
D, // [11:0] data output
DCLK, // Data output clock
BPF, // Black Pixel Flag
HACT, // Horizontal Active
VACT, // Vertical Active
VACT1);
input MCLK, // Master clock
MRST, // Master Reset - active low
ARO, // Array read Out.
ARST, // Array Reset. Active low
OE, // output enable active low
SCL; // I2C clock
inout SDA; // I2C data
input OFST; // I2C address ofset by 2: for simulation 0 - still mode, 1 - video mode.
output [11:0] D; // data output
output DCLK, // Data output clock
BPF, // Black Pixel Flag
HACT, // Horizontal Active
VACT, // Vertical Active
VACT1; // 1-clock VACT
parameter ramp = 1; // 1 - ramp, 0 - random (now - sensor.dat)
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 s_stop= 0;
parameter s_preVACT= 1;
parameter s_firstline=2;
parameter s_BPF= 3;
parameter s_preHACT= 4;
parameter s_HACT= 5;
parameter s_afterHACT=6;
parameter s_lastline= 7;
parameter s_frame_done=8;
//parameter t_preVACT= nAV; // 240
parameter t_preVACT= lline* trigdly;
parameter t_firstline=nrowb*lline+1; // 1664
parameter t_BPF= nbpf; // 16
parameter t_preHACT= ngp1; // 8
parameter t_HACT= ncols; // 1288
parameter t_afterHACT=lline-nbpf-ngp1-ncols; // 352
parameter t_lastline= nrowa*lline+1; // 1664
reg [15:0] sensor_data[0:4095]; // up to 64 x 64 pixels
// $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;
parameter new_bayer=0; // 0 - old (16x16), 1 - new (18x18)
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 (" -- 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
$readmemh("sensor.dat",sensor_data);
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, ective 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; // sign
d_rand=c_rand?(D+(((1023-d_rand)*r)>>10)):(d_rand-((d_rand*r)>>10));
end
endmodule
/*
** -----------------------------------------------------------------------------**
** sensor_phase353.v
**
** Phase conpensating for the sesnor data (separate for data and hact/vact)
**
** Copyright (C) 2010 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 sensor_phase353 (cclk, // command clock (posedge, invert on input if needed)
wcmd, // write command
cmd, // CPU write data [5:0]
// 0 - nop, just reset status data
// 1 - increase phase shift
// 2 - decrease phase shift
// 3 - reset phase shift to default (preprogrammed in FPGA configuration)
// c - reset phase90
// 4 - incr pahse90
// 8 - decrease phase90
// 10 - increase hact/vact phase
// 20 - decrease hact/vact phase
// 30 - reset hact/vact phase
HACT, // sensor HACT I/O pin (input), used to reset FIFO
VACT, // sensor VACT I/O pin (input)
DI, // sensor D[DATA_WIDTH-1:0] i/o pins (input), strobed @posedge gclk_idata and en_idata
debug, // 2-bit debug mode input
hact_length,// [13:0] WOI width-1 (to overwrite sensor HACT duration)
hact_regen, // 0 - use hact from sensor, 1 - regenerate using hact_lengh
mode_12bits,// input, 1 - enable 12/14 bit mode, 0 - 10 bit mode
mode_14bits,// input, 1 - enable 14 bit mode, 0 - 12/10 bit mode
mode_alt, // enable alternative vact/hact input (sync to data)
sync_alt, // alternative HACT/VACT input pad (10347) (VACT - 1 clock, HACT >1)
iclk, // DCM input clock (GCLK)
sclk, // global FIFO output clock (posedge)
shact, // hact - sync to sclk
en_svact, // disable processing second vact after the trigger in triggered mode
svact, // vact - sync to sclk (single cycle)
sdo, // data output[DATA_WIDTH-1:0], sync to sclk
dcm_done, // DCM command done
status, // dcm status (bit 1 - dcm clkin stopped)
locked); // DCM locked
/*in UCF
NET "i_sensorpads/i_sensor_phase/gclk_idata" TNM_NET = "TNM_GCLK_IDATA";
NET "i_sensorpads/i_sensor_phase/en_idata" TNM_NET = "TNM_EN_IDATA";
TIMESPEC "TS_PCLK_GCLK_IDATA" = FROM "TNM_PCLK" TO "TNM_GCLK_IDATA" TIG;
TIMESPEC "TS_GCLK_IDATA_PCLK" = FROM "TNM_GCLK_IDATA" TO "TNM_PCLK" TIG;
TIMESPEC "TS_DOUBLECYC_IDATA" = FROM "TNM_EN_IDATA" TO "TNM_EN_IDATA" "TS_CLK1";
NET "i_sensorpads/i_sensor_phase/phase_hact_sel_sync*" TIG;
NET "i_sensorpads/i_sensor_phase/mode_alt_sync" TIG;
NET "i_sensorpads/i_sensor_phase/mode_12bits_sync" TIG;
NET "i_sensorpads/i_sensor_phase/mode_14bits_sync" TIG;
NET "hact_length*" TIG;
*/
parameter MIN_VACT_PERIOD=130; // 3-130, to increase maximal value (130) - chnge counter width
parameter IS_SIMUL=0;
//synthesis translate_off
parameter IS_SIMUL=1;
//synthesis translate_on
input cclk; // command clock (posedge, invert on input if needed)
input wcmd; // write command
input [5:0] cmd; // CPU write data [5:0]
// 0 - nop, just reset status data
// 1 - increase phase shift
// 2 - decrease phase shift
// 3 - reset phase shift to default (preprogrammed in FPGA configuration)
// c - reset phase90
// 4 - incr pahse90
// 8 - decrease phase90
// 10 - increase hact/vact phase
// 20 - decrease hact/vact phase
// 30 - reset hact/vact phase
input HACT; // sensor HACT I/O pin (input), used to reset FIFO
input VACT; // sensor VACT I/O pin (input)
input [11:0] DI; // sensor D11:0], after IBUF (IOBUF)
input [1:0] debug; // 2-bit debug mode input, connect to 2'b0 if not needed
input [13:0] hact_length;// [13:0] WOI width (to overwrite sensor HACT duration)
input hact_regen; // 0 - use hact from sensor, 1 - regenerate using hact_lengh
input mode_12bits;// input, 1 - enable 12/14 bit mode, 0 - 10 bit mode, use 1'b1 in 10359
input mode_14bits;// input, 1 - enable 14 bit mode, 0 - 12/10 bit mode, use 1'b0 in 10359
input mode_alt; // enable alternative vact/hact input (sync to data), use 1'b0 in 10359
input sync_alt; // alternative HACT/VACT input pad (10347) (VACT - 1 clock, HACT >1)
input iclk; // global sensor input clock (posedge) - the clock that goes to all 3 sensors
input sclk; // global FIFO output clock (posedge)
output shact; // hact - sync to sclk
input en_svact; // disable processing second vact after the trigger in triggered mode
output svact; // vact - sync to sclk
output [13:0] sdo; // data output[DATA_WIDTH-1:0], sync to sclk (Use {pxdo[11:0],unused[1:0]} in 10359
output dcm_done; // DCM command done
output [7:0] status; // DCM command done
output locked; // DCM locked
wire dcm_rst_cmd;
reg [2:0] dcm_drst;
reg dcm_en;
reg dcm_incdec;
reg dcm_done;
wire dcm_done_dcm; // single-cycle
reg dcm_rst;
reg [2:0] dcm_reset_done;
reg [1:0] phase90sel;
reg [2:0] phase_hact_sel;
wire locked;
wire dcm_out0,dcm2x,dcm2x180;
wire gclk_idata;
reg en_idata;
wire pre_pre_en_idata, pre_pre_en_idata90;
reg pre_en_idata;
reg inv_gclk_idata;
reg inv_en_idata;
wire [7:0] status;
// reg reset_fifo_in_cntr; // only for simulation;
wire reset_fifo_in_cntr; // only for simulation;
FD i_dcm_rst_cmd(.Q(dcm_rst_cmd), .D((wcmd && (cmd[1:0] == 2'b11)) || (dcm_rst_cmd && !dcm_drst[2])), .C(cclk)) ;
always @ (posedge cclk) begin
dcm_reset_done[2:0] <= {dcm_reset_done[1] & ~dcm_reset_done[0], dcm_reset_done[0], dcm_rst}; // sync to cclkl end of dcm reset
dcm_en <= wcmd && (cmd[1]!=cmd[0]);
dcm_incdec <= wcmd && cmd[0];
if (wcmd) begin
if (cmd[2] && cmd[3]) phase90sel[1:0] <= 2'h0;
else if (cmd[2]) phase90sel[1:0] <= phase90sel[1:0] +1;
else if (cmd[3]) phase90sel[1:0] <= phase90sel[1:0] -1;
end
if (wcmd) begin
if (cmd[4] && cmd[5]) phase_hact_sel[2:0] <= 3'h0;
else if (cmd[4]) phase_hact_sel[2:0] <= phase_hact_sel[2:0] +1;
else if (cmd[5]) phase_hact_sel[2:0] <= phase_hact_sel[2:0] -1;
end
// if (wcmd) reset_fifo_in_cntr <= IS_SIMUL && (cmd[5:0]==6'h3f);
end
always @ (posedge iclk) begin
dcm_drst[2:0] <= dcm_drst[2]? 3'b0:{dcm_drst[1], dcm_drst[0], dcm_rst_cmd};
dcm_rst <= dcm_drst[0] || dcm_drst[1] || dcm_drst[2] ;
end
// make dcm_done behave as dcm_ready
always @ (posedge cclk)
if (wcmd && |cmd[2:0]) dcm_done <=1'b0;
else if (dcm_done_dcm || dcm_reset_done[2]) dcm_done <=1'b1;
/// DCM to compensate sensor delays. Adjustment for data phase - both fine and 90-degrees, hact/vact - 90-degree steps relative to data
always @ (posedge gclk_idata) begin
inv_gclk_idata <= phase90sel[0]; /// TODO: check polarities. Make them TIG?
inv_en_idata <= phase90sel[1]; /// TODO: check polarities. Make them TIG?
pre_en_idata <=inv_gclk_idata?pre_pre_en_idata90:pre_pre_en_idata; /// adjust tap
en_idata <= pre_en_idata ^ inv_en_idata;
end
BUFGMUX i_pclk (.O(gclk_idata), .I0(dcm2x), .I1(dcm2x180), .S(inv_gclk_idata));
DCM_SP #(
.CLKIN_DIVIDE_BY_2("FALSE"), // TRUE/FALSE to enable CLKIN divide by two feature
.CLKIN_PERIOD(10.0), //96Hz
.CLKOUT_PHASE_SHIFT("VARIABLE"),// Specify phase shift of NONE, FIXED or VARIABLE
.CLK_FEEDBACK("1X"), // Specify clock feedback of NONE, 1X or 2X
.DESKEW_ADJUST("SYSTEM_SYNCHRONOUS"), // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or
// an integer from 0 to 15
.DLL_FREQUENCY_MODE("LOW"), // HIGH or LOW frequency mode for DLL
.DUTY_CYCLE_CORRECTION("TRUE"), // Duty cycle correction, TRUE or FALSE
.PHASE_SHIFT(0), // Amount of fixed phase shift from -255 to 255
.STARTUP_WAIT("FALSE") // Delay configuration DONE until DCM LOCK, TRUE/FALSE
) i_dcm_sensor(
.CLKIN (iclk),
.CLKFB (dcm_out0),
.RST (dcm_rst),
.PSEN (dcm_en),
.PSINCDEC (dcm_incdec),
.PSCLK (cclk),
.DSSEN (1'b0),
.CLK0 (dcm_out0),
.CLK90 (pre_pre_en_idata), // adjust tap
.CLK180 (pre_pre_en_idata90), // adjust tap
.CLK270 (),
.CLKDV (),
.CLK2X (dcm2x),
.CLK2X180 (dcm2x180),
.CLKFX (),
.CLKFX180 (),
.STATUS (status[7:0]),
.LOCKED (locked),
.PSDONE (dcm_done_dcm));
// Preventing skipping VACT/HACT after DCM reset (disabling update of the fifo output address:
reg [1:0] dcm_in_locked; // syncing to sclk
reg [3:0] dcm_locked_cntr; // counter that extends !locked to the fifo size
reg dcm_fifo_locked; // safe to reset fifo output address
always @ (posedge sclk) begin
dcm_in_locked[1:0] <= {dcm_in_locked[0],locked};
if (!dcm_in_locked[1]) dcm_fifo_locked <= 1'b0;
else if (dcm_locked_cntr[3:0]==4'h0) dcm_fifo_locked <= 1'b1;
if (!dcm_in_locked[1]) dcm_locked_cntr[3:0] <= 4'hf;
else if (!dcm_fifo_locked) dcm_locked_cntr[3:0] <= dcm_locked_cntr[3:0]-1;
end
// reg [11:0] idi;
wire [11:0] idi;
reg [13:0] idi14;
wire hact_q0, vact_q0;
// wire hact_q1,vact_q1;
reg hact_q1,vact_q1;
wire sync_alt_d0;
reg [2:1] sync_alt_d;
reg [3:0] hact_q1_d;
reg [3:0] hact_q0_d;
reg [3:0] vact_q1_d;
reg [3:0] vact_q0_d;
reg hact_vd; // variable delay, each clock cycle
reg vact_vd; // variable delay, each clock cycle
reg hact_selected; // selected between normal and alt hact
reg vact_selected; // selected between normal and alt vact
reg [1:0] hact_selected_d;
reg hact_selected_2_cycles;
reg [1:0] vact_selected_d;
reg vact_selected_2_cycles;
wire alt_hact;
wire alt_vact;
reg [2:0] phase_hact_sel_sync;
reg mode_alt_sync;
reg mode_12bits_sync;
reg mode_14bits_sync;
reg svact,shact;
reg [13:0] sdo;
wire[13:0] pre_sdo;
wire pre_shact;
wire pre_svact; ///nominally 2-cycle long output from FIFO (can be 1 or 3 long)
reg pre_svact_d;
wire ihact,ivact;
reg [13:0] hact_count;
reg pre_shact_d;
reg [13:0] hact_length_sync;
reg hact_regen_sync; // sync to output
reg hact_regen_isync; // sync to gclk_idata
reg hact_count_zero;
assign alt_hact=sync_alt_d[1] && (sync_alt_d0 || sync_alt_d[2]); /// already controlled by mode_alt
assign alt_vact=sync_alt_d[1] && !sync_alt_d0 && !sync_alt_d[2]; /// already controlled by mode_alt
//synthesis translate_off
wire vact_or_hact= VACT || HACT;
reg sim_rst;
always @ (negedge glbl.GSR or posedge vact_or_hact) begin
if (vact_or_hact) sim_rst <= 1'b0;
else sim_rst <= 1'b1;
end
assign reset_fifo_in_cntr=glbl.GSR || sim_rst;
//synthesis translate_on
wire ihact00,ivact00;
/// some are double cycle
IBUF i_hact (.I(HACT), .O(ihact));
IBUF i_vact (.I(VACT), .O(ivact));
always @ (posedge gclk_idata) begin
hact_q1 <= ihact00;
vact_q1 <= ivact00;
hact_q0_d[3:0]<={hact_q0_d[2:0],hact_q0};
hact_q1_d[3:0]<={hact_q1_d[2:0],hact_q1};
vact_q0_d[3:0]<={vact_q0_d[2:0],vact_q0};
vact_q1_d[3:0]<={vact_q1_d[2:0],vact_q1};
end
always @ (posedge gclk_idata) if (en_idata) begin
// HACT delay -3..+4 90-degree steps, positive hact arrives later than data
{vact_vd,hact_vd} <= phase_hact_sel_sync[2]?
(phase_hact_sel_sync[1]?
(phase_hact_sel_sync[0]?{vact_q1_d[2],hact_q1_d[2]}:{vact_q0_d[3],hact_q0_d[3]}):
(phase_hact_sel_sync[0]?{vact_q1_d[3],hact_q1_d[3]}:{vact_q0_d[0],hact_q0_d[0]})):
(phase_hact_sel_sync[1]?
(phase_hact_sel_sync[0]?{vact_q1_d[0],hact_q1_d[0]}:{vact_q0_d[1],hact_q0_d[1]}):
(phase_hact_sel_sync[0]?{vact_q1_d[1],hact_q1_d[1]}:{vact_q0_d[2],hact_q0_d[2]}));
end
IDDR2 i_ihact (.Q0(hact_q0),.Q1(ihact00),.C0(gclk_idata),.C1(!gclk_idata),.CE(1'b1), .D(ihact), .R(1'b0), .S(1'b0) );
IDDR2 i_ivact (.Q0(vact_q0),.Q1(ivact00),.C0(gclk_idata),.C1(!gclk_idata),.CE(1'b1), .D(ivact), .R(1'b0), .S(1'b0) );
// FD i_hact_q1 (.C(gclk_idata), .D(ihact00), .Q(hact_q1));
// FD i_vact_q1 (.C(gclk_idata), .D(ivact00), .Q(vact_q1));
FDCE i_sync_alt_d0 (.Q(sync_alt_d0), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(sync_alt));
FDCE i_idi_0 (.Q(idi[ 0]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 0]));
FDCE i_idi_1 (.Q(idi[ 1]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 1]));
FDCE i_idi_2 (.Q(idi[ 2]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 2]));
FDCE i_idi_3 (.Q(idi[ 3]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 3]));
FDCE i_idi_4 (.Q(idi[ 4]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 4]));
FDCE i_idi_5 (.Q(idi[ 5]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 5]));
FDCE i_idi_6 (.Q(idi[ 6]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 6]));
FDCE i_idi_7 (.Q(idi[ 7]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 7]));
FDCE i_idi_8 (.Q(idi[ 8]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 8]));
FDCE i_idi_9 (.Q(idi[ 9]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[ 9]));
FDCE i_idi_10 (.Q(idi[10]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[10]));
FDCE i_idi_11 (.Q(idi[11]), .C(gclk_idata),.CE(en_idata),.CLR(1'b0),.D(DI[11]));
// synthesis attribute IOB of i_sync_alt_d0 is "TRUE"
// synthesis attribute IOB of i_idi_0 is "TRUE"
// synthesis attribute IOB of i_idi_1 is "TRUE"
// synthesis attribute IOB of i_idi_2 is "TRUE"
// synthesis attribute IOB of i_idi_3 is "TRUE"
// synthesis attribute IOB of i_idi_4 is "TRUE"
// synthesis attribute IOB of i_idi_5 is "TRUE"
// synthesis attribute IOB of i_idi_6 is "TRUE"
// synthesis attribute IOB of i_idi_7 is "TRUE"
// synthesis attribute IOB of i_idi_8 is "TRUE"
// synthesis attribute IOB of i_idi_9 is "TRUE"
// synthesis attribute IOB of i_idi_10 is "TRUE"
// synthesis attribute IOB of i_idi_11 is "TRUE"
// synthesis attribute NODELAY of i_sync_alt_d0 is "TRUE"
// synthesis attribute NODELAY of i_idi_0 is "TRUE"
// synthesis attribute NODELAY of i_idi_1 is "TRUE"
// synthesis attribute NODELAY of i_idi_2 is "TRUE"
// synthesis attribute NODELAY of i_idi_3 is "TRUE"
// synthesis attribute NODELAY of i_idi_4 is "TRUE"
// synthesis attribute NODELAY of i_idi_5 is "TRUE"
// synthesis attribute NODELAY of i_idi_6 is "TRUE"
// synthesis attribute NODELAY of i_idi_7 is "TRUE"
// synthesis attribute NODELAY of i_idi_8 is "TRUE"
// synthesis attribute NODELAY of i_idi_9 is "TRUE"
// synthesis attribute NODELAY of i_idi_10 is "TRUE"
// synthesis attribute NODELAY of i_idi_11 is "TRUE"
// synthesis attribute NODELAY of i_ihact is "TRUE"
// synthesis attribute NODELAY of i_ivact is "TRUE"
reg [1:0] shact_zero; // shact was zero (inactive), sync to gclk_data
always @ (posedge gclk_idata) if (en_idata) begin
idi14[13:4] <= idi[11:2];
idi14[ 3:2] <= (mode_12bits_sync || mode_14bits_sync)? idi[1:0]:2'h0;
idi14[ 1:0] <= mode_14bits_sync? {vact_q0_d[0],hact_q0_d[0]}:2'h0;
sync_alt_d[2:1]<={sync_alt_d[1], sync_alt_d0 & mode_alt_sync}; ///sync_alt_d[0] - IOB
phase_hact_sel_sync[2:0] <= phase_hact_sel[2:0];
mode_14bits_sync <= mode_14bits;
mode_12bits_sync <= mode_12bits;
// hact_regen_isync <= hact_regen;
// only update hact_regen_isync when HACT (both input and output from fifo) are inactive (to prevent short lines)
if ((!hact_q0_d[0]) && shact_zero[1]) hact_regen_isync <= hact_regen;
//shact_zero[1]
//hact_q0_d[3:0]
mode_alt_sync <= mode_alt;
hact_selected <= mode_alt_sync? alt_hact : hact_vd;
vact_selected <= mode_alt_sync? alt_vact : vact_vd;
///if (hact_regen_isync==0) will copy hact to hact_selected_2_cycles
hact_selected_d[1:0]<={hact_selected_d[0], hact_selected && hact_regen_isync };
hact_selected_2_cycles <= (hact_selected && !hact_selected_d[0]) ||
(hact_selected_d[0] && !hact_selected_d[1]);
vact_selected_d[1:0]<={vact_selected_d[0],vact_selected};
/*
vact_selected_2_cycles <= (vact_selected && !vact_selected_d[0]) ||
(vact_selected_d[0] && !vact_selected_d[1]);
*/
vact_selected_2_cycles <= (debug[0] || !hact_selected && !hact_selected_d[0] && !hact_selected_d[1]) && ((vact_selected && !vact_selected_d[0]) ||
(vact_selected_d[0] && !vact_selected_d[1]));
end
//phase_hact_sel==3'h0 - delay by 2 cycles from data
reg [3:0] fifo_data_in_addr;
reg [3:0] fifo_hact_in_addr;
reg [3:0] fifo_data_in_addr_saved;
reg ihact_rst_in;
wire reset_rq;
reg rq;
reg reset_out_fifo;
reg [2:0] pre_reset_out_fifo;
assign reset_rq= reset_out_fifo || (IS_SIMUL && reset_fifo_in_cntr) ;
//glbl.GSR
always @ (posedge gclk_idata) if (en_idata) begin
/// input FIFO counter is only reset for the simulation
if (IS_SIMUL && reset_fifo_in_cntr) fifo_data_in_addr[3:0] <= 4'h0;
else fifo_data_in_addr[3:0] <= fifo_data_in_addr[3:0] + 1;
// if (IS_SIMUL && reset_fifo_in_cntr) fifo_hact_in_addr[3:0] <= 4'he;
// else fifo_hact_in_addr[3:0] <= fifo_data_in_addr[3:0] - 1; // 1 behind data
if (IS_SIMUL && reset_fifo_in_cntr) fifo_hact_in_addr[3:0] <= 4'hc;
else fifo_hact_in_addr[3:0] <= fifo_data_in_addr[3:0] - 3; // 3 behind data
// if (ihact_rst_in) fifo_data_in_addr_saved[3:0] <= fifo_data_in_addr[3:0] - 4'h5; // save FIFO in address for transferring to FIFO out address later
if (ihact_rst_in) fifo_data_in_addr_saved[3:0] <= fifo_data_in_addr[3:0] - 4'h6; // save FIFO in address for transferring to FIFO out address later
end
always @ (posedge gclk_idata or posedge reset_rq) begin
if (reset_rq) rq <= 1'b0;
else if (ihact_rst_in && en_idata) rq <= 1'b1;
end
reg [3:0] fifo_out_addr;
always @ (posedge sclk) begin
pre_reset_out_fifo[2:0]<={pre_reset_out_fifo[1:0], rq};
reset_out_fifo<=pre_reset_out_fifo[1] && ! pre_reset_out_fifo[2];
if (reset_out_fifo && dcm_fifo_locked) fifo_out_addr[3:0] <= fifo_data_in_addr_saved[3:0];
else fifo_out_addr[3:0] <= fifo_out_addr[3:0]+1;
end
reg rq_back;
reg reset_out_fifo_back;
reg [2:0] pre_reset_out_fifo_back;
wire reset_rq_back;
assign reset_rq_back= reset_out_fifo_back || (IS_SIMUL && reset_fifo_in_cntr) ;
always @ (posedge sclk or posedge reset_rq_back) begin
if (reset_rq_back) rq_back <= 1'b0;
else if ( reset_out_fifo) rq_back <= 1'b1;
end
reg wait_reset_back;
always @ (posedge gclk_idata) if (en_idata) begin
shact_zero[1:0]<={shact_zero[0], ~shact}; // dual sync
pre_reset_out_fifo_back[2:0]<={pre_reset_out_fifo_back[1:0], rq_back};
reset_out_fifo_back<=pre_reset_out_fifo_back[1] && ! pre_reset_out_fifo_back[2];
wait_reset_back <= !(IS_SIMUL && reset_fifo_in_cntr) && !hact_selected && shact_zero[1] && (ihact_rst_in || (wait_reset_back && !reset_out_fifo_back));
ihact_rst_in <= (IS_SIMUL && reset_fifo_in_cntr) || (!hact_selected && shact_zero[1] && !wait_reset_back && !ihact_rst_in);
end
//FIFO 16 deep, 2 wide (vact, hact)
wire pre_svact_outfifo;
myRAM_WxD_D #( .DATA_WIDTH(2),.DATA_DEPTH(4))
i_fifo_hact_vact(.D({vact_selected_2_cycles,hact_selected_2_cycles}),
.WE(en_idata),
.clk(gclk_idata),
.AW(fifo_hact_in_addr[3:0]),
.AR(fifo_out_addr[3:0]),
.QW(),
.QR({pre_svact_outfifo,pre_shact}));
//FIFO 16 deep, 14 wide (data)
myRAM_WxD_D #( .DATA_WIDTH(14),.DATA_DEPTH(4))
i_fifo_data_vact(.D(idi14[13:0]),
.WE(en_idata),
.clk(gclk_idata),
.AW(fifo_data_in_addr[3:0]),
.AR(fifo_out_addr[3:0]),
.QW(),
.QR(pre_sdo[13:0]));
reg vact_bypass;
//assign pre_svact=debug[1]?vact_bypass:pre_svact_outfifo;
// for simulation
assign pre_svact= (debug[1]?vact_bypass:pre_svact_outfifo) && (!(IS_SIMUL && reset_fifo_in_cntr));
reg [7:0] svact_filter_cntr=8'h80;
reg en_svact_sync;
// parameter MIN_VACT_PERIOD=130; // 3-130, to increase maximal value (130) - chnge counter width
always @ (posedge sclk) begin
vact_bypass<=vact_selected_2_cycles;
hact_length_sync[13:0] <= hact_length[13:0];
hact_regen_sync <= hact_regen_isync;
pre_shact_d <= pre_shact;
if (IS_SIMUL && reset_fifo_in_cntr) shact <= 1'b0;
else if (pre_shact && !pre_shact_d) shact <= 1'b1;
else if (hact_regen_sync?hact_count_zero:(!pre_shact)) shact <= 1'b0;
if (!shact) hact_count[13:0] <= hact_length_sync[13:0];
else hact_count[13:0] <= hact_count[13:0]-1;
hact_count_zero <= (hact_count[13:0]== 14'h2); // now starts from total number, not number-1
sdo[13:0] <= pre_sdo[13:0];
en_svact_sync <= en_svact;
pre_svact_d <= pre_svact;
// if (pre_svact_d) svact_filter_cntr <= 8'h82-MIN_VACT_PERIOD;
/// for simulation
if (pre_svact_d) svact_filter_cntr <= 8'h82-MIN_VACT_PERIOD;
else if (IS_SIMUL && reset_fifo_in_cntr) svact_filter_cntr <= 8'h78;
else if (!svact_filter_cntr[7]) svact_filter_cntr <= svact_filter_cntr+1;
svact <= pre_svact && ! pre_svact_d && en_svact_sync && svact_filter_cntr[7];
end
endmodule
/*
** -----------------------------------------------------------------------------**
** sensorpads353.v
**
** I/O pads related circuitry for the sensor board connectorfs_composite
**
** Copyright (C) 2002-2010 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 sensorpads (/// interface to DCM
sclk, // system clock, @negedge
cmd, // [6:0] command for phase adjustment @ negedge (sclk) MSB - reset pclk2x DCM
wcmd, // write command@ negedge (slck)
dcm_done, // DCM command done
dcm_status, // [7:0] output dcm status (bit 1 - dcm clkin stopped)
dcm_locked, // DCM locked
clk_sel, // 0 - use clk, 1 - sensor dclk (bpf pad) for DCM input (if dclkmode - use clk if 0)
hact_length,// [13:0] WOI width-1 (to overwrite sensor HACT duration)
hact_regen, // 0 - use hact from sensor, 1 - regenerate using hact_lengh
clk, //pixel clock, posedge
pclk2x, // output - twice pixel clock
vact, // VACT pad, inout
hact, // HACT pad, inout
bpf, // BPF pad, inout
pxd, // [11:0] pads {PXD [9:0],CNVCLK, CNVSYNC} inout
mrst, // MRST pad, inoput (input in JTAG external FPGA programming mode)
arst, // ARST pad, output (output in JTAG external FPGA programming mode)
aro, // ARO pad, output
dclkmode, // input 0 - DCLK is clock to sensor, 1 - combined sync from sensor (like 10347)
pxd14, // input 1 - use {vact,hact} as 2 LSB in 14-bit data
debug, // 2-bit debug mode input
dclk, // DCLK pad (inout)
en_vacts, // disable processing second vact after the trigger in triggered mode
vacts, // output, single cycle
ihact, // output, iihact - posedge clk, latency = 2
sens_clk, // output - clock from sensor to be used as global clock after mux (directly from BPF)
ipxd, // [15:0] output, ipxd - posedge clk, latency = 2
imrst, // input (non-verting)
iarst, // input (non-verting)
iaro, // input (non-verting)
cnvctl, // [1:0] input {icnvclk, icnvsync} - used in 1/2/3 10318 to generate 3.3VDC-> 5.0VDC (and then linear 3.3V)
cnven, // input - 1 - enable converter outputs (0 - use them at 2LSBs of data)
senspgm, // SENSPGM I/O pin
senspgmin, // state of the SENSPGM I/O pin (read)
xpgmen, // enable programming mode for an external FPGA
xfpgaprog, // PROG_B to be sent to an external FPGA
xfpgadone, // state of the MRST pin ("DONE" pin on an external FPGA)
xfpgatck, // TCK to be sent to an external FPGA
xfpgatms, // TMS to be sent to an external FPGA
xfpgatdi, // TDI to be sent to an external FPGA
xfpgatdo // TDO read from an external FPGA
// ,pherr //[1:0] phase error (sync to posedge pclk) {too_early, too_late}
);
input clk_sel; // 0 - use clk, 1 - dclk for DCM input (if dclkmode - use bpf when 1, clk if 0)
input sclk; // system clock, @negedge
input [6:0] cmd; // [5:0] command for phase adjustment @ negedge (slck)
input wcmd; // write command@ negedge (slck)
output dcm_done; // DCM command done
output [7:0] dcm_status; // dcm status (bit 1 - dcm clkin stopped)
output dcm_locked; // DCM locked
input [13:0] hact_length;// [13:0] WOI width-1 (to overwrite sensor HACT duration)
input hact_regen; // 0 - use hact from sensor, 1 - regenerate using hact_lengh
input clk;
output pclk2x;
input vact;
input hact; //output in fillfactory mode
inout bpf; // output in fillfactory mode
inout [11:0] pxd; //actually only 2 LSBs are inouts
inout mrst;
output arst;
output aro;
input dclkmode;
input pxd14; // use {vact,hact} as 2 LSB in 14-bit data
input [1:0] debug; // 2-bit debug mode input
inout dclk;
input en_vacts; // disable processing second vact after the trigger in triggered mode
output vacts; // 1 cycle long
output ihact;
output sens_clk; // ibpf before FD
output [15:0] ipxd;
input imrst;
input iarst;
input iaro;
input [1:0] cnvctl; // 2-bits for converter control (use the same pins as lower bits in 12-bit sensors)
input cnven; // 0 - use 12-bit sensor data, 1 - use converter output pins
inout senspgm; // SENSPGM I/O pin
output senspgmin; // state of the SENSPGM I/O pin (read)
input xpgmen; // enable programming mode for external FPGA
input xfpgaprog; // PROG_B to be sent to an external FPGA
output xfpgadone; // state of the MRST pin ("DONE" pin on external FPGA)
input xfpgatck; // TCK to be sent to external FPGA
input xfpgatms; // TMS to be sent to external FPGA
input xfpgatdi; // TDI to be sent to external FPGA
output xfpgatdo; // TDO read from external FPGA
wire [7:0] dcm_status; // dcm status (bit 1 - dcm clkin stopped)
wire [15:0] ipxd;
assign ipxd[1:0]=2'h0;
wire [1:0] cnvctl;
wire cnven;
wire mrst, arst,aro,dclk, idclk;
wire dcm_rst_cmd;
reg [2:0] dcm_drst;
reg dcm_rst;
reg [1:0] xpgmen_d;
wire force_senspgm;
wire fifo_clkin;
wire [11:0] pxdi;
//Automatic clock placement failed. Please attempt to analyze the global clocking required for this design and either lock the clock...
assign fifo_clkin=(clk_sel && !dclkmode)?sens_clk:clk;
sensor_phase353
i_sensor_phase (.cclk(!sclk), // command clock (posedge, invert on input if needed)
.wcmd(wcmd), // write command
.cmd(cmd[5:0]),// CPU write data [5:0]
// 0 - nop, just reset status data
// 1 - increase phase shift
// 2 - decrease phase shift
// 3 - reset phase shift to default (preprogrammed in FPGA configuration)
// c - reset phase90
// 4 - incr pahse90
// 8 - decrease phase90
// 10 - increase hact/vact phase
// 20 - decrease hact/vact phase
// 30 - reset hact/vact phase
.HACT(hact), // sensor HACT I/O pin (input), used to reset FIFO
.VACT(vact), // sensor VACT I/O pin (input)
// .DI({pxdi[11:2],pxd[1:0]}), // sensor D[DATA_WIDTH-1:0] i/o pins (input), strobed @posedge gclk_idata and en_idata
.DI(pxdi[11:0]), // sensor D[DATA_WIDTH-1:0] i/o pins (input), strobed @posedge gclk_idata and en_idata
.debug(debug[1:0]), // 2-bit debug mode input
.hact_length(hact_length[13:0]),// [13:0] WOI width-1 (to overwrite sensor HACT duration)
.hact_regen(hact_regen), // 0 - use hact from sensor, 1 - regenerate using hact_lengh
.mode_12bits(!cnven), // input, 1 - enable 12/14 bit mode, 0 - 10 bit mode
.mode_14bits(pxd14), // input, 1 - enable 14 bit mode, 0 - 12/10 bit mode
.mode_alt(dclkmode), // enable alternative vact/hact input (sync to data)
.sync_alt(idclk), // alternative HACT/VACT input pad (10347) (VACT - 1 clock, HACT >1)
.iclk(fifo_clkin), // DCM input clock (GCLK) - sensor clock out or sensor clock in
.sclk(clk), // global FIFO output clock (posedge)
.shact(ihact), // hact - sync to sclk
.en_svact(en_vacts), // disable processing second vact after the trigger in triggered mode
.svact(vacts), // vact - sync to sclk (single cycle)
.sdo(ipxd[15:2]), // data output[DATA_WIDTH-1:0], sync to sclk
.dcm_done(dcm_done), // DCM command done
.status(dcm_status[7:0]), // dcm status (bit 1 - dcm clkin stopped)
.locked(dcm_locked)); // DCM locked
IOBUF i_mrst (.I(imrst), .IO(mrst), .T(xpgmen), .O(xfpgadone));
OBUF i_arst (.I(xpgmen? xfpgatms : iarst), .O(arst));
OBUF i_aro (.I(xpgmen? xfpgatck : iaro), .O(aro ));
IOBUF i_dclk (.I(clk), .IO(dclk), .T(dclkmode), .O(idclk));
IBUF i_bpf (.I(bpf), .O(sens_clk));
IOBUF i_pxd0 (.IO(pxd[ 0]), .I(xpgmen?xfpgatdi:cnvctl[0]), .T(~(cnven | xpgmen)), .O(pxdi[0]));
IOBUF i_pxd1 (.IO(pxd[ 1]), .I( cnvctl[1]), .T(~ cnven | xpgmen ), .O(pxdi[1]));
IBUF i_pxd2 (.I (pxd[ 2]), .O(pxdi[ 2]));
IBUF i_pxd3 (.I (pxd[ 3]), .O(pxdi[ 3]));
IBUF i_pxd4 (.I (pxd[ 4]), .O(pxdi[ 4]));
IBUF i_pxd5 (.I (pxd[ 5]), .O(pxdi[ 5]));
IBUF i_pxd6 (.I (pxd[ 6]), .O(pxdi[ 6]));
IBUF i_pxd7 (.I (pxd[ 7]), .O(pxdi[ 7]));
IBUF i_pxd8 (.I (pxd[ 8]), .O(pxdi[ 8]));
IBUF i_pxd9 (.I (pxd[ 9]), .O(pxdi[ 9]));
IBUF i_pxd10 (.I (pxd[10]), .O(pxdi[10]));
IBUF i_pxd11 (.I (pxd[11]), .O(pxdi[11]));
assign xfpgatdo=pxdi[1];
//pxdi[11:0]
PULLUP i_PU_mrst (.O(mrst));
PULLUP i_PU_senspgm(.O(senspgm));
// to reduce noise on pulled-up senspgm it is possible to force it high when xpgmen goes from high to low
always @ (posedge clk) xpgmen_d[1:0] <= {xpgmen_d[0],xpgmen};
// will latch the state of the senspgm pin after xpgmen is over - that will protect from driving senspgm pin
// high if it is grounded on the sensor board
FDCE i_force_senspgm (.Q(force_senspgm), .D(senspgmin), .C(clk), .CE(xpgmen_d[1:0]==2'b10), .CLR(xpgmen));
IOBUF i_senspgm (.I(xpgmen?(~xfpgaprog):force_senspgm), .IO(senspgm), .T(~(xpgmen || force_senspgm)), .O(senspgmin));
/// multiplicating pclk by 2, need a way to reset DCM - should be done after source of the pclk is changed
// extending DCM reset command, synchronizing to DCM input clock
FD_1 i_dcm_rst_cmd(.Q(dcm_rst_cmd), .D((wcmd && cmd[6]) || (dcm_rst_cmd && !dcm_drst[2])), .C(sclk)) ;
always @ (posedge clk) begin
dcm_drst[2:0] <= dcm_drst[2]? 3'b0:{dcm_drst[1], dcm_drst[0], dcm_rst_cmd};
dcm_rst <= dcm_drst[0] || dcm_drst[1] || dcm_drst[2] ;
end
wire pclk2x, pclk2xi;
BUFG i_pclk2x (.I(pclk2xi), .O(pclk2x));
DCM i_dcm4(
.CLKIN (clk),
.CLKFB (pclk2x),
.RST (dcm_rst),
.PSEN (1'b0),
.PSINCDEC (1'b0),
.PSCLK (1'b0),
.DSSEN (1'b0),
.CLK0 (),
.CLK90 (),
.CLK180 (),
.CLK270 (),
.CLKDV (),
.CLK2X (pclk2xi),
.CLK2X180 (),
.CLKFX (),
.CLKFX180 (),
.STATUS (),
.LOCKED (),
.PSDONE ());
// If needed - add positive PHASE_SHIFT - then posedge pclk2x will be earlier than posedge pclk by PHASE_SHIFT/256*period(pclk)
// synthesis attribute CLK_FEEDBACK of i_dcm4 is "2X"
// synthesis attribute CLKIN_DIVIDE_BY_2 of i_dcm4 is "FALSE"
// synthesis attribute CLKIN_PERIOD of i_dcm4 is 10
// synthesis attribute CLKOUT_PHASE_SHIFT of i_dcm4 is "FIXED"
// synthesis attribute DESKEW_ADJUST of i_dcm4 is "SYSTEM_SYNCHRONOUS"
// synthesis attribute DLL_FREQUENCY_MODE of i_dcm4 is "LOW"
// synthesis attribute DUTY_CYCLE_CORRECTION of i_dcm4 is "TRUE"
// put here default phase shift ....
// synthesis attribute PHASE_SHIFT of i_dcm4 is 0
// synthesis translate_off
defparam i_dcm4.CLK_FEEDBACK="2X";
defparam i_dcm4.CLKIN_DIVIDE_BY_2="FALSE";
defparam i_dcm4.CLKIN_PERIOD=10;
defparam i_dcm4.CLKOUT_PHASE_SHIFT="FIXED";
defparam i_dcm4.DESKEW_ADJUST="SYSTEM_SYNCHRONOUS";
defparam i_dcm4.DLL_FREQUENCY_MODE="LOW";
defparam i_dcm4.DUTY_CYCLE_CORRECTION="TRUE";
defparam i_dcm4.PHASE_SHIFT=0;
// synthesis translate_on
endmodule
/*
** -----------------------------------------------------------------------------**
** sensorpix353.v
**
** Input sensor data processing
**
** Copyright (C) 2002-2008 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 sensorpix( pclk, // clock (==pclk)
// control interface
sclk, // global memory clock, @negedge
we_lensff, // write parameters to lens flat field correction module
pre_wfpn, // decoded addresses - write fpn [10:0] mode
// [10] - testmode - if 1 generates gradient data (as Zoran chips) where pixel value = horizontal position
// [9:7] - submode - subtract background (8 bits) mode (use di[7:0]):
// 000 - no subtraction;
// 001 - (finest) subtract 8 bit bkgnd from 12 bits pixels
// 010 - shift 8bit bkgnd 1 bit left before applying
// 011 - shift 8bit bkgnd 2 bits left before applying
// 100 - shift 8bit bkgnd 2 bits left before applying
// 101 - shift 8bit bkgnd 2 bits left before applying
// fpn data to subtract should be a little less to add a "fat zero"
// [6:4] - mpymode sensitivity correction mode (use di[15:8]):
// 000 - no correction
// 001 - fine correction (+/-3.125%)
// 010 - fine correction (+/-6.25%)
// 011 - fine correction (+/-12.5%)
// 100 - +/- 25%
// 101 - +/- 50%
// [3] - wdth - word width: 0 - 8 bit, 1 - 16 bit (5 MSB == 0)
// bits [2:0] - REMOVED
// [2:0] scaling of 11 bit FPN result to fit in 8bit output:
// 00 - default - use [9:1]
// 01 - use [10:2] - to protect from saturation after applying mpymode
// nominal range - 0..127
// 10 - use [7:0] before saturation, "digital gain" == 4 (maximal)
// 11 - use [8:1] before saturation, "digital gain" == 2
pre_wthrsh, // write thresh. register [21:0]
// [21:0] - trigger threshold - sum of pixels in a line, [7:0] - for fpn mode
ta, // "curves" table write address
twce, // "curves" table write enable
wd, // used for curves (instead of wd)- delayed one cwr pulse
en, // Enable. Should go active before or with the first hact going active.
// when low will also reset MSB of addresses - buffer page for ping-pong access.
// SDRAM ch1 should be enabled earler to have data ready in the buffer
// When going low will mask input hact, finish pending data->SDRAM and quit
// So normal sequence is:
// 1 - program (end enable) SDRAM channels 0 and 1, channel 1 will start reading
// 2 - wait for frame sync and enable "en"
// 3 (optional) - after frame is over (before the first hact of the next one)
// turn "en" off. If needed to restart - go to step 1 to keep buffer pages in sync.
trig, // trigger out - fires sum of pixels in a line > threshold
trig_sel, // threshold !=0, use this trigger and disable external
bayer, // bayer phase, used for "gamma" tables
// 1-st 256 16-bit words R, then 256*Gr, 256*Gb, 256*B
hact_out,
// sensor interface
hact, // line active
// pxd, // [11:0] - 12 bit pixel data
pxd, // [15:0] - 16 bit pixel data
// channel 0 (data->SDRAM) interface
dwe, // WE to SDRAM buffer
wa, // 10 bit address (2 MSB - page # for ping-pong access to 256x16 pages)
do, // 16 bit data to SDRAM (1/pixel for raw, 0.5/pixel for FPN processed
wpage, // write page to SDRAM
// ch0rdy, // SDRAM buffer is ready (will not be used as sensor does not wait)
// channel 1 (FPN data from SDRAM) interface
ra,
di,
rpage,
vacts_sclk, // frame sync, @negedge single cycle
table_page); // number of gamma table page currently in use (writes go to the other one)
input pclk;
input sclk;
input we_lensff;
input pre_wfpn;
input pre_wthrsh;
input [15:0] wd;
input en;
output trig;
output trig_sel;
input [ 1:0] bayer; // bayer phase
output hact_out;
input hact;
input [15:0] pxd;
output dwe;
output [ 9:0] wa;
output [15:0] do;
output wpage;
output [ 9:0] ra;
input [15:0] di;
output rpage;
input [9:0] ta;
input twce;
input vacts_sclk;
output table_page;
wire table_page;
wire next_table_page;
reg [12:0] fsc; // sensitivity correction (di[15:0] and mpymode - for now - leave 13 bits
reg [15:0] pd_a; // just delayed pixel data
// wire [15:0] fbg; // scaled di[7:0] according to submode[1:0]
reg [15:0] fbg; // scaled di[7:0] according to submode[1:0]
wire [16:0] pd_subp; // background subtracted
reg [15:0] pd_sub; // registered after bkgnd subtracted, applied zero saturation
wire [28:0] pd_corrp;// full 29-bit result of application of sensitivity correction
reg [16:0] pd_corr; // registered 17 MSBs from the result of sensitivity correction
wire [16:0] pd_corr_r; // registered pd_corr
// reg [16:0] pd_corr_r2; // registered pd_corr_r (extra delay to match increased gamma latency)
reg [15:0] do; // 16-bit data to SDRAM
wire hact_dly3;// hact delayed 3 clocks to be combined with hact_en
// wire hact_outp;// hact delayed 5 clocks combined with hact_en to control writing to SDRAM
// reg hact_out; // hact delayed 6 clocks
// wire en_out; // en delayed 5 clocks
// increased latency
wire hact_outp;// hact delayed 6 clocks combined with hact_en to control writing to SDRAM
reg hact_out; // hact delayed 7 clocks
wire en_out; // en delayed 6 clocks
reg [ 9:0] ra;
reg [ 9:0] wa;
reg dwe;
wire incbra; // increment read bank (ra[7])
wire incbwa; // increment read bank (wa[7])
reg rpage;
reg wpage;
reg [ 9:0] testdata;
reg [21:0] thresh;
reg [22:0] sumpix;
reg trig_sel;
reg testmode;
reg [ 2:0] submode;
reg [ 2:0] mpymode;
reg wdth;
// reg [ 2:0] shft;
reg trig;
// wire hact_m= hact && en;
reg hact_m;
reg [3:0] hact_d; /// combine sevaral dealys?
// reg hact_d0;
wire [9:0] ta;
wire twce;
reg [15:0] dsat; //saturated 16-bit corrected data - input to "curves"
reg [15:0] dsat_d; //
// reg [ 7:0] dsat_r; // delayed LSBs of dsat
reg [15:0] pd_lenscorr_in; //data input to lens flat field correction (after dsat
wire [15:0] pd_lenscorr_out; //data after lens flat fiel correction
reg [ 7:0] pd_lenscorr_out_d; // delayed LSBs of pd_lenscorr_out
reg en_d;
/*
.fstart(), // frame start - single clock (will have frame latency as coefficients are written after the fstart)
.newline(), // start of scan line - ahead of linerun
.linerun(), // active pixel output - latency will be = *** TBD
*/
wire [7:0] cdata; //8-bit pixel data after "curves"
// modified table data to increase precision. table_base[9:0] is now 10 bits (2 extra).
// The 10-bit interpolation will be rounded to 8 bits at the very last stage
// 8 bit table_diff will be "floating point" with the following format
// now "signed" is 2's complement, was sign, abs() before
wire [7:0] table_diff_w; // 8 msbs it table word - msb - sign (0 plus, 1 - minus), other 7 bits - +/-127 difference to the next value
wire [9:0] table_base_w; // 8 lsbs in the table - base value, will be corrected using table_diff and input data lsbs (2 for now)
wire [35:0] table_mult;
// register decoded memory output
reg [9:0] table_base;
reg [10:0] table_diff;
wire [9:0] interp_data;
//
reg wfpn;
reg wthrsh;
reg twce_d;
reg [15:0] wdd;
// wire wfpn = pre_wfpn;
// wire wthrsh = pre_wthrsh;
// reg hact_d; //delayed by 1 pclk
reg bayer_nset; // set color to bayer (start of frame up to first hact)when zero
wire sync_bayer; // at the beginning of the line - sync color to bayer
reg [1:0] color; // for selecting page in a gamma table
reg bayer0_latched; // latch bayer[0] at the beginning of first line
// adding latency (to increase sensor clock frequency) after multiplier.
// delaying table_mult[17:7], table_base [9:0] and pd_corr_r2[16:1]
// also SDRAM control outputs
reg [17:7] table_mult_r;
reg [ 9:0] table_base_r;
// reg [16:1] pd_corr_r3;
// input vacts_sclk;
//twce_d
FDE_1 i_table_page (.C(sclk), .CE(vacts_sclk), .D(next_table_page), .Q(table_page));
FDE_1 i_next_table_page (.C(sclk), .CE(twce_d && &ta[9:0]), .D(!table_page), .Q(next_table_page));
// assign sync_bayer=hact_d[0] && ~hact_d[1];
assign sync_bayer=hact_d[1] && ~hact_d[2];
assign interp_data[9:0] = table_base_r[9:0]+table_mult_r[17:8]+table_mult_r[7]; //round
assign cdata[7:0] = interp_data[9:2]; //truncate
always @ (posedge pclk) begin
table_base[9:0] <= table_base_w[9:0];
table_diff[10:0] <= table_diff_w[7]?
{table_diff_w[6:0],4'b0}:
{{4{table_diff_w[6]}},table_diff_w[6:0]};
/// dsat_r[7:0] <= dsat[7:0];
pd_lenscorr_out_d[7:0] <= pd_lenscorr_out[7:0];
table_mult_r[17:7] <= table_mult[17:7];
table_base_r[ 9:0] <= table_base[ 9:0];
end
MULT18X18 i_table_mult (
.P(table_mult), // 36-bit multiplier output
.A({{7{table_diff[10]}},table_diff[10:0]}), // 18-bit multiplier input
.B({10'b0,pd_lenscorr_out_d[7:0]}) // 18-bit multiplier input
);
always @ (negedge sclk) begin
wfpn <= pre_wfpn;
wthrsh <= pre_wthrsh;
twce_d <= twce;
if (pre_wfpn || pre_wthrsh || twce) wdd[15:0]<= wd[15:0];
end
always @ (negedge sclk) if (wfpn) begin
testmode <= wdd[10];
submode[2:0] <= wdd[9:7];
mpymode[2:0] <= wdd[6:4];
wdth <= wdd[3];
end
always @ (negedge sclk) if (wthrsh) thresh[21:0] <= {wd[5:0],wdd[15:0]};
always @ (posedge pclk) begin
hact_m <= hact && en;
en_d <= en;
hact_d[3:0] <= {hact_d[2:0],hact};
// hact_d0<=hact;
// hact_d<=hact_d0;
bayer_nset <= en && (bayer_nset || hact);
bayer0_latched <= bayer_nset? bayer0_latched:bayer[0];
// color[1:0] <= { en? ((hact_d0 && ~hact_d)^color[1]):bayer[1] ,
// (en &&(hact_d || ~hact_d0))?~color[0]:bayer[0] }; // adjust here correct phase
color[1:0] <= { bayer_nset? (sync_bayer ^ color[1]):bayer[1] ,
(bayer_nset &&(~sync_bayer))?~color[0]:bayer0_latched };
end
always @ (posedge pclk)
if (!hact_d[0]) testdata[9:0] <= 10'b0;
else testdata[9:0] <= testdata[9:0]+1;
always @ (posedge pclk) //fsc is left 13 bits
case (mpymode[2:0])
3'b000 : fsc[12:0] <= 13'h1000; // 0x1000
3'b001 : fsc[12:0] <= {~di[15], di[15], di[15], di[15], di[15] ,di[15:8]}; // 0xf80..0x107f - +/- 3.125%
3'b010 : fsc[12:0] <= {~di[15], di[15], di[15], di[15], di[15:8], 1'b0}; // 0xf00..0x10fe - +/- 6.25%
3'b011 : fsc[12:0] <= {~di[15], di[15], di[15], di[15:8], 2'b00};
3'b100 : fsc[12:0] <= {~di[15], di[15], di[15:8], 3'b000};
3'b101 : fsc[12:0] <= {~di[15], di[15:8], 4'b0000}; // 0x800..0x17f0 - +/- 50%
3'b110 : fsc[12:0] <= {~di[15], di[15:8], 4'b0000}; // 0x800..0x17f0 - +/- 50%
3'b111 : fsc[12:0] <= {~di[15], di[15:8], 4'b0000}; // 0x800..0x17f0 - +/- 50%
endcase
always @ (posedge pclk) pd_a[15:0] <= testmode? {testdata[9:0],6'b0}: pxd[15:0];
always @ (posedge pclk) fbg[15:0]= {submode[2]?
((submode[0] ||submode[1])?
{di[7:0],4'b0}: // >4
{1'b0,di[7:0],3'b0}): // 4
(submode[1]?
(submode[0]?
{2'b0,di[7:0],2'b0}: // 3
{3'b0,di[7:0],1'b0}): // 2
(submode[0]?
{4'b0,di[7:0]}: // 1
12'b0)), // 0
4'b0};
assign pd_subp[16:0]={1'b0,pd_a[15:0]}-{1'b0,fbg[15:0]};
always @ (posedge pclk) pd_sub[15:0] <= pd_subp[16]? 16'b0: pd_subp[15:0];
assign pd_corrp[28:0]= pd_sub[15:0] * fsc[12:0];
always @ (posedge pclk) pd_corr[16:0] <= pd_corrp[28:12]; // 12 LSBs discarded
SRL16 i_pd_corr_r1 (.Q(pd_corr_r[1]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[1])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r2 (.Q(pd_corr_r[2]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[2])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r3 (.Q(pd_corr_r[3]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[3])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r4 (.Q(pd_corr_r[4]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[4])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r5 (.Q(pd_corr_r[5]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[5])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r6 (.Q(pd_corr_r[6]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[6])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r7 (.Q(pd_corr_r[7]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[7])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r8 (.Q(pd_corr_r[8]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[8])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r9 (.Q(pd_corr_r[9]), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[9])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r10 (.Q(pd_corr_r[10]),.A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[10])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r11 (.Q(pd_corr_r[11]),.A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[11])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r12 (.Q(pd_corr_r[12]),.A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[12])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r13 (.Q(pd_corr_r[13]),.A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[13])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r14 (.Q(pd_corr_r[14]),.A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[14])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r15 (.Q(pd_corr_r[15]),.A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[15])); ///7+1=8 (was 3 before lens correction)
SRL16 i_pd_corr_r16 (.Q(pd_corr_r[16]),.A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(pd_corr[16])); ///7+1=8 (was 3 before lens correction)
always @ (posedge pclk) begin
dsat[15:0] <= pd_corrp[28]?16'hffff:pd_corrp[27:12];
dsat_d[15:0] <= dsat[15:0];
pd_lenscorr_in[15:0] <= dsat_d[15:0]; /// just delay by 1 cycle
///TODO: done. Need to delay pd_corr_r3 by 4 more cycles for lens flat field correction
// Raw data will be 1/2 of the full scale to allow correction to fit in 16-bit range
do[15:0] <= (wdth)? {pd_corr_r[16:1]} : {cdata[7:0],do[15:8]};
end
// assign incbra= (ra[7:0] == 8'hff) || (|ra[7:0] && (~hact_m));
assign incbra= (ra[7:0] == 8'hff) || (|ra[7:0] && (~(hact & en)));
always @ (posedge pclk) begin
rpage <= incbra;
// if (!hact_m) ra[7:0] <= 8'h0;
if (!(hact && en)) ra[7:0] <= 8'h0;
else ra[7:0] <= ra[7:0]+1;
if (!en) ra[9:8] <= 2'h0;
else if (incbra) ra[9:8] <= ra[9:8]+1;
hact_out <= hact_outp;
dwe <= wdth? hact_outp : (!dwe && hact_out);
end
/*
SRL16 i_hact_dly3 (.Q(hact_dly3), .A0(1'b0), .A1(1'b1), .A2(1'b0), .A3(1'b0), .CLK(pclk), .D(hact_m)); // dly=2+1
SRL16 i_en_out (.Q(en_out), .A0(1'b1), .A1(1'b0), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(en)); // dly=5+1
SRL16 i_hact_outp (.Q(hact_outp), .A0(1'b1), .A1(1'b0), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(hact_m)); // dly=5+1
*/
/// NOTE: adding 5 cycles here
SRL16 i_hact_dly3 (.Q(hact_dly3), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(pclk), .D(hact_m)); // dly=2+1+5
SRL16 i_en_out (.Q(en_out), .A0(1'b0), .A1(1'b1), .A2(1'b0), .A3(1'b1), .CLK(pclk), .D(en)); // dly=5+1+5
SRL16 i_hact_outp (.Q(hact_outp), .A0(1'b0), .A1(1'b1), .A2(1'b0), .A3(1'b1), .CLK(pclk), .D(hact_m)); // dly=5+1+5
assign incbwa= (dwe && (wa[7:0]==8'hff)) || (|wa[7:0] && !hact_out);
always @ (posedge pclk) begin
wpage <= incbwa;
if (!hact_out) wa[7:0] <= 8'h0;
else if (dwe) wa[7:0] <= wa[7:0]+1;
if (!en_out) wa[9:8] <= 2'h0;
else if (incbwa) wa[9:8] <= wa[9:8]+1;
end
// disable to save resources - registers will be optimized out
/**/
always @ (posedge pclk) if (!hact_dly3) sumpix[22:0] <={1'b0,~thresh[21:0]};
else sumpix[22:0] <=sumpix[22:0]+pd_corr[16:6]; // preserve for now
always @ (posedge pclk) trig_sel <= (|thresh[21:0]);
always @ (posedge pclk) trig <= trig_sel && sumpix[22];
/**/
//next_table_page
RAMB16_S9_S9 i_cstableh (
.DOA({table_diff_w[6:0],table_base_w[9]}),// Port A 8-bit Data Output
.DOPA(table_diff_w[7]), // Port A 8-bit Parity Output
.ADDRA({table_page,color[1:0],pd_lenscorr_out[15:8]}), // Port A 11-bit Address Input
.CLKA(pclk), // Port A Clock
.DIA(8'b0), // Port A 8-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.ENA(1'b1), //(change to en???) // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.DOB(), // Port B 8bit Data Output
.DOPB(), // Port B 1-bit Parity Output
.ADDRB({~table_page,ta[9:0]}), // Port B 11-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB({wd[0],wdd[15:9]}), // Port B 8-bit Data Input
.DIPB(wd[1]), // Port-B 1-bit parity Input
.ENB(twce_d), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b1) // Port B Write Enable Input
);
RAMB16_S9_S9 i_cstablel (
.DOA(table_base_w[7:0]), // Port A 8-bit Data Output
.DOPA(table_base_w[8]), // Port A 8-bit Parity Output
.ADDRA({table_page,color[1:0],pd_lenscorr_out[15:8]}), // Port A 11-bit Address Input
.CLKA(pclk), // Port A Clock
.DIA(8'b0), // Port A 8-bit Data Input
.DIPA(1'b0), // Port A 1-bit parity Input
.ENA(1'b1), //(change to en???) // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b0), // Port A Write Enable Input
.DOB(), // Port B 8-bit Data Output
.DOPB(), // Port B 1-bit Parity Output
.ADDRB({~table_page,ta[9:0]}), // Port B 11-bit Address Input
.CLKB(!sclk), // Port B Clock
.DIB(wdd[7:0]), // Port B 8-bit Data Input
.DIPB(wdd[8]), // Port-B 1-bit parity Input
.ENB(twce_d), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b1) // Port B Write Enable Input
);
lens_flat i_lens_flat(.sclk(sclk), /// system clock @negedge
.wen(we_lensff), /// write LSW from di
.di(wd[15:0]), /// [15:0] data in
.pclk(pclk), /// pixel clock (@pclk)
.fstart(en && !en_d), /// frame start - single clock (will have frame latency as coefficients are written after the fstart)
.newline(hact & ~hact_d[0]), /// start of scan line - ahead of linerun
.linerun(hact_d[1]), /// active pixel output - latency will be = 3 clocks
.bayer(bayer[1:0]),
.pixdi(pd_lenscorr_in[15:0]), /// pixel data in,16 bit (normal data is positive, 15 bits)
.pixdo(pd_lenscorr_out[15:0]) /// pixel data out, same format as input
);
endmodule
/*
** -----------------------------------------------------------------------------**
** sensortrig.v
**
** Synchronization/triggering controller for sensor readout
**dsat
** Copyright (C) 2002-2008 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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 sensortrig (pclk,
sclk, // global
wlin, // decoded address, write last line # in frame (since trigger in external trigger mode)
wcmd, // decoded address, write command from d[3:0]:
// now wcmd, d[28:16] - number of lines to delay frame syn interrupt
// d[3] - 0 skip lines, 1 - skip frames
// d[2] - enable
// d[1] - external (0 - internal)
// d[0] - continuous
framesync_dly, // write frame sync (vacts_out) delay in lines
d, // [31:0][11:0] data in
compressed_frames, // [7:0] - bitmask of frames to compress (generate vacts15)
frame_num, // [2:0] current frame number (switches after vacts_sclk)
trig, // external trigger, 0->1 transition
hact, // hact (line active)
vacts_in, // single-cycle frame sync
vacts_out, // single-cycle frame sync (divided if needed in photofinish mode)
vacts15, // pulse from vacts active for 15 scan lines
sensor_en, // enable sensor output
trig_v, // [13:0] line number when trigger occured
trig_h, // [13:0] pixel number when trigger occured
status, // [2:0]: 00 - off, 01 - waiting for vacts to start, 10 - frame active, 11 - frame over
frame_run, // active while frame is being acquired (include all line_run)
xfer_over_irq, // pulse after transfer of specified number of lines (after trigger)
trig_irq, // single-cycle (pclk) pulse after external trigger
fillfactory, // fillfactory sensor mode
ystart, // start of frame (fillfactory sensor mode) - 3 cycles long;
yclock // start of line (fillfactory sensor mode) - 1 cycle long;
);
input pclk;
input sclk;
input wlin;
input wcmd;
input [15:0] d;
input [ 7:0] compressed_frames; //[7:0] - bitmask of frames to compress (generate vacts15)
input [ 2:0] frame_num;
input framesync_dly; // write frame sync (vacts_out) delay in lines
input trig;
input hact;
input vacts_in;
output vacts_out;
output vacts15;
output sensor_en;
output [13:0] trig_v;
output [13:0] trig_h; // can be 12'h800
output [2:0] status; // modify, MSB - "done"
output frame_run;
output xfer_over_irq;
output trig_irq;
input fillfactory; // fillfactory sensor mode
output ystart; // start of frame (fillfactory sensor mode) - 3 cycles long;
output yclock; // start of line (fillfactory sensor mode) - 1 cycle long;
wire fillfactory; // fillfactory sensor mode
reg ystart; // start of frame (fillfactory sensor mode) - 3 cycles long;
wire yclock; // start of line (fillfactory sensor mode) - 1 cycle long;
wire sensor_en;
wire [2:0] status;
reg [1:0] hact_dly;
reg nxt_line;
reg nxt_line1; // delayed
wire nxt_lf; // next line/frame (depending on cmd[3]
wire state1, // waiting vacts
state2, // got vacts, (==hact_en)
state3; // got external trigger (does not turn off state2)
wire trig0, // sync to trig
trig1, // first registered to pclk (not used by itself)
trig2; // registered by pclk, latency 2
wire start0, // sync to wclk
start1, // 1-st registered by pclk
start; // 2-nd registered by pclk
wire [3:0] cmd; // command register, written @wclk (wcmd=1'b1)
reg [13:0] nlines; // lines to acquire
reg [13:0] vact_dly; //delay vact irq by this number of lines
reg [13:0] vact_dly_cntr;
reg [13:0] trig_v;
reg [13:0] trig_h; // can be 12'h800
reg [13:0] lines_left;
wire xfer_over;
reg xfer_over_irq;
reg done;
wire sync_wr,sync_wr0,sync_wr1; // writing nlines in ff mode;
reg frame_run;
reg pre_vacts_out; //at the beginning of the frame
reg pre_vacts_out_d; // delayed by some 1 pre_vacts_out
reg vacts_out; // delayed by some lines (0 - next cycle after pre_vacts_out_d)
reg vacts_dly_on; // from pre_vacts till vacts;
wire wlin_pclks0;
reg [ 1:0] wlin_pclks;
reg [13:0] nff; // photofinish mode - number of sensor frames in one "frame"
reg [13:0] ff_count; // frame in frame counter
wire ff_count_eq0;
reg [3:0] vacts15_cntr;
reg vacts15;
reg set_lines_left;
assign yclock=nxt_line;
assign nxt_lf=(cmd[3])? pre_vacts_out: nxt_line; // next line/frame (depending on cmd[3]
reg en_vacts15_sclk,en_vacts15;
reg [7:0] frame_num_1shot;
always @ (negedge sclk) begin
frame_num_1shot <={frame_num[2:0]==3'h7,
frame_num[2:0]==3'h6,
frame_num[2:0]==3'h5,
frame_num[2:0]==3'h4,
frame_num[2:0]==3'h3,
frame_num[2:0]==3'h2,
frame_num[2:0]==3'h1,
frame_num[2:0]==3'h0};
en_vacts15_sclk <= | (frame_num_1shot[7:0] & compressed_frames[7:0]);
end
assign ff_count_eq0= (ff_count[13:0]==14'h0);
FDCE_1 i_wlin_pclks0 (.C(sclk),.CE(wlin),.CLR(wlin_pclks[1]), .D(1'b1), .Q(wlin_pclks0));
always @ (posedge pclk) begin
en_vacts15 <= en_vacts15_sclk;
wlin_pclks[1:0] <= {wlin_pclks[0] && !wlin_pclks[1], wlin_pclks0};
if (wlin_pclks[1] || (nff[13:0] == 14'h0) || (ff_count_eq0 && vacts_in)) ff_count[13:0] <= nff[13:0];
else if (vacts_in) ff_count[13:0] <= ff_count[13:0]-1;
pre_vacts_out <= vacts_in && ff_count_eq0;
pre_vacts_out_d <= pre_vacts_out;
if (pre_vacts_out) vact_dly_cntr[13:0] <= vact_dly[13:0];
else if (nxt_line && vacts_dly_on) vact_dly_cntr[13:0] <= vact_dly_cntr[13:0] -1 ;
if (pre_vacts_out) vacts_dly_on <= 1'b1;
else if (vacts_out) vacts_dly_on <= 1'b0;
vacts_out <= !vacts_out && vacts_dly_on &&
((pre_vacts_out_d && (vact_dly[13:0]==14'h0)) ||
(nxt_line && (vact_dly_cntr[13:0]==14'h0)));
// generate vacts15 - vacts_out delayed by 15 scan lines (before compressor could start)
if (vacts_out) vacts15_cntr[3:0] <= 4'hf;
else if (nxt_line && vacts15) vacts15_cntr[3:0] <= vacts15_cntr[3:0] -1 ;
if (vacts_out) vacts15 <= en_vacts15;
else if (nxt_line && (vacts15_cntr[3:0] ==4'h0)) vacts15 <= 1'b0 ;
end
FDE_1 i_cmd_0 (.C(sclk), .CE(wcmd), .D(d[0]), .Q(cmd[0]));
FDE_1 i_cmd_1 (.C(sclk), .CE(wcmd), .D(d[1]), .Q(cmd[1]));
FDE_1 i_cmd_2 (.C(sclk), .CE(wcmd), .D(d[2]), .Q(cmd[2]));
FDE_1 i_cmd_3 (.C(sclk), .CE(wcmd), .D(d[3]), .Q(cmd[3]));
always @ (negedge sclk) if (framesync_dly) vact_dly[13:0] <= d[13:0];
// write command synchronization
FDC_1 i_start0 (.C(sclk),.CLR(start), .D(start0 || wcmd), .Q(start0));
FDC i_start1 (.C(pclk), .CLR(start), .D(start0), .Q(start1));
FD i_start (.C(pclk), .D(start1), .Q(start ));
// write wlin synchronization
FDC_1 i_sync_wr0 (.C(sclk), .CLR(sync_wr), .D(sync_wr0 || (wlin && fillfactory)), .Q(sync_wr0));
FDC i_sync_wr1 (.C(pclk), .CLR(sync_wr), .D(sync_wr0), .Q(sync_wr1));
FD i_sync_wr (.C(pclk), .D(sync_wr1), .Q(sync_wr ));
// external trigger synchronization
// warnings for combinatorial input for trig ++++++++++++++++++++
FDC i_trig0 (.C(trig),.CLR(trig2 || !state2 || state3), .D(state2 && !state3 && cmd[1]),.Q(trig0));
FDC i_trig1 (.C(pclk), .CLR(trig2), .D(trig0), .Q(trig1));
FD i_trig2 (.C(pclk), .D(trig1), .Q(trig2));
// state transitions (state3 and state2 are NOT mutually exclusive)
FD i_state1 (.C(pclk), .D(cmd[2] && (state1? (!pre_vacts_out) : ((xfer_over && cmd[0]) || (start && !state2)))), .Q(state1));
FD i_state2 (.C(pclk), .D(cmd[2] && (state2? (!xfer_over) : (state1 && pre_vacts_out))), .Q(state2));
FD i_state3 (.C(pclk), .D(cmd[2] && (state3? (!xfer_over) : ((state1 && pre_vacts_out && !cmd[1]) || trig2))), .Q(state3));
always @ (negedge sclk) if (wlin && !d[14]) begin ///(d[14]==1) - write number of pixels in a line
if (d[15]) nff[13:0] <= d[13:0];
else nlines[13:0] <= d[13:0];
end
assign sensor_en=state2;
always @ (posedge pclk) begin
frame_run <= state2 && !state3;
hact_dly[1:0] <= {hact_dly[0],hact};
nxt_line <= (hact_dly[1] && !hact_dly[0]) || (fillfactory && ystart && !nxt_line && !nxt_line1);
// nxt_line1 <= nxt_line;
nxt_line1 <= yclock;
// sync_wr_d1 <= sync_wr;
// sync_wr_d2 <= sync_wr_d1;
ystart <= (((hact_dly[0] && !hact && (lines_left[13:0]==14'b1)) || sync_wr) || ystart) && !nxt_line1 && fillfactory; // 3 cycles long
// count_h[11:0] <= hact_dly[1]? (count_h[11:0]+(!state3)):12'b0; // will stop counting
end
always @ (posedge pclk)
if (pre_vacts_out && state1) trig_v[13:0] <= 14'b0;
else if (nxt_line && state2 && !state3 && !trig2) trig_v[13:0] <= trig_v[13:0]+1;
always @ (posedge pclk) if (state2 && !state3 && !trig2) begin
if (!hact_dly[1]) trig_h[13:0] <= 14'b0;
else trig_h[13:0] <= trig_h[13:0]+1;
end
always @ (posedge pclk)
set_lines_left <= state1 || (set_lines_left && !hact);
always @ (posedge pclk)
// if (fillfactory?(sync_wr || ((lines_left[13:0]==14'b0) && hact_dly[1] && !hact_dly[0])):state1) lines_left[13:0] <= nlines[13:0];
if (fillfactory?(sync_wr || ((lines_left[13:0]==14'b0) && hact_dly[1] && !hact_dly[0])):set_lines_left) lines_left[13:0] <= nlines[13:0];
else if (fillfactory ? nxt_line : (nxt_lf && (state3 || trig2))) lines_left[13:0] <= lines_left[13:0]-1;
// assign xfer_over=state3 && (lines_left[13:0]==14'h001) && nxt_lf;
assign xfer_over=state3 && (((lines_left[13:0]==14'h001) && nxt_lf) ||
(vacts_in && ff_count_eq0)); // abort input frame at the (next) frame sync
//vacts_in && ff_count_eq0
always @ (posedge pclk) xfer_over_irq <= xfer_over;
always @ (posedge pclk) done <= !start && (done || xfer_over);
assign status[2:0]= {done,state2,state1 || state3};
assign trig_irq=trig2;
// assign hact_en=state2;
endmodule
/*
** -----------------------------------------------------------------------------**
** stuffer333.v
**etrax_dma
** Bit stuffer for JPEG encoder
**
** Copyright (C) 2002-2010 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
`define debug_compressor
// 08.27.2005 - modified "rdy" - moved register to make it faster.
// 01.22.2004 - fixed bug if flush comes with !rdy (required mod of huffman.v to extend "flush" until ready)
// 02.05.2004 - modified data length output. It is 24 it ow, in bytes and is output as last 4 bytes in the
// data block that is 32-byte DMA page aligned
// running on v8.2i - does not meet constraints with enabled global USE_SYNC_SET yes/auto because set input is slower. Trying to selectively disable it
// synthesis attribute use_sync_set of stuffer is no;
// synthesis attribute use_sync_reset of stuffer is no;
// synthesis attribute use_clock_enable of stuffer is no;
module stuffer (clk, //clock
en, // enable, 0- reset
reset_data_counters, // reset data transfer counters (only when DMA and compressor are disabled)
flush, // flush output data (fill byte with 0, long word with 0
stb, // input data strobe
dl, // [3:0] number of bits to send (0 - 16)
d, // [15:0] input data to shift (only lower bits are valid)
// time stamping - will copy time at the end of color_first (later than the first hact after vact in the current froma, but before the next one
// and before the data is needed for output
color_first, //
sec, // [31:0] number of seconds
usec, // [19:0] number of microseconds
rdy, // enable huffman encoder to proceed. Used as CE for many huffman encoder registers
q, // [15:0] output data
qv, // output data valid
done,// reset by !en, goes high after some delay after flushing
imgptr, // [23:0]image pointer in 32-byte chunks
flushing
`ifdef debug_stuffer
,etrax_dma_r, // [3:0] just for testing
test_cntr,
test_cntr1
`endif
);
input clk;
input en;
input reset_data_counters; // reset data transfer counters (only when DMA and compressor are disabled)
input flush;
input stb;
input [ 3:0] dl;
input [15:0] d;
input color_first; //
input [31:0] sec; // sync to pclk at first hact after vact
input [19:0] usec;
output rdy;
output [15:0] q;
output qv;
output done;
output [23:0] imgptr;
output flushing;
`ifdef debug_stuffer
output [3:0] etrax_dma_r; // just for testing
output [3:0] test_cntr; // just for testing
output [7:0] test_cntr1; // just for testing
reg [3:0] etrax_dma_r; // just for testing
reg [3:0] test_cntr; // just for testing
reg [7:0] test_cntr1; // just for testing
reg en_d;
`endif
wire rdy; // can only go low while flushing and inserting 00 after ff
// reg rdy_reg;
// wire inc8; // increment bit counter by 8 after inserting 00 after ff TBD
reg [23:1] stage1; // stage 1 register (after right-shifting input data by 0..7 - actually left by 7..0)
wire [2:0] shift1; // shift amount for stage 1
reg [4:0] stage1_bits; // number of topmost invalid bits in stage1 register - 2 MSBs, use lower 3 stage2_bits
reg [4:0] stage1_length; // number of bits (1..16) in stage 1 register
reg flushing;
wire flush_end;
reg stage1_full;
wire [7:0] byteMask;
wire [31:1] longMask;
wire [31:1] dflt_stage2;
wire [ 2:0] sel;
wire [ 1:0] st2m;
wire [31:1] st2_d;
reg [31:1] stage2;
reg [ 4:0] stage2_bits;
wire send8h, send8l, send8;
reg [15:0] q;
reg qv;
reg flush_end_delayed; // update: fixed delay some delay after flush_end to ensure combining with output FIFO empty
wire pre_flush_end_delayed; // some delay after flush_end to ensure combining with output FIFO empty
wire done;
reg [23:0] size_count; //(now will be byte count)
// to make it faster - split in parts
reg inc_size_count2316;
reg [ 2:0] size_out;
reg size_out_over; // only needed with extra 32 bytes of zeroes added.
reg busy_eob; // flushing and sending length
reg trailer, was_trailer; // sending out data length and 32 bytes for ETRAX
reg [ 3:0] etrax_dma; // count words to make total size multiple of 32 bytes.
// Last 4 bytes of data will have actual length in bytes
// There will always be at least 4 more bytes (0-es) before length - needed for software
reg will_flush; // next dv will be flushing byte/word
wire flush_now;
wire start_sizeout; //delay by 2 cycles
reg send8h_r, send8l_r;
wire pre_stage2_bits_3; // what will be registered to stage2_bits[3];
wire [4:3] willbe_stage1_bits;
wire [3:0] sum_lengths;
reg [1:0] st2m_r;
reg [2:0] stb_time;
reg [31:0] sec_r;
reg [19:0] usec_r;
reg time_out;
reg time_size_out;
wire start_time_out;
// stb_time[2] - single-cycle pulse after color_first goes low
reg [23:0] imgptr; //updated after each frame compressed (points to start of next frame)
reg [19:0] imgsz32; // current image size in multiples of 32-bytes
reg inc_imgsz32;
always @ (negedge clk) flushing <= en && !flush_end && ((flush && rdy) || flushing);
wire [4:0] pre_stage1_bits;
assign pre_stage1_bits[4:0]={2'b00,stage1_bits[2:0]} + {(dl[3:0]==4'b0),dl[3:0]};
always @ (negedge clk) begin
if (!en || flush_end) stage1_bits[4:0] <= 5'b0;
else if (stb && rdy) stage1_bits <= {(2'b10-pre_stage1_bits[4:3]),pre_stage1_bits[2:0]};
end
assign shift1[2:0]= stage1_bits[2:0] + dl[2:0];
always @ (negedge clk) if (stb && rdy) begin
case (shift1[2:0])
0: stage1[23:1] <= { d[15:0],7'b0};
1: stage1[23:1] <= {1'b0,d[15:0],6'b0};
2: stage1[23:1] <= {2'b0,d[15:0],5'b0};
3: stage1[23:1] <= {3'b0,d[15:0],4'b0};
4: stage1[23:1] <= {4'b0,d[15:0],3'b0};
5: stage1[23:1] <= {5'b0,d[15:0],2'b0};
6: stage1[23:1] <= {6'b0,d[15:0],1'b0};
7: stage1[23:1] <= {7'b0,d[15:0] };
endcase
stage1_length[4:0] <= {(dl[3:0]==4'b0),dl[3:0]};
end
//*****************************
always @ (negedge clk) begin
if (!en) stage2_bits <= 5'b0;
else if (send8) stage2_bits[4:0] <= stage2_bits[4:0] - 8;
else if (flushing && !stage1_full && !stage2_bits[4] && (stage2_bits[3:0]!=4'b0)) stage2_bits[4:0]<=5'h10; // actual flushing to word size
else stage2_bits[4:0] <= (rdy && stage1_full)? {1'b0,stage2_bits[3:0]}+stage1_length[4:0]:{1'b0,stage2_bits[3:0]};
end
assign sum_lengths=stage2_bits[3:0]+stage1_length[3:0];
assign pre_stage2_bits_3= en &&
(send8? (~stage2_bits[3]): (
!(flushing && !stage1_full && !stage2_bits[4] && (stage2_bits[3:0]!=4'b0)) && // not flushing
((rdy && stage1_full)?sum_lengths[3]: stage2_bits[3] )
));
assign willbe_stage1_bits[4:3]={2{en && !flush_end}} & ((stb && rdy)?(2'b10-pre_stage1_bits[4:3]):stage1_bits[4:3]);
// assign rdy =(!stage2_bits[4] || (!send8h_r && !send8l_r)) && !busy_eob;
// accelerating rdy calculation - making it a register
wire pre_busy_eob=en && !flush_end_delayed && (busy_eob || (flush && rdy));
wire [4:3] pre_stage2_bits_4_interm1=stage2_bits[4:3]-2'h1;
wire [4:0] pre_stage2_bits_4_interm2={1'b0,stage2_bits[3:0]}+stage1_length[4:0];
wire pre_stage2_bits_4=en && (send8?
(pre_stage2_bits_4_interm1[4]):
((flushing && !stage1_full && !stage2_bits[4] && (stage2_bits[3:0]!=4'b0))?
(1'b1):
(((rdy && stage1_full))?
(pre_stage2_bits_4_interm2[4]):
(1'b0)
)
)
);
// if ( send8h_r && stage2_bits[4]) send8h_r <= &stage2[23:16];
// else if (!send8l_r || !stage2_bits[4]) send8h_r <= &((longMask[31:24] & st2_d[31:24]) | (~longMask[31:24] & dflt_stage2[31:24]));
wire pre_send8h_r= (( send8h_r && stage2_bits[4])?
(&stage2[23:16]):
((!send8l_r || !stage2_bits[4])?
(&((longMask[31:24] & st2_d[31:24]) | (~longMask[31:24] & dflt_stage2[31:24]))):
(send8h_r)
)
);
// if (( send8h_r || send8l_r) && stage2_bits[4]) send8l_r <= &stage2[15:8];
// else send8l_r <= &((longMask[23:16] & st2_d[23:16]) | (~longMask[23:16] & dflt_stage2[23:16]));
wire pre_send8l_r= ((( send8h_r || send8l_r) && stage2_bits[4] )?
(&stage2[15:8]):
(&((longMask[23:16] & st2_d[23:16]) | (~longMask[23:16] & dflt_stage2[23:16])))
);
// assign rdy =(!stage2_bits[4] || (!send8h_r && !send8l_r)) && !busy_eob;
//Trying to delay rdy to make more room before it
reg rdy_rega,rdy_regb, rdy_regc, rdy_regd;
// s ynthesis attribute use_sync_set of {module_name|signal_name|instance_name} [is] no;
always @ (negedge clk) begin
// rdy_reg <= (!pre_stage2_bits_4 || (!pre_send8h_r && !pre_send8l_r)) && !pre_busy_eob;
rdy_rega <= !pre_stage2_bits_4;
rdy_regb <= !pre_send8h_r;
rdy_regc <= !pre_send8l_r;
rdy_regd <= !pre_busy_eob;
busy_eob <= pre_busy_eob;
//**********************************
send8h_r<=pre_send8h_r;
send8l_r<=pre_send8l_r;
end
// assign rdy = rdy_reg;
assign rdy = (rdy_rega || (rdy_regb && rdy_regc)) && rdy_regd;
assign send8h= send8h_r && stage2_bits[4];
assign send8l= send8l_r && stage2_bits[4];
assign send8=stage2_bits[4] && (send8h_r || send8l_r);
always @ (negedge clk) begin
if (!en) stage1_full <= 1'b0;
/// else if (rdy) stage1_full <=stb;
/* TODO: MAke sure it is OK !! 05/12/2010 */
// else if (rdy) stage1_full <=stb && !flushing; //force flush does not turn off stb, in normal operation flushing is after last stb
else if (flushing) stage1_full <= 1'b0; //force flush does not turn off stb, in normal operation flushing is after last stb
else if (rdy) stage1_full <=stb; //force flush does not turn off stb, in normal operation flushing is after last stb
end
assign sel[2:0]=stage2_bits[2:0];
assign byteMask[7:0]= {!sel[2] && !sel[1] && !sel[0],
!sel[2] && !sel[1],
!sel[2] && (!sel[1] || !sel[0]),
!sel[2],
!sel[2] || (!sel[1] && !sel[0]),
!sel[2] || !sel[1],
!sel[2] || !sel[1] || !sel[0],
1'b1
};
//TODO: Try to move stage1_full up here, this is the time-limiting path 05.26.2010
assign longMask[31:1]={{8{(flushing || stage1_full) && !stage2_bits[3]}} & byteMask[7:0],
{8{flushing || stage1_full}} & ({8{!stage2_bits[3]}} | byteMask[7:0]),
{8{stage1_full}},
{7{stage1_full}}};
always @ (negedge clk) st2m_r[1:0]<=willbe_stage1_bits[4:3]-{1'b0,pre_stage2_bits_3};
assign st2m[1:0]=st2m_r[1:0];
assign st2_d[31:1]= {{8{!flushing || stage1_full}} & (st2m[1]?{stage1[7:1],1'b0}:(st2m[0]? stage1[15:8]: stage1[23:16])),
{8{!flushing || stage1_full}} & (st2m[1]? stage1[23:16]: (st2m[0]?{stage1[7:1],1'b0}:stage1[15: 8])),
st2m[1]? stage1[15: 8]: {stage1[7:1],1'b0},
{stage1[7:1]}};
assign dflt_stage2=stage2_bits[4]?{stage2[15:1],16'b0}:{stage2[31:1]};
always @ (negedge clk) begin
if (send8h) stage2[31:24] <= stage2[23:16];
else if (send8l) stage2[31:24] <= 8'h00;
else stage2[31:24] <= (longMask[31:24] & st2_d[31:24]) | (~longMask[31:24] & dflt_stage2[31:24]);
if (send8) stage2[23:16] <= stage2[15:8];
else stage2[23:16] <= (longMask[23:16] & st2_d[23:16]) | (~longMask[23:16] & dflt_stage2[23:16]);
if (send8) stage2[15: 8] <= {stage2[7:1],1'b0};
else stage2[15: 8] <= (longMask[15: 8] & st2_d[15: 8]) | (~longMask[15: 8] & dflt_stage2[15: 8]);
if (send8) stage2[7: 1] <= 7'b0;
else stage2[7: 1] <= (longMask[7: 1] & st2_d[7: 1]) | (~longMask[7: 1] & dflt_stage2[7: 1]);
end
// output stage
assign flush_end= !stage2_bits[4] && flushing && !stage1_full && (stage2_bits[3:0]==4'b0);
assign flush_now= en && (!send8) && (flushing && !stage1_full && !stage2_bits[4]) && !will_flush;
always @ (negedge clk) begin
stb_time[2:0] <= {stb_time[1] & ~stb_time[0], stb_time[0],color_first};
if (stb_time[2]) sec_r[31:0] <= sec[31:0];
else if (start_sizeout) sec_r[31:0] <= {8'hff, size_count[23:0]};
else if (time_size_out) sec_r[31:0] <= {usec_r[15:0],sec_r[31:16]};
if (stb_time[2]) usec_r[19:0] <= usec[19:0];
else if (time_out) usec_r[19:0] <= {16'h0,usec_r[19:16]};
//reset_data_counters; // reset data transfer counters (only when DMA and compressor are disabled)
// if (!en ) etrax_dma[3:0] <= 0; // not needed to be reset after frame, and that was wrong (to early)
if (reset_data_counters ) etrax_dma[3:0] <= 0; // not needed to be reset after frame, and that was wrong (to early)
else if (qv) etrax_dma[3:0] <= etrax_dma[3:0] + 1;
// just for testing
`ifdef debug_stuffer
reg [3:0] tst_done_dly;
en_d<= en;
if (en) etrax_dma_r[3:0] <= etrax_dma[3:0];
// if (en && ! en_d) test_cntr[3:0] <= test_cntr[3:0]+1;
if (done) test_cntr1[7:0] <= 0;
else if (qv) test_cntr1[7:0] <= test_cntr1[7:0] +1 ; // normally should be one (done 1 ahead of end of qv)
tst_done_dly[3:0] <= {tst_done_dly[2:0],done};
if (tst_done_dly[1]) test_cntr[3:0] <= 0;
else if (qv) test_cntr[3:0] <= test_cntr[3:0] +1 ;
`endif
size_out_over <= en && (size_out_over?(!done):size_out[0]);
size_out[2:0]<={size_out[1:0],start_sizeout};
// time_out <= en && (start_time_out || (time_out && !(etrax_dma[3:0]== 4'hc)));
// time_size_out <= en && (start_time_out || (time_out && !(etrax_dma[3:0]== 4'he)));
time_out <= en && (start_time_out || (time_out && !(etrax_dma[3:2]== 2'h3)));
time_size_out <= en && (start_time_out || (time_size_out && !(etrax_dma[3:1]== 3'h7)));
trailer <= en && (trailer?(!flush_end_delayed):(flush_end));
was_trailer<=trailer;
will_flush <= en && (will_flush?(!qv):(flush_now && (stage2_bits[3:0]!=4'b0)));
if (flush_now) size_count[0] <= stage2_bits[3] ^ (|stage2_bits[2:0]); // odd number of bytes
if (!en || size_out[2]) size_count[15:1] <= 0;
else if (!trailer && !was_trailer && qv && (!will_flush || !size_count[0])) size_count[15:1] <= size_count[15:1]+1;
inc_size_count2316 <= (!trailer && !was_trailer && qv && (!will_flush || !size_count[0])) && (&size_count[15:1]);
//reset_data_counters instead of !en here?
if (!en || size_out[2]) size_count[23:16] <= 0;
else if (inc_size_count2316) size_count[23:16] <= size_count[23:16]+1;
qv <= en && (stage2_bits[4] || trailer);
// to make it faster (if needed) use a single register as a source for q[15:0] in two following lines
// if (time_out) q[15:0] <= sec_r[15:0];
// else if (|size_out[1:0]) q[15:0] <= size_out[0]?{size_count[7:0],size_count[15:8]}:{size_count[23:16],8'hff};
if (time_size_out) q[15:0] <= {sec_r[7:0],sec_r[15:8]};
// else if (|size_out[1:0]) q[15:0] <= size_out[0]?{size_count[7:0],size_count[15:8]}:{size_count[23:16],8'hff};
else q[15:0] <= {(stage2_bits[4]?stage2[31:24]:8'b0),
((stage2_bits[4] && !send8h)? stage2[23:16]:8'b0)};
inc_imgsz32 <= (etrax_dma[3:0]== 4'h0) && qv;
//reset_data_counters instead of !en here?
// if (!en || done) imgsz32[19:0] <= 0;
if (reset_data_counters || done) imgsz32[19:0] <= 0;
else if (inc_imgsz32) imgsz32[19:0]<=imgsz32[19:0]+1;
// if (!en) imgptr[23:0] <= 0;
if (reset_data_counters) imgptr[23:0] <= 0;
else if (done) imgptr[23:0] <= imgptr[23:0]+ imgsz32[19:0];
flush_end_delayed <= en & pre_flush_end_delayed; // en just to prevent optimizing pre_flush_end_delayed+flush_end_delayed into a single SRL16
end
//start_sizeout
//assign start_sizeout= qv && trailer && (etrax_dma[3:0]== 4'hc) && !size_out_over;
assign start_time_out= qv && trailer && (etrax_dma[3:0]== 4'h8) && !size_out_over;
assign start_sizeout= time_out && (etrax_dma[3:0]== 4'hc);
SRL16_1 i_pre_flush_end_delayed (.D(size_out[1]),.Q(pre_flush_end_delayed), .A0(1'b0), .A1(1'b1), .A2(1'b1), .A3(1'b1), .CLK(clk)); // dly=3+1 // rather arbitrary?
assign done = flush_end_delayed;
endmodule
/*
** -----------------------------------------------------------------------------**
** twelve_ios.v
**
** GPIO control
**
** Copyright (C) 2005-2007 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X353
** X353 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
*/
// update to eliminate need for a shadow register
// each pair of data bits at write cycle control the data and enable in the following way:
// bit 1 bit 0 dibit enable data
// 0 0 0 - no change -
// 0 1 1 1 0
// 1 0 2 1 1
// 1 1 3 0 0
//Unified IO control for the 6 pins that are connected from the FPGA to the inter-board 16-pin connector
// those pins were controlled (in models 303, 313, 323 and earlier 333) by the control register, status was
// read through the status register.
// Now each pin will be controlled by 2 bits (data+enable), total 12 bits that will come from one of 4 sources
// selected by bits [13:12] of the new control word:
// 0 - use bits [11:0] of the control word
// 1 - use channel A (USB)?
// 2 - use channel B (tbd)
// 3 - use channel C (tbd)
// Updating logic
// global enable signals (disabled channel will not compete for per-biot access)
// next 4 enable signals are controlled by bit pairs (0X - don't change, 10 - disable, 11 - enable)
// bit [25:24] - enable software bits (contolled by bits [23:0] (on at powerup)
// bit [27:26] - enable chn. A
// bit [29:28] - enable chn. B
// bit [31:30] - enable chn. C
// Enabled bits will be priority encoded (C - highest, software - lowest)
module twelve_ios (sclk, // @negedge
pre_wen, // 1 cycle ahead of write data
di, // [15:0] data in
io_do, // [5:0] data to I/O pins
io_t, // [5:0] tristate I/O pins
da, // [5:0] data from port A (USB?)
da_en, // [5:0] data enable from port A (USB?)
db, // [5:0] data from port B
db_en, // [5:0] data enable from port B
dc, // [5:0] data from port C
dc_en); // [5:0] data enable from port C
input sclk;
input pre_wen;
input [15:0] di;
output [11:0] io_do;
output [11:0] io_t;
input [11:0] da;
input [11:0] da_en;
input [11:0] db;
input [11:0] db_en;
input [11:0] dc;
input [11:0] dc_en;
// wire [23:0] cr; // control register - reset at powerup
wire [11:0] ds; // "software" data (programmed by lower 24 bits)
wire [11:0] ds_en; // "software" data enable (programmed by lower 24 bits)
wire [ 3:0] ch_en; // channel enable
reg pre_wen_d;
reg cr_wen;
reg [31:0] did; // registered (dealyed by 1 clock) version of di[25:0]
wire [11:0] ds_en_m;
wire [11:0] da_en_m;
wire [11:0] db_en_m;
wire [11:0] dc_en_m;
assign dc_en_m[11:0]= dc_en[11:0] & {12{ch_en[3]}};
assign db_en_m[11:0]= db_en[11:0] & {12{ch_en[2]}} & ~dc_en_m[11:0];
assign da_en_m[11:0]= da_en[11:0] & {12{ch_en[1]}} & ~dc_en_m[11:0] & ~db_en_m[11:0];
assign ds_en_m[11:0]= ds_en[11:0] & {12{ch_en[0]}} & ~dc_en_m[11:0] & ~db_en_m[11:0] & ~da_en_m[11:0];
assign io_do[11:0]=(dc_en_m[11:0] & dc[11:0]) |
(db_en_m[11:0] & db[11:0]) |
(da_en_m[11:0] & da[11:0]) |
(ds_en_m[11:0] & ds[11:0]);
assign io_t[11:0]=~(dc_en_m[11:0] | db_en_m[11:0] | da_en_m[11:0] | ds_en_m[11:0]);
// 0 0 0 - no change -
// 0 1 1 1 0
// 1 0 2 1 1
// 1 1 3 0 0
FDE_1 i_ds_0 (.C(sclk), .CE(cr_wen & (did[ 0] | did[ 1])), .D( ~did[ 0] ), .Q(ds[ 0]));
FDE_1 i_ds_1 (.C(sclk), .CE(cr_wen & (did[ 2] | did[ 3])), .D( ~did[ 2] ), .Q(ds[ 1]));
FDE_1 i_ds_2 (.C(sclk), .CE(cr_wen & (did[ 4] | did[ 5])), .D( ~did[ 4] ), .Q(ds[ 2]));
FDE_1 i_ds_3 (.C(sclk), .CE(cr_wen & (did[ 6] | did[ 7])), .D( ~did[ 6] ), .Q(ds[ 3]));
FDE_1 i_ds_4 (.C(sclk), .CE(cr_wen & (did[ 8] | did[ 9])), .D( ~did[ 8] ), .Q(ds[ 4]));
FDE_1 i_ds_5 (.C(sclk), .CE(cr_wen & (did[10] | did[11])), .D( ~did[10] ), .Q(ds[ 5]));
FDE_1 i_ds_6 (.C(sclk), .CE(cr_wen & (did[12] | did[13])), .D( ~did[12] ), .Q(ds[ 6]));
FDE_1 i_ds_7 (.C(sclk), .CE(cr_wen & (did[14] | did[15])), .D( ~did[14] ), .Q(ds[ 7]));
FDE_1 i_ds_8 (.C(sclk), .CE(cr_wen & (did[16] | did[17])), .D( ~did[16] ), .Q(ds[ 8]));
FDE_1 i_ds_9 (.C(sclk), .CE(cr_wen & (did[18] | did[19])), .D( ~did[18] ), .Q(ds[ 9]));
FDE_1 i_ds_10 (.C(sclk), .CE(cr_wen & (did[20] | did[21])), .D( ~did[20] ), .Q(ds[10]));
FDE_1 i_ds_11 (.C(sclk), .CE(cr_wen & (did[22] | did[23])), .D( ~did[22] ), .Q(ds[11]));
FDE_1 i_ds_en_0 (.C(sclk), .CE(cr_wen & (did[ 0] | did[ 1])), .D(~(did[ 1] & did[ 0])), .Q(ds_en[ 0]));
FDE_1 i_ds_en_1 (.C(sclk), .CE(cr_wen & (did[ 2] | did[ 3])), .D(~(did[ 3] & did[ 2])), .Q(ds_en[ 1]));
FDE_1 i_ds_en_2 (.C(sclk), .CE(cr_wen & (did[ 4] | did[ 5])), .D(~(did[ 5] & did[ 4])), .Q(ds_en[ 2]));
FDE_1 i_ds_en_3 (.C(sclk), .CE(cr_wen & (did[ 6] | did[ 7])), .D(~(did[ 7] & did[ 6])), .Q(ds_en[ 3]));
FDE_1 i_ds_en_4 (.C(sclk), .CE(cr_wen & (did[ 8] | did[ 9])), .D(~(did[ 9] & did[ 8])), .Q(ds_en[ 4]));
FDE_1 i_ds_en_5 (.C(sclk), .CE(cr_wen & (did[10] | did[11])), .D(~(did[11] & did[10])), .Q(ds_en[ 5]));
FDE_1 i_ds_en_6 (.C(sclk), .CE(cr_wen & (did[12] | did[13])), .D(~(did[13] & did[12])), .Q(ds_en[ 6]));
FDE_1 i_ds_en_7 (.C(sclk), .CE(cr_wen & (did[14] | did[15])), .D(~(did[15] & did[14])), .Q(ds_en[ 7]));
FDE_1 i_ds_en_8 (.C(sclk), .CE(cr_wen & (did[16] | did[17])), .D(~(did[17] & did[16])), .Q(ds_en[ 8]));
FDE_1 i_ds_en_9 (.C(sclk), .CE(cr_wen & (did[18] | did[19])), .D(~(did[19] & did[18])), .Q(ds_en[ 9]));
FDE_1 i_ds_en_10 (.C(sclk), .CE(cr_wen & (did[20] | did[21])), .D(~(did[21] & did[20])), .Q(ds_en[10]));
FDE_1 i_ds_en_11 (.C(sclk), .CE(cr_wen & (did[22] | did[23])), .D(~(did[23] & did[22])), .Q(ds_en[11]));
FDE_1 #(.INIT(1'b1)) i_ch_en_0 (.C(sclk), .CE(cr_wen & did[25]), .D(did[24]), .Q(ch_en[ 0]));
FDE_1 #(.INIT(1'b0)) i_ch_en_1 (.C(sclk), .CE(cr_wen & did[27]), .D(did[26]), .Q(ch_en[ 1]));
FDE_1 #(.INIT(1'b0)) i_ch_en_2 (.C(sclk), .CE(cr_wen & did[29]), .D(did[28]), .Q(ch_en[ 2]));
FDE_1 #(.INIT(1'b0)) i_ch_en_3 (.C(sclk), .CE(cr_wen & did[31]), .D(did[30]), .Q(ch_en[ 3]));
always @ (negedge sclk) begin
pre_wen_d <= pre_wen;
cr_wen <=pre_wen_d;
if (pre_wen) did[15: 0] <= di[15:0];
if (pre_wen_d) did[31:16] <= di[15:0];
end
endmodule
Release 10.1.03 par K.39 (lin)
Copyright (c) 1995-2008 Xilinx, Inc. All rights reserved.
inspiron:: Tue Jan 17 20:24:37 2012
par -w -intstyle ise -pl high -rl high -xe n -t 1 -n 5 -s 5 x353_map.ncd
/home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3/mppr_result.dir
x353.pcf
Constraints file: x353.pcf.
"x353" is an NCD, version 3.2, device xc3s1200e, package ft256, speed -4
Initializing temperature to 85.000 Celsius. (default - Range: -40.000 to 100.000 Celsius)
Initializing voltage to 1.140 Volts. (default - Range: 1.140 to 1.320 Volts)
INFO:Timing:3377 - Intersecting Constraints found and resolved. For more information see the TSI report.
Device speed data version: "PRODUCTION 1.27 2008-01-09".
INFO:Par:252 - The Map -timing placement will be discarded and your design will be placed using the command line options
specified in PAR.
Design Summary Report:
Number of External IOBs 142 out of 190 74%
Number of External Input IOBs 35
Number of External Input DIFFMIs 1
Number of LOCed External Input DIFFMIs 1 out of 1 100%
Number of External Input DIFFSIs 1
Number of LOCed External Input DIFFSIs 1 out of 1 100%
Number of External Input IBUFs 33
Number of LOCed External Input IBUFs 33 out of 33 100%
Number of External Output IOBs 37
Number of External Output DIFFMs 1
Number of LOCed External Output DIFFMs 1 out of 1 100%
Number of External Output DIFFSs 1
Number of LOCed External Output DIFFSs 1 out of 1 100%
Number of External Output IOBs 35
Number of LOCed External Output IOBs 35 out of 35 100%
Number of External Bidir IOBs 70
Number of External Bidir IOBs 70
Number of LOCed External Bidir IOBs 70 out of 70 100%
Number of BUFGMUXs 9 out of 24 37%
Number of DCMs 4 out of 8 50%
Number of MULT18X18SIOs 19 out of 28 67%
Number of RAMB16s 22 out of 28 78%
Number of Slices 7247 out of 8672 83%
Number of SLICEMs 460 out of 4336 10%
Overall effort level (-ol): Not applicable because -pl and -rl switches are used
Placer effort level (-pl): High
Placer cost table entry (-t): 2
Router effort level (-rl): High
Extra effort level (-xe): Normal
Starting initial Timing Analysis. REAL time: 25 secs
Finished initial Timing Analysis. REAL time: 25 secs
Starting Placer
Phase 1.1
Phase 1.1 (Checksum:1b71b1e) REAL time: 29 secs
Phase 2.7
Phase 2.7 (Checksum:1b71b1e) REAL time: 29 secs
Phase 3.31
Phase 3.31 (Checksum:1b71b1e) REAL time: 29 secs
Phase 4.2
......
.....................
WARNING:Place:1019 - A clock IOB / clock component pair have been found that are not placed at an optimal clock IOB /
clock site pair. The clock component <i_pclk> is placed at site <BUFGMUX_X1Y11>. The IO component <BPF> is placed at
site <K5>. This will not allow the use of the fast path between the IO and the Clock buffer. This is normally an
ERROR but the CLOCK_DEDICATED_ROUTE constraint was applied on COMP.PIN <BPF.PAD> allowing your design to continue.
This constraint disables all clock placer rules related to the specified COMP.PIN. The use of this override is highly
discouraged as it may lead to very poor timing results. It is recommended that this error condition be corrected in
the design.
Phase 4.2 (Checksum:1b87fb3) REAL time: 34 secs
.....................
..........
Phase 5.30
Phase 5.30 (Checksum:1b87fb3) REAL time: 2 mins 4 secs
Phase 6.8
..................
...............
....
...............
......
.....
....
Phase 6.8 (Checksum:5102912) REAL time: 3 mins 13 secs
Phase 7.5
Phase 7.5 (Checksum:5102912) REAL time: 3 mins 13 secs
Phase 8.18
Phase 8.18 (Checksum:5121dbd) REAL time: 3 mins 36 secs
Phase 9.5
Phase 9.5 (Checksum:5121dbd) REAL time: 3 mins 37 secs
REAL time consumed by placer: 3 mins 39 secs
CPU time consumed by placer: 3 mins 35 secs
Writing design to file /home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3/mppr_result.dir/H_H_2.ncd
Total REAL time to Placer completion: 3 mins 42 secs
Total CPU time to Placer completion: 3 mins 38 secs
Starting Router
Phase 1: 46851 unrouted; REAL time: 3 mins 53 secs
Phase 2: 38596 unrouted; REAL time: 3 mins 55 secs
Phase 3: 12776 unrouted; REAL time: 4 mins 7 secs
Phase 4: 12776 unrouted; (126136) REAL time: 4 mins 7 secs
Phase 5: 12895 unrouted; (6322) REAL time: 4 mins 13 secs
Phase 6: 12937 unrouted; (1612) REAL time: 4 mins 13 secs
Phase 7: 0 unrouted; (3185) REAL time: 4 mins 36 secs
Phase 8: 0 unrouted; (3185) REAL time: 4 mins 45 secs
Updating file: /home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3/mppr_result.dir/H_H_2.ncd with current fully
routed design.
Phase 9: 0 unrouted; (3185) REAL time: 6 mins 29 secs
Phase 10: 0 unrouted; (2970) REAL time: 6 mins 41 secs
Phase 11: 0 unrouted; (2970) REAL time: 6 mins 51 secs
Updating file: /home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3/mppr_result.dir/H_H_2.ncd with current fully
routed design.
Phase 12: 0 unrouted; (2708) REAL time: 8 mins 23 secs
Updating file: /home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3/mppr_result.dir/H_H_2.ncd with current fully
routed design.
Phase 13: 0 unrouted; (2400) REAL time: 10 mins 29 secs
Phase 14: 0 unrouted; (2322) REAL time: 10 mins 40 secs
Phase 15: 0 unrouted; (2285) REAL time: 10 mins 47 secs
Phase 16: 0 unrouted; (1985) REAL time: 10 mins 52 secs
Phase 17: 0 unrouted; (1780) REAL time: 10 mins 57 secs
Phase 18: 0 unrouted; (0) REAL time: 13 mins 12 secs
Phase 19: 0 unrouted; (0) REAL time: 13 mins 14 secs
Phase 20: 0 unrouted; (0) REAL time: 13 mins 25 secs
WARNING:Route - CLK Net:i_compressor/go_single may have excessive skew because 1 CLK pins and 28 NON_CLK pins failed to
route using a CLK template.
WARNING:Route - CLK Net:i_compressor/done_input may have excessive skew because 1 CLK pins and 4 NON_CLK pins failed to
route using a CLK template.
WARNING:Route - CLK Net:i_sensorpads/fifo_clkin is being routed on general routing resources. If you are trying to use
local clocking techniques, evaluate the placement of the clock's source and loads to ensure it meets the guidelines
for local clocking. Otherwise, consider placing this clock on a dedicated clock routing resource. For more
information on clock routing resources, see the target architecture's user guide.
WARNING:Route - CLK Net:compressor_eot may have excessive skew because 1 CLK pins and 1 NON_CLK pins failed to route
using a CLK template.
WARNING:Route - CLK Net:i_sensortrig/done may have excessive skew because 1 CLK pins and 2 NON_CLK pins failed to route
using a CLK template.
WARNING:Route - CLK Net:i_compressor/done_compress may have excessive skew because 1 CLK pins and 2 NON_CLK pins failed
to route using a CLK template.
WARNING:Route - CLK Net:trig_irq may have excessive skew because 1 CLK pins and 8 NON_CLK pins failed to route using a
CLK template.
WARNING:Route - CLK Net:i_sensortrig/vacts_out is being routed on general routing resources. If you are trying to use
local clocking techniques, evaluate the placement of the clock's source and loads to ensure it meets the guidelines
for local clocking. Otherwise, consider placing this clock on a dedicated clock routing resource. For more
information on clock routing resources, see the target architecture's user guide.
Total REAL time to Router completion: 13 mins 27 secs
Total CPU time to Router completion: 13 mins 16 secs
Partition Implementation Status
-------------------------------
No Partitions were found in this design.
-------------------------------
Generating "PAR" statistics.
**************************
Generating Clock Report
**************************
+---------------------+--------------+------+------+------------+-------------+
| Clock Net | Resource |Locked|Fanout|Net Skew(ns)|Max Delay(ns)|
+---------------------+--------------+------+------+------------+-------------+
| xclk | BUFGMUX_X3Y8| No | 2217 | 0.211 | 0.293 |
+---------------------+--------------+------+------+------------+-------------+
| sclk0 | BUFGMUX_X2Y11| No | 3047 | 0.345 | 0.514 |
+---------------------+--------------+------+------+------------+-------------+
| i_sysinterface/cwr | BUFGMUX_X1Y1| No | 54 | 0.202 | 0.377 |
+---------------------+--------------+------+------+------------+-------------+
| pclk2x | BUFGMUX_X1Y0| No | 131 | 0.202 | 0.378 |
+---------------------+--------------+------+------+------------+-------------+
| sclk270 | BUFGMUX_X2Y10| No | 60 | 0.158 | 0.373 |
+---------------------+--------------+------+------+------------+-------------+
|i_sensorpads/i_senso | | | | | |
| r_phase/gclk_idata | BUFGMUX_X0Y9| No | 95 | 0.145 | 0.287 |
+---------------------+--------------+------+------+------------+-------------+
| i_dma_fifo1/swclk | BUFGMUX_X2Y0| No | 7 | 0.035 | 0.277 |
+---------------------+--------------+------+------+------------+-------------+
| pclk | BUFGMUX_X1Y11| No | 916 | 0.209 | 0.379 |
+---------------------+--------------+------+------+------------+-------------+
| i_dma_fifo0/swclk | BUFGMUX_X2Y1| No | 7 | 0.102 | 0.300 |
+---------------------+--------------+------+------+------------+-------------+
|i_compressor/go_sing | | | | | |
| le | Local| | 29 | 0.000 | 1.094 |
+---------------------+--------------+------+------+------------+-------------+
|i_compressor/done_in | | | | | |
| put | Local| | 5 | 0.000 | 1.509 |
+---------------------+--------------+------+------+------------+-------------+
|i_compressor/done_co | | | | | |
| mpress | Local| | 3 | 0.000 | 1.906 |
+---------------------+--------------+------+------+------------+-------------+
|i_sensorpads/fifo_cl | | | | | |
| kin | Local| | 4 | 0.000 | 1.901 |
+---------------------+--------------+------+------+------------+-------------+
| trig_irq | Local| | 9 | 0.000 | 1.956 |
+---------------------+--------------+------+------+------------+-------------+
| i_sensortrig/done | Local| | 3 | 0.000 | 2.825 |
+---------------------+--------------+------+------+------------+-------------+
|i_sensortrig/vacts_o | | | | | |
| ut | Local| | 18 | 1.288 | 3.322 |
+---------------------+--------------+------+------+------------+-------------+
|i_sensortrig/xfer_ov | | | | | |
| er_irq | Local| | 1 | 0.000 | 1.033 |
+---------------------+--------------+------+------+------------+-------------+
| compressor_eot | Local| | 2 | 0.000 | 1.506 |
+---------------------+--------------+------+------+------------+-------------+
| i_irq_smart/irq | Local| | 1 | 0.000 | 1.412 |
+---------------------+--------------+------+------+------------+-------------+
| _mux0002 | Local| | 1 | 0.000 | 0.660 |
+---------------------+--------------+------+------+------------+-------------+
* Net Skew is the difference between the minimum and maximum routing
only delays for the net. Note this is different from Clock Skew which
is reported in TRCE timing report. Clock Skew is the difference between
the minimum and maximum path delays which includes logic delays.
Timing Score: 0
INFO:Timing:2761 - N/A entries in the Constraints list may indicate that the constraint does not cover any paths or that it has no
requested value.
Number of Timing Constraints that were not applied: 4
Asterisk (*) preceding a constraint indicates it was not met.
This may be due to a setup or hold violation.
------------------------------------------------------------------------------------------------------
Constraint | Check | Worst Case | Best Case | Timing | Timing
| | Slack | Achievable | Errors | Score
------------------------------------------------------------------------------------------------------
TS_i_iclockios_isclk0 = PERIOD TIMEGRP "i | SETUP | 0.002ns| 7.098ns| 0| 0
_iclockios_isclk0" TS_CLK0 HIGH 50% | HOLD | 0.574ns| | 0| 0
------------------------------------------------------------------------------------------------------
TS_HUFFLATCHES = MAXDELAY FROM TIMEGRP "T | SETUP | 0.044ns| 4.393ns| 0| 0
G_HUFFLATCHES" TO TIMEGRP "TG_HUF | | | | |
FFFS" TS_CLK0 * 0.625 | | | | |
------------------------------------------------------------------------------------------------------
TS_HUFFLATCHESI = MAXDELAY FROM TIMEGRP " | SETUP | 0.065ns| 4.283ns| 0| 0
TG_HUFFFFS" TO TIMEGRP "TG_HUFFLA | | | | |
TCHES" TS_CLK0 * 0.6125 | | | | |
------------------------------------------------------------------------------------------------------
TS_i_sensorpads_pclk2xi = PERIOD TIMEGRP | SETUP | 0.125ns| 5.075ns| 0| 0
"i_sensorpads_pclk2xi" TS_CLK1 / 2 | HOLD | 0.640ns| | 0| 0
HIGH 50% | | | | |
------------------------------------------------------------------------------------------------------
TS_CLK1 = PERIOD TIMEGRP "CLK1" 10.4 ns H | SETUP | 0.134ns| 10.266ns| 0| 0
IGH 50% | HOLD | 0.722ns| | 0| 0
------------------------------------------------------------------------------------------------------
TS_AXIS_READ = MAXDELAY FROM TIMEGRP "CPU | MAXDELAY| 0.184ns| 16.816ns| 0| 0
_ADDRCE" TO TIMEGRP "CPU_DATA" 17 ns | | | | |
------------------------------------------------------------------------------------------------------
TS_OE_TO_DATA = MAXDELAY FROM TIMEGRP "OE | MAXDELAY| 0.241ns| 11.759ns| 0| 0
" TO TIMEGRP "CPU_DATA" 12 ns | | | | |
------------------------------------------------------------------------------------------------------
TS_i_sensorpads_i_sensor_phase_dcm2x180 = | SETUP | 0.313ns| 4.887ns| 0| 0
PERIOD TIMEGRP "i_sensorpads_i_s | HOLD | 1.020ns| | 0| 0
ensor_phase_dcm2x180" TS_CLK1 / 2 PHASE 2 | | | | |
.6 ns HIGH 50% | | | | |
------------------------------------------------------------------------------------------------------
TS_DOUBLECYCS3 = MAXDELAY FROM TIMEGRP "T | SETUP | 0.410ns| 13.790ns| 0| 0
G_SLOW_SRC3" TO TIMEGRP "TG_DOUBL | | | | |
EDEST3" TS_CLK0 * 2 | | | | |
------------------------------------------------------------------------------------------------------
TS_i_iclockios_isclk270 = PERIOD TIMEGRP | SETUP | 0.416ns| 6.268ns| 0| 0
"i_iclockios_isclk270" TS_CLK0 PHASE | HOLD | 1.373ns| | 0| 0
5.325 ns HIGH 50% | | | | |
------------------------------------------------------------------------------------------------------
TS_HUFFRAMS = MAXDELAY FROM TIMEGRP "TG_H | SETUP | 0.419ns| 5.615ns| 0| 0
UFFRAMS" TO TIMEGRP "TG_HUFFLATCHES" | | | | |
TS_CLK0 * 0.85 | | | | |
------------------------------------------------------------------------------------------------------
TS_HUFFRAMSA = MAXDELAY FROM TIMEGRP "TG_ | SETUP | 1.220ns| 4.903ns| 0| 0
HUFFLATCHES" TO TIMEGRP "TG_HUFFRAMS" | | | | |
TS_CLK0 * 0.8625 | | | | |
------------------------------------------------------------------------------------------------------
TS_DACK0 = MAXDELAY FROM TIMEGRP "DACK" T | MAXDELAY| 1.986ns| 15.014ns| 0| 0
O TIMEGRP "ALLPADS" 17 ns | | | | |
------------------------------------------------------------------------------------------------------
TS_WE = MAXDELAY FROM TIMEGRP "WE" TO TIM | MAXDELAY| 2.987ns| 8.513ns| 0| 0
EGRP "TNM_CWR" 11.5 ns | | | | |
------------------------------------------------------------------------------------------------------
TS_HIST_DOUBLECYC2 = MAXDELAY FROM TIMEGR | SETUP | 4.045ns| 6.355ns| 0| 0
P "TG_HIST_DOUBLE2_SRC" TO TIMEGRP | | | | |
"TG_HIST_DOUBLE2_DST" TS_CLK1 | | | | |
------------------------------------------------------------------------------------------------------
TS_HIST_DOUBLECYC1 = MAXDELAY FROM TIMEGR | SETUP | 4.239ns| 6.161ns| 0| 0
P "FFS(\"*hist_pre*\")" TO TIMEGRP | | | | |
"FFS(\"*hist_post*\")" TS_CLK1 | | | | |
------------------------------------------------------------------------------------------------------
TS_DOUBLECYCS2 = MAXDELAY FROM TIMEGRP "T | SETUP | 5.522ns| 8.678ns| 0| 0
G_DOUBLECYCS2" TO TIMEGRP "TG_ALL | | | | |
_SYNC" TS_CLK0 * 2 | | | | |
------------------------------------------------------------------------------------------------------
TS_DOUBLECYC_IDATA = MAXDELAY FROM TIMEGR | SETUP | 5.759ns| 4.641ns| 0| 0
P "TNM_EN_IDATA" TO TIMEGRP "TNM_ | | | | |
EN_IDATA" TS_CLK1 | | | | |
------------------------------------------------------------------------------------------------------
TS_WR_DATA = MAXDELAY FROM TIMEGRP "CPU_D | SETUP | 6.460ns| 2.540ns| 0| 0
ATA" TO TIMEGRP "TG_CWRDEST" 9 ns | | | | |
------------------------------------------------------------------------------------------------------
PATH "TS_PCLK_PCLK2X_path" TIG | SETUP | N/A| 4.600ns| N/A| 0
------------------------------------------------------------------------------------------------------
PATH "TS_GCLK_IDATA_PCLK_path" TIG | SETUP | N/A| 13.510ns| N/A| 0
------------------------------------------------------------------------------------------------------
PATH "TS_PCLK_GCLK_IDATA_path" TIG | SETUP | N/A| 5.796ns| N/A| 0
------------------------------------------------------------------------------------------------------
TS_i_sensorpads_i_sensor_phase_pre_pre_en | N/A | N/A| N/A| N/A| N/A
_idata = PERIOD TIMEGRP "i_sensor | | | | |
pads_i_sensor_phase_pre_pre_en_idata" TS_ | | | | |
CLK1 PHASE 2.6 ns HIGH 50% | | | | |
------------------------------------------------------------------------------------------------------
TS_i_sensorpads_i_sensor_phase_pre_pre_en | N/A | N/A| N/A| N/A| N/A
_idata90 = PERIOD TIMEGRP "i_sens | | | | |
orpads_i_sensor_phase_pre_pre_en_idata90" | | | | |
TS_CLK1 PHASE 5.2 ns HIGH 50% | | | | |
------------------------------------------------------------------------------------------------------
TS_i_sensorpads_i_sensor_phase_dcm2x = PE | N/A | N/A| N/A| N/A| N/A
RIOD TIMEGRP "i_sensorpads_i_sens | | | | |
or_phase_dcm2x" TS_CLK1 / 2 HIGH 50% | | | | |
------------------------------------------------------------------------------------------------------
TS_CLK0 = PERIOD TIMEGRP "CLK0" 7.1 ns HI | N/A | N/A| N/A| N/A| N/A
GH 50% | | | | |
------------------------------------------------------------------------------------------------------
Derived Constraint Report
Derived Constraints for TS_CLK0
+-------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | Period | Actual Period | Timing Errors | Paths Analyzed |
| Constraint | Requirement |-------------+-------------|-------------+-------------|-------------+-------------|
| | | Direct | Derivative | Direct | Derivative | Direct | Derivative |
+-------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
|TS_CLK0 | 7.100ns| N/A| 7.098ns| 0| 0| 0| 31272|
| TS_DOUBLECYCS2 | 14.200ns| 8.678ns| N/A| 0| 0| 423| 0|
| TS_DOUBLECYCS3 | 14.200ns| 13.790ns| N/A| 0| 0| 8243| 0|
| TS_HUFFRAMS | 6.035ns| 5.615ns| N/A| 0| 0| 36| 0|
| TS_HUFFLATCHES | 4.438ns| 4.393ns| N/A| 0| 0| 115| 0|
| TS_HUFFRAMSA | 6.124ns| 4.903ns| N/A| 0| 0| 21| 0|
| TS_HUFFLATCHESI | 4.349ns| 4.283ns| N/A| 0| 0| 107| 0|
| TS_i_iclockios_isclk0 | 7.100ns| 7.098ns| N/A| 0| 0| 22239| 0|
| TS_i_iclockios_isclk270 | 7.100ns| 6.268ns| N/A| 0| 0| 88| 0|
+-------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
Derived Constraints for TS_CLK1
+-------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | Period | Actual Period | Timing Errors | Paths Analyzed |
| Constraint | Requirement |-------------+-------------|-------------+-------------|-------------+-------------|
| | | Direct | Derivative | Direct | Derivative | Direct | Derivative |
+-------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
|TS_CLK1 | 10.400ns| 10.266ns| 10.150ns| 0| 0| 57766| 1866|
| TS_DOUBLECYC_IDATA | 10.400ns| 4.641ns| N/A| 0| 0| 244| 0|
| TS_HIST_DOUBLECYC1 | 10.400ns| 6.161ns| N/A| 0| 0| 495| 0|
| TS_HIST_DOUBLECYC2 | 10.400ns| 6.355ns| N/A| 0| 0| 117| 0|
| TS_i_sensorpads_pclk2xi | 5.200ns| 5.075ns| N/A| 0| 0| 890| 0|
| TS_i_sensorpads_i_sensor_phase| 10.400ns| N/A| N/A| 0| 0| 0| 0|
| _pre_pre_en_idata | | | | | | | |
| TS_i_sensorpads_i_sensor_phase| 10.400ns| N/A| N/A| 0| 0| 0| 0|
| _pre_pre_en_idata90 | | | | | | | |
| TS_i_sensorpads_i_sensor_phase| 5.200ns| N/A| N/A| 0| 0| 0| 0|
| _dcm2x | | | | | | | |
| TS_i_sensorpads_i_sensor_phase| 5.200ns| 4.887ns| N/A| 0| 0| 120| 0|
| _dcm2x180 | | | | | | | |
+-------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
All constraints were met.
INFO:Timing:2761 - N/A entries in the Constraints list may indicate that the
constraint does not cover any paths or that it has no requested value.
Generating Pad Report.
All signals are completely routed.
Total REAL time to PAR completion: 13 mins 31 secs
Total CPU time to PAR completion: 13 mins 20 secs
Peak Memory Usage: 356 MB
Placement: Completed - No errors found.
Routing: Completed - No errors found.
Timing: Completed - No errors found.
Number of error messages: 0
Number of warning messages: 9 (0 filtered)
Number of info messages: 3 (0 filtered)
Writing design to file /home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3/mppr_result.dir/H_H_2.ncd
PAR done!
This source diff could not be displayed because it is too large. You can view the blob instead.
# SCSPAD 3.31 Andrey Filippov
# Use this file with Xilinx software
# Project: ~/PCB/10353/REVB/10353b
# Created: Sat Jan 20 01:40:47 2007
NET "PXD<0>" LOC = "J3" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<1>" LOC = "H6" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<2>" LOC = "J2" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<3>" LOC = "H5" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<4>" LOC = "J1" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<5>" LOC = "G5" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<6>" LOC = "H4" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<7>" LOC = "G4" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<8>" LOC = "G3" | IOSTANDARD = "LVCMOS25" ;
NET "PXD<9>" LOC = "H3" | IOSTANDARD = "LVCMOS25" ;
#NET "DCLK" LOC = "L3" | IOSTANDARD = "LVCMOS25" | SLEW = "SLOW" | DRIVE = 2 ; # default
NET "DCLK" LOC = "L3" | IOSTANDARD = "LVCMOS25" | SLEW = "SLOW" | DRIVE = 4 ; # increased for Eyesis4pi 450mm cable
NET "BPF" LOC = "K5" | IOSTANDARD = "LVCMOS25" ;
NET "VACT" LOC = "K1" | IOSTANDARD = "LVCMOS25" ;
NET "HACT" LOC = "J5" | IOSTANDARD = "LVCMOS25" ;
NET "MRST" LOC = "E3" | IOSTANDARD = "LVCMOS25" ;
NET "ARO" LOC = "C1" | IOSTANDARD = "LVCMOS25" ;
NET "ARST" LOC = "E1" | IOSTANDARD = "LVCMOS25" ;
NET "SCL0" LOC = "G2" | IOSTANDARD = "LVCMOS25" ;
NET "SDA0" LOC = "E4" | IOSTANDARD = "LVCMOS25" ;
NET "CNVSYNC" LOC = "B1" | IOSTANDARD = "LVCMOS25" ;
NET "CNVCLK" LOC = "B2" | IOSTANDARD = "LVCMOS25" ;
NET "SENSPGM" LOC = "D1" | IOSTANDARD = "LVCMOS25" ;
NET "EXT<0>" LOC = "C4" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<1>" LOC = "C5" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<2>" LOC = "A4" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<3>" LOC = "A5" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<4>" LOC = "D6" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<5>" LOC = "C6" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<6>" LOC = "C7" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<7>" LOC = "B7" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<8>" LOC = "E7" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<9>" LOC = "D7" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<10>" LOC = "F8" | IOSTANDARD = "LVCMOS33" ;
NET "EXT<11>" LOC = "E8" | IOSTANDARD = "LVCMOS33" ;
NET "CLK3" LOC = "A8" | IOSTANDARD = "LVCMOS33" ;
NET "CLK2" LOC = "C9" | IOSTANDARD = "LVCMOS33" ;
NET "CLK4" LOC = "B8" | IOSTANDARD = "LVCMOS33" ;
NET "CLK1" LOC = "A10" | IOSTANDARD = "LVCMOS33" ;
NET "CLK0" LOC = "A9" | IOSTANDARD = "LVCMOS33" ;
NET "LDQS" LOC = "N8" | IOSTANDARD = "SSTL2_I" ;
NET "UDQS" LOC = "P8" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<0>" LOC = "R14" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<1>" LOC = "T12" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<2>" LOC = "N12" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<3>" LOC = "N10" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<4>" LOC = "R11" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<5>" LOC = "N9" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<6>" LOC = "M9" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<7>" LOC = "L8" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<8>" LOC = "P9" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<9>" LOC = "P10" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<10>" LOC = "M10" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<11>" LOC = "P11" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<12>" LOC = "P12" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<13>" LOC = "R13" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<14>" LOC = "T13" | IOSTANDARD = "SSTL2_I" ;
NET "SDD<15>" LOC = "P14" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<0>" LOC = "P1" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<1>" LOC = "K3" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<2>" LOC = "M1" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<3>" LOC = "K2" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<4>" LOC = "T4" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<5>" LOC = "M4" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<6>" LOC = "T5" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<7>" LOC = "P5" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<8>" LOC = "N5" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<9>" LOC = "R6" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<10>" LOC = "N1" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<11>" LOC = "P6" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<12>" LOC = "P7" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<13>" LOC = "P2" | IOSTANDARD = "SSTL2_I" ;
NET "SDA<14>" LOC = "L4" | IOSTANDARD = "SSTL2_I" ;
NET "SDWE" LOC = "M7" | IOSTANDARD = "SSTL2_I" ;
NET "SDCAS" LOC = "N7" | IOSTANDARD = "SSTL2_I" ;
NET "SDRAS" LOC = "M6" | IOSTANDARD = "SSTL2_I" ;
NET "SDLDM" LOC = "M8" | IOSTANDARD = "SSTL2_I" ;
NET "SDUDM" LOC = "T8" | IOSTANDARD = "SSTL2_I" ;
NET "SDCLK" LOC = "R2" | IOSTANDARD = DIFF_SSTL2_I ;
NET "SDCLK_FB" LOC = "R3" | IOSTANDARD = DIFF_SSTL2_I ;
NET "SDNCLK" LOC = "R1" | IOSTANDARD = DIFF_SSTL2_I ;
NET "SDNCLK_FB" LOC = "T3" | IOSTANDARD = DIFF_SSTL2_I ;
#NET "SDNCLK_FB" LOC = "T3" | IOSTANDARD = "DIFF_SSTL2_I" ;
#NET "SDCLK_FB" LOC = "R3" | IOSTANDARD = "DIFF_SSTL2_I" ;
#NET "SDCLK" LOC = "R2" | IOSTANDARD = "DIFF_SSTL2_I ";
#NET "SDNCLK" LOC = "R1" | IOSTANDARD = "DIFF_SSTL2_I ";
NET "SDCLKE" LOC = "N6" | IOSTANDARD = "SSTL2_I" ;
NET "D<0>" LOC = "M16" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<1>" LOC = "N15" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<2>" LOC = "N16" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<3>" LOC = "L13" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<4>" LOC = "P16" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<5>" LOC = "N14" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<6>" LOC = "R16" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<7>" LOC = "P15" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<8>" LOC = "R15" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<9>" LOC = "L12" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<10>" LOC = "C11" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<11>" LOC = "A13" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<12>" LOC = "B11" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<13>" LOC = "D9" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<14>" LOC = "B10" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<15>" LOC = "A12" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<16>" LOC = "A7" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<17>" LOC = "K12" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<18>" LOC = "E9" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<19>" LOC = "B4" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<20>" LOC = "F9" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<21>" LOC = "C3" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<22>" LOC = "H11" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<23>" LOC = "B6" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<24>" LOC = "K14" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<25>" LOC = "E10" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<26>" LOC = "K15" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<27>" LOC = "L14" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<28>" LOC = "L15" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<29>" LOC = "K13" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<30>" LOC = "C8" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "D<31>" LOC = "D8" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 8 ;
NET "A<0>" LOC = "D14" | IOSTANDARD = "LVCMOS33" ;
NET "A<1>" LOC = "F13" | IOSTANDARD = "LVCMOS33" ;
NET "A<2>" LOC = "F12" | IOSTANDARD = "LVCMOS33" ;
NET "A<3>" LOC = "E11" | IOSTANDARD = "LVCMOS33" ;
NET "A<4>" LOC = "E13" | IOSTANDARD = "LVCMOS33" ;
NET "A<5>" LOC = "E16" | IOSTANDARD = "LVCMOS33" ;
NET "A<6>" LOC = "F14" | IOSTANDARD = "LVCMOS33" ;
NET "A<7>" LOC = "F15" | IOSTANDARD = "LVCMOS33" ;
NET "A<8>" LOC = "G14" | IOSTANDARD = "LVCMOS33" ;
NET "A<9>" LOC = "G13" | IOSTANDARD = "LVCMOS33" ;
NET "A<10>" LOC = "G16" | IOSTANDARD = "LVCMOS33" ;
NET "A<11>" LOC = "G15" | IOSTANDARD = "LVCMOS33" ;
NET "A<12>" LOC = "H12" | IOSTANDARD = "LVCMOS33" ;
NET "BA<0>" LOC = "H14" | IOSTANDARD = "LVCMOS33" ;
NET "BA<1>" LOC = "H15" | IOSTANDARD = "LVCMOS33" ;
NET "SYS_SDWE" LOC = "J13" | IOSTANDARD = "LVCMOS33" ;
NET "SYS_SDCAS" LOC = "J16" | IOSTANDARD = "LVCMOS33" ;
NET "SYS_SDRAS" LOC = "K16" | IOSTANDARD = "LVCMOS33" ;
NET "SYS_SDCLKI" LOC = "J12" | IOSTANDARD = "LVCMOS33" ;
NET "SYS_SDCLK" LOC = "J14" | IOSTANDARD = "LVCMOS33" ;
NET "SYS_BUSEN" LOC = "C16" | IOSTANDARD = "LVCMOS33" ;
NET "WE" LOC = "M13" | IOSTANDARD = "LVCMOS33" ;
NET "OE" LOC = "M14" | IOSTANDARD = "LVCMOS33" ;
NET "CE" LOC = "D16" | IOSTANDARD = "LVCMOS33" ;
NET "CE1" LOC = "E14" | IOSTANDARD = "LVCMOS33" ;
NET "DREQ0" LOC = "C15" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 4 ; # default
NET "DACK0" LOC = "B14" | IOSTANDARD = "LVCMOS33" ;
NET "DREQ1" LOC = "D10" | IOSTANDARD = "LVCMOS33" | SLEW = "SLOW" | DRIVE = 4 ; # default
NET "DACK1" LOC = "A14" | IOSTANDARD = "LVCMOS33" ;
NET "IRQ" LOC = "D15" | IOSTANDARD = "LVCMOS33" ;
NET "BG" LOC = "D11" | IOSTANDARD = "LVCMOS33" ;
NET "BRIN" LOC = "B16" | IOSTANDARD = "LVCMOS33" ;
NET "BROUT" LOC = "B13" | IOSTANDARD = "LVCMOS33" ;
#assign an output with SSTL2_I so VREF will be used in bank 3
NET "DUMMYVFEF" LOC = "J4" | IOSTANDARD = "SSTL2_I" ;
#week pulldown to fool the software into keeping signals
NET "ALWAYS0" LOC = "J6" | IOSTANDARD = "LVCMOS25" ;
NET "CLK0" TNM_NET = "CLK0";
NET "CLK1" TNM_NET = "CLK1";
NET "CLK1" CLOCK_DEDICATED_ROUTE = FALSE; #phase is not critical, just clock generator
NET "CLK0" CLOCK_DEDICATED_ROUTE = FALSE; #phase is not critical, just clock generator
PIN "i_dcm333/i_dcm2.CLK90" CLOCK_DEDICATED_ROUTE = FALSE;
#TIMESPEC "TS_CLK0" = PERIOD "CLK0" 7.25 ns HIGH 50 %; #03534018B
#TIMESPEC "TS_CLK0" = PERIOD "CLK0" 7.15 ns HIGH 50 %; #reports "N/A" but is needed for derivative signals
TIMESPEC "TS_CLK0" = PERIOD "CLK0" 7.1 ns HIGH 50 %;
TIMESPEC "TS_CLK1" = PERIOD "CLK1" 10.4 ns HIGH 50 %; #96MHz
#TIMESPEC "TS_CLK1" = PERIOD "CLK1" 10.6 ns HIGH 50 %; #trying to meet other
#TIMESPEC "TS_CLK1" = PERIOD "CLK1" 18.4 ns HIGH 50 %; #TEMPORARY TO FIND A PROBLEM
TIMEGRP "CPU_ADDR" = pads("A<*>");
TIMEGRP "CPU_ADDRCE" = "CPU_ADDR" pads("CE*");
TIMEGRP "CPU_DATA" = pads("D<*>");
TIMEGRP "WE" = pads("WE");
TIMEGRP "OE" = pads("OE");
TIMEGRP "DACK_PAD"= pads("DACK*");
TIMEGRP "DREQ_PAD"= pads("DREQ*");
TIMEGRP "ALLPADS"= pads("*");
NET "idack0" TPTHRU = "IDACK0_TP";
NET "idack1" TPTHRU = "IDACK1_TP";
#NET "idreq0" TPTHRU = "IDREQ0_TP";va
#NET "idreq1" TPTHRU = "IDREQ1_TP";
#TIMESPEC "TS_DACK_DREQ0" = FROM "DACK_PAD" THRU "IDACK0_TP" THRU "IDREQ0_TP" TO "DREQ_PAD" 9.5 ns;
#TIMESPEC "TS_DACK_DREQ1" = FROM "DACK_PAD" THRU "IDACK1_TP" THRU "IDREQ1_TP" TO "DREQ_PAD" 9.5 ns;
NET "*/cwr" TNM_NET = "TNM_CWR";
TIMEGRP "TG_CWRDEST" = "TNM_CWR" except latches ("*"); # RAMS, FFS
###MARK1# TIMEGRP "TG_LATCHES_A" = latches ("i_sysinterface/i_a*");
NET "DACK*" TNM_NET = "DACK";
NET "SDA0*" TNM_NET = "SDA0";
NET "sclk0" TNM_NET = "TNM_CLK0";
NET "xclk" TNM_NET = "TNM_XCLK";
NET "pclk" TNM_NET = "TNM_PCLK";
NET "i_sensorpads/i_sensor_phase/gclk_idata" TNM_NET = "TNM_GCLK_IDATA";
NET "i_sensorpads/i_sensor_phase/en_idata" TNM_NET = "TNM_EN_IDATA";
TIMESPEC "TS_PCLK_GCLK_IDATA" = FROM "TNM_PCLK" TO "TNM_GCLK_IDATA" TIG;
TIMESPEC "TS_GCLK_IDATA_PCLK" = FROM "TNM_GCLK_IDATA" TO "TNM_PCLK" TIG;
#TIMESPEC "TS_GCLK_IDATA_PERIOD" = PERIOD "TNM_GCLK_IDATA" "TS_CLK1" / 2;
TIMESPEC "TS_DOUBLECYC_IDATA" = FROM "TNM_EN_IDATA" TO "TNM_EN_IDATA" "TS_CLK1";
NET "i_sensorpads/i_sensor_phase/phase_hact_sel_sync*" TIG;
NET "i_sensorpads/i_sensor_phase/mode_alt_sync" TIG;
NET "i_sensorpads/i_sensor_phase/mode_12bits_sync" TIG;
NET "i_sensorpads/i_sensor_phase/mode_14bits_sync" TIG;
NET "hact_length*" TIG;
NET "cb_*" TIG;
TIMEGRP "TG_CLK1" = pads("CLK1");
TIMEGRP "TG_DCLK" = pads("DCLK");
#TIMESPEC "TS_SENSORCLOCK" = FROM "TG_CLK1" TO "TG_DCLK" 14.0 ns;
#######TIMESPEC "TS_OE_TO_DATA" = FROM "OE" TO "CPU_DATA" 10.3 ns; # temporary, with proxies
#TIMESPEC "TS_OE_TO_DATA" = FROM "OE" TO "CPU_DATA" 14.0ns ; # with DRIVE = 4 ; # default
TIMESPEC "TS_OE_TO_DATA" = FROM "OE" TO "CPU_DATA" 12.0ns ; # with DRIVE = 8
#normal
#######TIMESPEC "TS_AXIS_READ" = FROM "CPU_ADDRCE" TO "CPU_DATA" 16 ns; #17.5 ns;
#TIMESPEC "TS_AXIS_READ" = FROM "CPU_ADDRCE" TO "CPU_DATA" 19 ns; # with DRIVE = 4 ; # default
TIMESPEC "TS_AXIS_READ" = FROM "CPU_ADDRCE" TO "CPU_DATA" 17 ns; # with DRIVE = 8
###MARK1#TIMESPEC "TS_WR_ADDR" = FROM "TG_LATCHES_A" TO "TG_CWRDEST" 9.7 ns; #temporary, with proxies
TIMESPEC "TS_WR_DATA" = FROM "CPU_DATA" TO "TG_CWRDEST" 9 ns; # temporary, with proxies
TIMESPEC "TS_WE" = FROM "WE" TO "TNM_CWR" 11.5 ns; #
#########TIMESPEC "TS_DACK0" = FROM "DACK" TO "ALLPADS" 15 ns;
TIMESPEC "TS_DACK0" = FROM "DACK" TO "ALLPADS" 17 ns;
#NET "*dcr<*>" TIG; # new freedom
# new freedom
TIMEGRP "TG_ALL_SYNC"= FFS RAMS MULTS;
TIMEGRP "TG_DOUBLECYCS2"= ffs("i_mcontr/i_descrproc/seq_par*")
# ffs("i_mcontr/i_descrproc/linAddr*")
ffs("i_mcontr/i_descrproc/sa*")
ffs("i_mcontr/i_descrproc/nxtTL*")
ffs("i_mcontr/i_descrproc/tile*")
ffs("i_mcontr/i_descrproc/mode*")
ffs("i_mcontr/i_descrproc/WnR*")
ffs("i_mcontr/i_descrproc/depend*")
ffs("i_mcontr/i_descrproc/nextFrame*")
ffs("i_mcontr/i_descrproc/suspXfer*")
ffs("i_mcontr/i_descrproc/lineNumSource*")
ffs("i_mcontr/i_descrproc/lineNumDest*")
ffs("i_mcontr/i_descrproc/prevStripSource*")
ffs("i_mcontr/i_descrproc/last_lines_reg*")
# ffs("i_mcontr/i_descrproc/first_line_reg*")
ffs("i_mcontr/i_descrproc/first_tile_reg*")
# ffs("i_mcontr/i_descrproc/first_line_dest*")
ffs("i_mcontr/i_descrproc/first_tile_dest*")
ffs("i_mcontr/i_descrproc/nxtTFr*")
ffs("i_mcontr/i_descrproc/srcAtStart*")
mults("i_mcontr/i_descrproc/linAddr*");
TIMESPEC "TS_DOUBLECYCS2" = FROM "TG_DOUBLECYCS2" TO "TG_ALL_SYNC" "TS_CLK0" * 2;
TIMEGRP "TG_FAST_SRC3"= ffs("*stepsE*") ffs("*stepsI*") ffs("*stepsDwe*");
TIMEGRP "TG_SLOW_SRC3" = TG_ALL_SYNC EXCEPT "TG_FAST_SRC3";
TIMEGRP "TG_DOUBLEDEST3"= ffs("i_mcontr/i_descrproc/seq_par*")
# ffs("i_mcontr/i_descrproc/linAddr*")
ffs("i_mcontr/i_descrproc/sa*")
ffs("i_mcontr/i_descrproc/nxtTL*")
ffs("i_mcontr/i_descrproc/tile*")
ffs("i_mcontr/i_descrproc/mode*")
ffs("i_mcontr/i_descrproc/WnR*")
ffs("i_mcontr/i_descrproc/depend*")
ffs("i_mcontr/i_descrproc/nextFrame*")
ffs("i_mcontr/i_descrproc/nextBlocksEn*")
ffs("i_mcontr/i_descrproc/suspXfer*")
ffs("i_mcontr/i_descrproc/lineNumSource*")
ffs("i_mcontr/i_descrproc/lineNumDest*")
ffs("i_mcontr/i_descrproc/prevStripSource*")
ffs("i_mcontr/i_descrproc/rovr*")
ffs("i_mcontr/i_descrproc/last_lines_reg*")
# ffs("i_mcontr/i_descrproc/first_line_reg*")
ffs("i_mcontr/i_descrproc/first_tile_reg*")
# ffs("i_mcontr/i_descrproc/first_line_dest*")
ffs("i_mcontr/i_descrproc/first_tile_dest*")
ffs("i_mcontr/i_descrproc/nxtTFr*")
ffs("i_mcontr/i_descrproc/nxtTF_p*")
ffs("i_mcontr/i_descrproc/srcAtStart*")
mults("i_mcontr/i_descrproc/linAddr*");
TIMESPEC "TS_DOUBLECYCS3" = FROM "TG_SLOW_SRC3" TO "TG_DOUBLEDEST3" "TS_CLK0" * 2;
## Next - redundant?
##TIMESPEC "TS_DOUBLECYCS4" = FROM FFS("*i_chArbit/chNum*") TO "TG_DOUBLEDEST3" TS_CLK0*2;
TIMEGRP "TG_HUFFRAMS"= rams ("*i_huffman*") ;
#FIXME: Constraint <TIMEGRP "TG_HUFFFFS" ... does not match any design objects.
TIMEGRP "TG_HUFFFFS"= ffs ("*i_huffman*")
ffs ("*i_stuffer*") ;
TIMEGRP "TG_HUFFLATCHES"= latches ("*i_huffman*") ;
# some registers in Huffman module are isolated from others through latches too - never used?
##TIMEGRP "TG_HUFFFFS_ISOLOUT" = ffs ("*i_huff_fifo/load_q");
TIMEGRP "TG_STUFFER_WAS_READY_EARLY" = latches ("i_compressor/i_huffman/i_stuffer_was_rdy_early") ;
TIMEGRP "TG_HUFF_FIFO_LOAD_Q" = ffs ("i_compressor/i_huffman/i_huff_fifo/load_q") ;
TIMEGRP "TG_COMPRESSOR"= ffs ("*i_compressor*") ;
### THe two below constraints are not needed, they are covered by "TS_HUFFLATCHES" and "TS_HUFFLATCHESI"
## TIMESPEC "TS_HUFF_FIFO_LOAD_Q"= FROM "TG_STUFFER_WAS_READY_EARLY" TO "TG_HUFFFFS" "TS_CLK0" * 0.625;
## TIMESPEC "TS_STUFFER_WAS_READY_EARLY"= FROM "TG_HUFFFFS" TO "TG_STUFFER_WAS_READY_EARLY" "TS_CLK0" * 0.7;
TIMESPEC "TS_HUFFRAMS" = FROM "TG_HUFFRAMS" TO "TG_HUFFLATCHES" "TS_CLK0" * 0.85;
TIMESPEC "TS_HUFFLATCHES" = FROM "TG_HUFFLATCHES" TO "TG_HUFFFFS" "TS_CLK0" * 0.625;
TIMESPEC "TS_HUFFRAMSA" = FROM "TG_HUFFLATCHES" TO "TG_HUFFRAMS" "TS_CLK0" * 0.8625;
TIMESPEC "TS_HUFFLATCHESI" = FROM "TG_HUFFFFS" TO "TG_HUFFLATCHES" "TS_CLK0" * 0.6125;
NET "*enSDRAM" TIG;
#was already ignored from sclk0 to pclk
NET "*dcr*" TIG;
NET "i_rtc353/acc*" TIG;
NET "i_rtc353/sec*" TIG;
NET "i_rtc353/usec*" TIG;
NET "i_rtc353/wsec*" TIG;
NET "i_rtc353/wusec*" TIG;
NET "i_rtc353/corr*" TIG;
#needed?
NET "i_camsync/ts_rcv_sec*" TIG;
NET "i_camsync/ts_rcv_usec*" TIG;
#NET "i_imu_logger/imu_in_word*" TIG;
NET "i_rtc353/psec*" TIG;
NET "i_rtc353/pusec*" TIG;
#NET "i_rtc353/esec*" TIG;
#NET "i_rtc353/eusec*" TIG;
#INST "i_imu_logger/i_buffer*" TIG;
#INST "i_imu_logger/config*" TIG;
#INST "i_imu_logger/enable*" TIG;
INST "*_tig_*" TIG;
#histogram
#NET "???" TNM_NET = "TNM_PCLK";
NET "pclk2x" TNM_NET = "TNM_PCLK2X";
TIMESPEC "TS_PCLK_PCLK2X" = FROM "TNM_PCLK" TO "TNM_PCLK2X" TIG;
#TIMESPEC "TS_PCLK2X_PCLK" = FROM "TNM_PCLK2X" TO "TNM_PCLK" TIG;
TIMEGRP "TG_HIST_DOUBLE_DEST"= ffs("*hist_post*");
TIMEGRP "TG_HIST_DOUBLE_SRC "= ffs("*hist_pre*");
TIMESPEC "TS_HIST_DOUBLECYC1" = FROM FFS("*hist_pre*") TO FFS("*hist_post*") "TS_CLK1" ;
INST "i_histogram/pos_left_*" TIG;
INST "i_histogram/pos_top_*" TIG;
INST "i_histogram/size_width_*" TIG;
INST "i_histogram/size_height_*" TIG;
INST "i_histogram/minus_pos_left_*" TIG;
INST "i_histogram/pos_left_is_zero*" TIG;
TIMEGRP "TG_HIST_DOUBLE2_SRC"= ffs("i_histogram/pix_cntr*");
TIMEGRP "TG_HIST_DOUBLE2_DST"= ffs("i_histogram/pix_cntr*")
ffs("i_histogram/line_started*")
ffs("i_histogram/line_ended*") ;
TIMESPEC "TS_HIST_DOUBLECYC2" = FROM "TG_HIST_DOUBLE2_SRC" TO "TG_HIST_DOUBLE2_DST" "TS_CLK1" ;
INST "i_sensorpads/i_sensor_phase/rq_back*" TIG;
#compressor controls
INST "i_compressor/i_m_c*" TIG;
INST "i_compressor/i_coring_num*" TIG;
INST "i_compressor/i_compr_ifc/cmprs_en*" TIG;
INST "i_compressor/i_compr_ifc/cmprs_fmode*" TIG;
INST "i_compressor/i_compr_ifc/cmprs_mode*" TIG;
INST "i_compressor/i_compr_ifc/cmprs_qpage*" TIG;
INST "i_compressor/i_compr_ifc/cmprs_shift*" TIG;
INST "i_compressor/i_compr_ifc/i_bayer_shift*" TIG;
#INST "i_mcontr/i_descproc/bonded*" TIG;
INST "*bonded*" TIG;
#:Place:1018 - A clock IOB / clock component pair have been found that are
# not placed at an optimal clock IOB / clock site pair. The clock component
# <i_pclk> is placed at site <BUFGMUX_X1Y11>. The IO component <BPF> is placed
# at site <K5>. This will not allow the use of the fast path between the IO
# and the Clock buffer. If this sub optimal condition is acceptable for this
# design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .ucf file to
# demote this message to a WARNING and allow your design to continue. However,
# the use of this override is highly discouraged as it may lead to very poor
# timing results. It is recommended that this error condition be corrected in
# the design. A list of all the COMP.PINs used in this clock placement rule is
# listed below. These examples can be used directly in the .ucf file to
# override this clock rule.
NET "BPF" CLOCK_DEDICATED_ROUTE = FALSE;
#Used with defined debug_mcontr_reset, comment out if disabled
INST "debug_mcontr_count*" TIG;
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
<<<<<<< x353_1.sav
[timestart] 0
[size] 1844 1178
[pos] 1910 0
*-27.431326 555456250 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
=======
[timestart] 214700000
[size] 1844 1170
[pos] 1910 0
*-24.692209 307364625 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
>>>>>>> 1.14
[treeopen] testbench353.
[treeopen] testbench353.i_x353.
<<<<<<< x353_1.sav
[treeopen] testbench353.i_x353.i_camsync.
[treeopen] testbench353.i_x353.i_compressor.
=======
[treeopen] testbench353.i_x353.i_imu_logger.
>>>>>>> 1.14
[treeopen] testbench353.i_x353.i_mcontr.i_descrproc.
[treeopen] testbench353.i_x353.i_sensorpads.i_sensor_phase.
<<<<<<< x353_1.sav
[treeopen] testbench353.i_x353.i_sysinterface.i_we.
@800200
=======
[treeopen] testbench353.i_x353.i_sysinterface.i_we.
@c00200
>>>>>>> 1.14
-system
@28
testbench353.i_sensor12bits.ARO
testbench353.i_x353.CLK1
testbench353.VACT
testbench353.i_x353.vacts_every
testbench353.i_x353.vacts_long
testbench353.HACT
@22
testbench353.PXD[11:0]
@28
testbench353.DREQ
testbench353.DACK
@22
testbench353.DMA_DI[31:0]
testbench353.CPU_DI[31:0]
testbench353.CPU_DO[31:0]
@28
testbench353.i_x353.cb_bayer_phase[1:0]
<<<<<<< x353_1.sav
testbench353.i_x353.DREQ0
testbench353.i_x353.DACK0
testbench353.i_x353.DREQ1
testbench353.i_x353.DACK1
@22
testbench353.DMA_DI_1[31:0]
@28
testbench353.i_x353.vacts
@23
testbench353.i_x353.i2c_frame_no[2:0]
@28
testbench353.i_x353.i_irq_smart.is_compressing
testbench353.i_x353.i_irq_smart.wait_frame_sync
testbench353.IRQ
testbench353.i_x353.compressor_eot
testbench353.i_x353.compressor_done_compress
testbench353.i_x353.compressor_done_input
testbench353.i_x353.compressor_done_pulse
testbench353.i_x353.compressor_started
@22
testbench353.i_x353.i_compressor.imgptr[23:0]
@28
testbench353.i_x353.i_irq_smart.compressor_done
testbench353.i_x353.i_irq_smart.compressor_fifo_done
testbench353.i_x353.i_irq_smart.delaying_done_irq
@22
testbench353.i_x353.i_irq_smart.di[15:0]
@28
testbench353.i_x353.i_irq_smart.done_request
testbench353.i_x353.i_irq_smart.end_postpone_fs
testbench353.i_x353.i_irq_smart.fifo_empty
testbench353.i_x353.i_irq_smart.finished
testbench353.i_x353.i_irq_smart.frame_sync
testbench353.i_x353.i_irq_smart.fs_postponed
testbench353.i_x353.i_irq_smart.irq
testbench353.i_x353.i_irq_smart.is_compressing
testbench353.i_x353.i_compressor.eot
testbench353.i_x353.i_compressor.i_huffman.last_block
testbench353.i_x353.i_compressor.i_huffman.gotLastBlock
testbench353.i_x353.i_compressor.color_first
testbench353.i_x353.i_compressor.color_last
testbench353.i_x353.i_compressor.i_encoderDCAC.lasti
testbench353.i_x353.i_compressor.i_encoderDCAC.lasto
testbench353.i_x353.i_irq_smart.is_finishing
testbench353.i_x353.i_irq_smart.rst
testbench353.i_x353.i_irq_smart.wait_fifo
testbench353.i_x353.i_irq_smart.wait_frame_sync
testbench353.i_x353.i_irq_smart.was_finishing
testbench353.i_x353.i_irq_smart.will_delay_done_irq
testbench353.i_x353.i_irq_smart.will_postpone_fs
testbench353.i_x353.i_camsync.restart
testbench353.i_x353.i_compressor.compressor_started
testbench353.i_x353.i_compressor.stuffer_done
testbench353.i_x353.i_compressor.i_stuffer.flush
testbench353.i_x353.i_compressor.i_stuffer.flush_end
testbench353.i_x353.i_compressor.i_stuffer.flush_end_delayed
testbench353.i_x353.i_compressor.i_stuffer.flush_now
testbench353.i_x353.i_compressor.i_stuffer.flushing
@1000200
=======
testbench353.i_x353.DREQ0
testbench353.i_x353.DACK0
testbench353.i_x353.DREQ1
testbench353.i_x353.DACK1
@22
testbench353.DMA_DI_1[31:0]
@1401200
>>>>>>> 1.14
-system
@c00022
testbench353.i_x353.D[31:0]
<<<<<<< x353_1.sav
@28
(0)testbench353.i_x353.D[31:0]
(1)testbench353.i_x353.D[31:0]
(2)testbench353.i_x353.D[31:0]
(3)testbench353.i_x353.D[31:0]
(4)testbench353.i_x353.D[31:0]
(5)testbench353.i_x353.D[31:0]
(6)testbench353.i_x353.D[31:0]
(7)testbench353.i_x353.D[31:0]
(8)testbench353.i_x353.D[31:0]
(9)testbench353.i_x353.D[31:0]
(10)testbench353.i_x353.D[31:0]
(11)testbench353.i_x353.D[31:0]
(12)testbench353.i_x353.D[31:0]
(13)testbench353.i_x353.D[31:0]
(14)testbench353.i_x353.D[31:0]
(15)testbench353.i_x353.D[31:0]
(16)testbench353.i_x353.D[31:0]
(17)testbench353.i_x353.D[31:0]
(18)testbench353.i_x353.D[31:0]
(19)testbench353.i_x353.D[31:0]
(20)testbench353.i_x353.D[31:0]
(21)testbench353.i_x353.D[31:0]
(22)testbench353.i_x353.D[31:0]
(23)testbench353.i_x353.D[31:0]
(24)testbench353.i_x353.D[31:0]
(25)testbench353.i_x353.D[31:0]
(26)testbench353.i_x353.D[31:0]
(27)testbench353.i_x353.D[31:0]
(28)testbench353.i_x353.D[31:0]
(29)testbench353.i_x353.D[31:0]
(30)testbench353.i_x353.D[31:0]
(31)testbench353.i_x353.D[31:0]
@1401200
-group_end
@800200
=======
@28
(0)testbench353.i_x353.D[31:0]
(1)testbench353.i_x353.D[31:0]
(2)testbench353.i_x353.D[31:0]
(3)testbench353.i_x353.D[31:0]
(4)testbench353.i_x353.D[31:0]
(5)testbench353.i_x353.D[31:0]
(6)testbench353.i_x353.D[31:0]
(7)testbench353.i_x353.D[31:0]
(8)testbench353.i_x353.D[31:0]
(9)testbench353.i_x353.D[31:0]
(10)testbench353.i_x353.D[31:0]
(11)testbench353.i_x353.D[31:0]
(12)testbench353.i_x353.D[31:0]
(13)testbench353.i_x353.D[31:0]
(14)testbench353.i_x353.D[31:0]
(15)testbench353.i_x353.D[31:0]
(16)testbench353.i_x353.D[31:0]
(17)testbench353.i_x353.D[31:0]
(18)testbench353.i_x353.D[31:0]
(19)testbench353.i_x353.D[31:0]
(20)testbench353.i_x353.D[31:0]
(21)testbench353.i_x353.D[31:0]
(22)testbench353.i_x353.D[31:0]
(23)testbench353.i_x353.D[31:0]
(24)testbench353.i_x353.D[31:0]
(25)testbench353.i_x353.D[31:0]
(26)testbench353.i_x353.D[31:0]
(27)testbench353.i_x353.D[31:0]
(28)testbench353.i_x353.D[31:0]
(29)testbench353.i_x353.D[31:0]
(30)testbench353.i_x353.D[31:0]
(31)testbench353.i_x353.D[31:0]
@1401200
-group_end
@c00200
>>>>>>> 1.14
-color_conversion
@22
testbench353.i_x353.i_compressor.i_color_proc.nblocks[17:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.noMoreData
testbench353.i_x353.i_compressor.i_color_proc.go
@22
testbench353.i_x353.i_compressor.i_color_proc.bcntr[17:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.ccv_start_en
testbench353.i_x353.i_compressor.i_color_proc.sdram_rdy
testbench353.i_x353.i_compressor.i_color_proc.all_ready
@22
testbench353.i_x353.i_compressor.i_color_proc.seq_cntr[8:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.pre_first_pixel
testbench353.i_x353.i_compressor.i_color_proc.first_pixel
testbench353.i_x353.i_compressor.i_color_proc.last0
testbench353.i_x353.i_compressor.i_color_proc.last
@22
testbench353.i_x353.i_compressor.cmprs_mode[3:0]
testbench353.i_x353.i_compressor.component_color
@28
testbench353.i_x353.i_compressor.component_first
testbench353.i_x353.i_compressor.component_lastinmb
@800022
testbench353.i_x353.i_compressor.component_num[2:0]
@28
(0)testbench353.i_x353.i_compressor.component_num[2:0]
(1)testbench353.i_x353.i_compressor.component_num[2:0]
(2)testbench353.i_x353.i_compressor.component_num[2:0]
@1001200
-group_end
@22
testbench353.i_x353.i_compressor.converter_type[2:0]
testbench353.i_x353.i_compressor.color_tn[2:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.clk
@22
testbench353.i_x353.i_compressor.color_d[9:0]
testbench353.i_x353.i_compressor.color_avr[8:0]
@28
testbench353.i_x353.i_compressor.color_dv
@22
testbench353.i_x353.i_compressor.i_color_proc.converter_type_r[2:0]
testbench353.i_x353.i_compressor.i_color_proc.c_in[8:0]
testbench353.i_x353.i_compressor.i_color_proc.c_out[8:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.cwe
testbench353.i_x353.i_compressor.i_color_proc.buf_sel
testbench353.i_x353.i_compressor.i_color_proc.ccv_out_start
testbench353.i_x353.i_compressor.i_color_proc.ccv_start_en
testbench353.i_x353.i_compressor.i_color_proc.go
@22
testbench353.i_x353.i_compressor.i_color_proc.do[9:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.ds
testbench353.i_x353.i_compressor.i_color_proc.dv
@1000200
-color_conversion
@c00200
-channel0
@28
testbench353.i_x353.i_sensorpix.hact
@c00022
testbench353.i_x353.i_sensorpix.pxd[15:0]
@28
(0)testbench353.i_x353.i_sensorpix.pxd[15:0]
(1)testbench353.i_x353.i_sensorpix.pxd[15:0]
(2)testbench353.i_x353.i_sensorpix.pxd[15:0]
(3)testbench353.i_x353.i_sensorpix.pxd[15:0]
(4)testbench353.i_x353.i_sensorpix.pxd[15:0]
(5)testbench353.i_x353.i_sensorpix.pxd[15:0]
(6)testbench353.i_x353.i_sensorpix.pxd[15:0]
(7)testbench353.i_x353.i_sensorpix.pxd[15:0]
(8)testbench353.i_x353.i_sensorpix.pxd[15:0]
(9)testbench353.i_x353.i_sensorpix.pxd[15:0]
(10)testbench353.i_x353.i_sensorpix.pxd[15:0]
(11)testbench353.i_x353.i_sensorpix.pxd[15:0]
(12)testbench353.i_x353.i_sensorpix.pxd[15:0]
(13)testbench353.i_x353.i_sensorpix.pxd[15:0]
(14)testbench353.i_x353.i_sensorpix.pxd[15:0]
(15)testbench353.i_x353.i_sensorpix.pxd[15:0]
@1401200
-group_end
@28
testbench353.i_x353.i_sensorpix.hact_out
testbench353.i_x353.i_sensorpix.dwe
@22
testbench353.i_x353.i_sensorpix.do[15:0]
testbench353.i_x353.i_mcontr.ch0a[9:0]
@28
testbench353.i_x353.i_mcontr.ch0clk
@22
testbench353.i_x353.i_mcontr.ch0di[15:0]
@28
testbench353.i_x353.i_mcontr.ch0en
@22
testbench353.i_x353.i_mcontr.ch0rd[31:0]
@28
testbench353.i_x353.i_mcontr.ch0rdy
@22
testbench353.i_mt46v16m16fg.Dq[15:0]
@28
testbench353.i_mt46v16m16fg.Cas_n
testbench353.i_mt46v16m16fg.We_n
testbench353.i_mt46v16m16fg.Clk
@22
testbench353.i_x353.i_mcontr.ch0a[9:0]
@28
testbench353.i_x353.i_mcontr.ch0we
@22
testbench353.i_x353.i_mcontr.ch0di[15:0]
@28
testbench353.i_x353.i_mcontr.readNextFrame0
testbench353.i_x353.i_mcontr.stch0
testbench353.i_x353.i_sensorpix.wpage
testbench353.i_x353.i_sensorpix.incbwa
@1401200
-channel0
@c00200
-aaa
@28
testbench353.i_x353.i_sensorpads.clk
testbench353.i_x353.i_sensorpads.hact
testbench353.i_x353.i_sensorpads.vact
testbench353.i_x353.i_sensorpads.ihact
testbench353.i_x353.i_sensorpads.vacts
@22
testbench353.i_x353.i_sensorpads.pxd[11:0]
testbench353.i_x353.i_sensorpads.ipxd[15:0]
@1401200
-aaa
@c00200
-quantizer
-sensor_phase
@22
testbench353.i_x353.i_sensorpads.i_sensor_phase.svact_filter_cntr[7:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.en_svact_sync
testbench353.i_x353.i_sensorpads.i_sensor_phase.pre_svact
testbench353.i_x353.i_sensorpads.i_sensor_phase.pre_svact_d
testbench353.i_x353.i_sensorpads.i_sensor_phase.svact
@800022
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_q0_d[3:0]
@28
(3)testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_q0_d[3:0]
@1001200
-group_end
@800028
testbench353.i_x353.i_sensorpads.i_sensor_phase.shact_zero[1:0]
@28
(0)testbench353.i_x353.i_sensorpads.i_sensor_phase.shact_zero[1:0]
@1001200
-group_end
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_selected_2_cycles
testbench353.i_x353.i_sensorpads.i_sensor_phase.pre_shact
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_regen
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_regen_isync
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_regen_sync
testbench353.i_x353.i_sensorpads.clk_sel
testbench353.i_x353.i_sensorpads.i_sensor_phase.iclk
testbench353.i_x353.i_sensorpads.i_sensor_phase.wcmd
testbench353.i_x353.i_sensorpads.i_sensor_phase.dcm_en
testbench353.i_x353.i_sensorpads.i_sensor_phase.dcm_rst
testbench353.i_x353.i_sensorpads.i_sensor_phase.sync_alt
testbench353.i_x353.BPF
testbench353.i_sensor12bits.DCLK
testbench353.i_x353.i_sensorpads.i_sensor_phase.wcmd
@22
testbench353.i_x353.idi[31:0]
testbench353.i_x353.i_sensorpads.i_sensor_phase.cmd[5:0]
testbench353.i_x353.PXD[9:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.HACT
testbench353.i_x353.i_sensorpads.i_sensor_phase.VACT
testbench353.i_x353.i_sensorpads.i_sensor_phase.mode_12bits
testbench353.i_x353.i_sensorpads.i_sensor_phase.mode_14bits
testbench353.i_x353.i_sensorpads.i_sensor_phase.mode_alt
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_vd
testbench353.i_x353.i_sensorpads.i_sensor_phase.gclk_idata
testbench353.i_x353.i_sensorpads.i_sensor_phase.en_idata
testbench353.i_x353.i_sensorpads.i_sensor_phase.sclk
testbench353.i_x353.i_sensorpads.i_sensor_phase.vact_vd
testbench353.i_x353.i_sensorpads.i_sensor_phase.phase_hact_sel_sync[2:0]
testbench353.i_x353.i_sensorpads.i_sensor_phase.phase_hact_sel[2:0]
testbench353.i_x353.i_sensorpads.i_sensor_phase.vact_selected_2_cycles
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_selected
testbench353.i_x353.i_sensorpads.i_sensor_phase.shact
testbench353.i_x353.i_sensorpads.i_sensor_phase.svact
@22
testbench353.i_x353.i_sensorpads.i_sensor_phase.sdo[13:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.sim_rst
testbench353.i_x353.i_sensorpads.i_sensor_phase.reset_fifo_in_cntr
@22
testbench353.i_x353.i_sensorpads.i_sensor_phase.idi14[13:0]
testbench353.i_x353.i_sensorpads.i_sensor_phase.fifo_data_in_addr[3:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_selected_2_cycles
@22
testbench353.i_x353.i_sensorpads.i_sensor_phase.fifo_hact_in_addr[3:0]
testbench353.i_x353.i_sensorpads.i_sensor_phase.fifo_data_in_addr_saved[3:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.dcm_done
testbench353.i_x353.i_sensorpads.i_sensor_phase.reset_out_fifo
@22
testbench353.i_x353.i_sensorpads.i_sensor_phase.fifo_out_addr[3:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.dcm_rst_cmd
@800028
testbench353.i_x353.i_sensorpads.i_sensor_phase.dcm_in_locked[1:0]
@28
(0)testbench353.i_x353.i_sensorpads.i_sensor_phase.dcm_in_locked[1:0]
@1001200
-group_end
@22
testbench353.i_x353.i_sensorpads.i_sensor_phase.dcm_locked_cntr[3:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.dcm_fifo_locked
testbench353.i_x353.i_sensorpads.i_sensor_phase.locked
testbench353.i_x353.i_sensorpads.i_sensor_phase.pre_shact
@22
testbench353.i_x353.i_sensorpads.i_sensor_phase.pre_sdo[13:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.reset_fifo_in_cntr
@22
testbench353.i_x353.i_sensorpads.hact_length[13:0]
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_count[13:0]
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.hact_count_zero
@1401200
-sensor_phase
@c00200
-hist
@800022
testbench353.i_x353.i_histogram.dvld2x[3:0]
@28
(0)testbench353.i_x353.i_histogram.dvld2x[3:0]
(1)testbench353.i_x353.i_histogram.dvld2x[3:0]
(2)testbench353.i_x353.i_histogram.dvld2x[3:0]
(3)testbench353.i_x353.i_histogram.dvld2x[3:0]
@22
testbench353.i_x353.i_histogram.minus_pos_left[13:1]
@28
testbench353.i_x353.i_histogram.pos_left_is_zero
@22
testbench353.i_x353.i_histogram.pos_left[13:1]
testbench353.i_x353.i_histogram.size_width[13:1]
testbench353.i_x353.i_histogram.pix_cntr[13:1]
@1001200
-group_end
@c00028
testbench353.i_x353.i_histogram.line_run_s[2:0]
@28
(0)testbench353.i_x353.i_histogram.line_run_s[2:0]
(1)testbench353.i_x353.i_histogram.line_run_s[2:0]
(2)testbench353.i_x353.i_histogram.line_run_s[2:0]
@1401200
-group_end
@28
testbench353.i_x353.i_histogram.line_start
testbench353.i_x353.i_histogram.line_start_posl_zero
testbench353.i_x353.i_histogram.line_started
testbench353.i_x353.i_histogram.line_ended
testbench353.i_x353.i_histogram.window_on
@800022
testbench353.i_x353.i_histogram.hist_seq[5:0]
@28
(0)testbench353.i_x353.i_histogram.hist_seq[5:0]
(1)testbench353.i_x353.i_histogram.hist_seq[5:0]
(2)testbench353.i_x353.i_histogram.hist_seq[5:0]
(3)testbench353.i_x353.i_histogram.hist_seq[5:0]
(4)testbench353.i_x353.i_histogram.hist_seq[5:0]
(5)testbench353.i_x353.i_histogram.hist_seq[5:0]
@1001200
-group_end
@28
testbench353.i_x353.i_histogram.line_end
testbench353.i_x353.i_sensortrig.ff_count_eq0
testbench353.i_x353.i_sensortrig.vacts_in
testbench353.i_x353.i_sensortrig.state3
testbench353.i_x353.i_sensortrig.xfer_over
testbench353.i_x353.i_sensortrig.done
@22
testbench353.i_x353.i_sensortrig.nlines[13:0]
testbench353.i_x353.i_sensortrig.lines_left[13:0]
@28
testbench353.i_x353.line_run
@22
testbench353.i_x353.ipxd_ts[15:0]
@800028
testbench353.i_x353.sr_sensortrig[2:0]
@28
(0)testbench353.i_x353.sr_sensortrig[2:0]
(1)testbench353.i_x353.sr_sensortrig[2:0]
(2)testbench353.i_x353.sr_sensortrig[2:0]
testbench353.i_x353.line_run
@1001200
-group_end
@28
testbench353.i_x353.da_hist_next
testbench353.i_x353.i_histogram.frame_start
testbench353.i_x353.i_histogram.frame_started
testbench353.i_x353.i_histogram.hist_bank
testbench353.i_x353.i_histogram.di_vld
@22
testbench353.i_x353.i_histogram.di[15:0]
@28
testbench353.i_x353.i_histogram.window_on
testbench353.i_x353.i_sensortrig.vacts_in
testbench353.i_x353.i_sensortrig.vacts_out
testbench353.i_x353.i_histogram.init_hist
testbench353.i_x353.i_histogram.init_hist_d
testbench353.i_x353.i_histogram.frame_run
@800028
testbench353.i_x353.i_histogram.frame_run_s[2:0]
@28
(0)testbench353.i_x353.i_histogram.frame_run_s[2:0]
(1)testbench353.i_x353.i_histogram.frame_run_s[2:0]
(2)testbench353.i_x353.i_histogram.frame_run_s[2:0]
@1001200
-group_end
@28
testbench353.i_x353.i_histogram.pclk2x
testbench353.i_x353.frame_run
testbench353.i_x353.i_sensortrig.state2
testbench353.i_x353.i_sensortrig.xfer_over
testbench353.i_x353.i_sensortrig.xfer_over_irq
testbench353.i_x353.i_sensortrig.pclk
@1401200
-hist
@c00200
-stuffer_was_ready_early
@28
testbench353.i_x353.i_compressor.i_huffman.en2x
testbench353.i_x353.i_compressor.i_stuffer.rdy_rega
testbench353.i_x353.i_compressor.i_stuffer.rdy_regb
testbench353.i_x353.i_compressor.i_stuffer.rdy_regc
testbench353.i_x353.i_compressor.i_stuffer.rdy_regd
testbench353.i_x353.i_compressor.i_huffman.rdy
testbench353.i_x353.i_compressor.i_huffman.stuffer_was_rdy
testbench353.i_x353.i_compressor.i_huffman.i_huff_fifo.dav
testbench353.i_x353.i_compressor.i_huffman.i_huff_fifo.want_read
testbench353.i_x353.i_compressor.i_huffman.i_huff_fifo.re_r
testbench353.i_x353.i_compressor.i_huffman.tables_re
testbench353.i_x353.i_compressor.i_huffman.i_huff_fifo.load_q
testbench353.i_x353.i_compressor.i_huffman.i_huff_fifo.clk
@1401200
-stuffer_was_ready_early
@c00200
-compressor
@c00022
testbench353.i_x353.i_mcontr.i_descrproc.dest_bond_en[3:0]
@28
(0)testbench353.i_x353.i_mcontr.i_descrproc.dest_bond_en[3:0]
(1)testbench353.i_x353.i_mcontr.i_descrproc.dest_bond_en[3:0]
(2)testbench353.i_x353.i_mcontr.i_descrproc.dest_bond_en[3:0]
(3)testbench353.i_x353.i_mcontr.i_descrproc.dest_bond_en[3:0]
@1401200
-group_end
@c00022
testbench353.i_x353.i_mcontr.i_descrproc.bonded[3:0]
@28
(0)testbench353.i_x353.i_mcontr.i_descrproc.bonded[3:0]
(1)testbench353.i_x353.i_mcontr.i_descrproc.bonded[3:0]
(2)testbench353.i_x353.i_mcontr.i_descrproc.bonded[3:0]
(3)testbench353.i_x353.i_mcontr.i_descrproc.bonded[3:0]
@1401200
-group_end
@28
testbench353.i_x353.i_compressor.bonded
testbench353.i_x353.i_compressor.i_compr_ifc.rcs[1:0]
@22
testbench353.i_x353.i_compressor.i_compr_ifc.ntiles[17:0]
testbench353.i_x353.i_compressor.i_color_proc.bcntr[17:0]
testbench353.i_x353.i_compressor.i_color_proc.nblocks[17:0]
@28
testbench353.i_x353.HACT
testbench353.i_x353.i_compressor.chInitOnehot2
testbench353.i_x353.i_compressor.cmprs_en
testbench353.i_x353.i_compressor.inc_sdrama
testbench353.i_x353.i_compressor.pxrdy
testbench353.i_x353.i_compressor.nxtpage
testbench353.i_x353.i_compressor.eot
testbench353.i_x353.i_compressor.confirmFrame2Compressor
testbench353.i_x353.i_compressor.compressor_starting[1:0]
testbench353.i_x353.i_compressor.compressor_started
testbench353.i_x353.i_compressor.pre_go_single
testbench353.i_x353.i_compressor.go_single
testbench353.i_x353.i_compressor.go_rq
testbench353.i_x353.i_compressor.vacts_long
testbench353.i_x353.i_compressor.vlong
testbench353.i_x353.i_compressor.is_compressing
testbench353.i_x353.i_compressor.is_compressing_d
testbench353.i_x353.i_mcontr.readNextFrame2
testbench353.i_x353.i_compressor.i_color_proc.bcntrIsZero
@22
testbench353.i_x353.i_compressor.i_stuffer.imgsz32[19:0]
testbench353.i_x353.i_compressor.i_stuffer.imgptr[23:0]
@28
testbench353.i_x353.i_compressor.i_stuffer.inc_imgsz32
testbench353.i_x353.i_compressor.i_stuffer.inc_size_count2316
testbench353.i_x353.i_compressor.flush
testbench353.i_x353.i_compressor.done_compress
testbench353.i_x353.i_compressor.clk
testbench353.i_x353.i_compressor.stuffer_done
testbench353.i_x353.i_compressor.i_compr_ifc.cmprs_en_s
@22
testbench353.i_x353.i_compressor.i_compr_ifc.cmprs_en_timeout[6:0]
@28
testbench353.i_x353.i_compressor.i_compr_ifc.cmprs_en_finish
testbench353.i_x353.i_compressor.i_compr_ifc.cmprs_en_long
testbench353.i_x353.i_compressor.i_compr_ifc.force_flush1
testbench353.i_x353.i_compressor.i_compr_ifc.force_flush
testbench353.i_x353.i_compressor.i_stuffer.flushing
testbench353.i_x353.i_compressor.i_stuffer.en
testbench353.i_x353.i_compressor.i_stuffer.flush_end
@22
testbench353.i_x353.i_compressor.i_stuffer.stage2_bits[4:0]
@28
testbench353.i_x353.i_compressor.i_stuffer.rdy
testbench353.i_x353.i_compressor.i_stuffer.stb
testbench353.i_x353.i_compressor.i_stuffer.stage1_full
testbench353.i_x353.i_compressor.stuffer_done
testbench353.i_x353.i_compressor.i_stuffer.size_out[2:0]
testbench353.i_x353.i_compressor.i_stuffer.flush_end
testbench353.i_x353.i_compressor.i_stuffer.start_sizeout
testbench353.i_x353.i_compressor.i_stuffer.done
@22
testbench353.i_x353.i_compressor.i_stuffer.etrax_dma[3:0]
@28
testbench353.i_x353.i_compressor.i_stuffer.time_out
testbench353.i_x353.i_compressor.i_stuffer.trailer
testbench353.i_x353.i_compressor.i_stuffer.start_time_out
testbench353.i_x353.i_compressor.abort_compress
@1401200
-group_end
@c00200
-irq_smart
@28
testbench353.i_x353.i_irq_smart.frame_sync
testbench353.i_x353.i_irq_smart.irq
testbench353.i_x353.i_irq_smart.fifo_empty
testbench353.i_x353.i_irq_smart.is_compressing
testbench353.i_x353.i_irq_smart.compressor_done
testbench353.i_x353.i_irq_smart.is_finishing
testbench353.i_x353.i_irq_smart.delaying_done_irq
testbench353.i_x353.i_irq_smart.fs_postponed
testbench353.i_x353.i_irq_smart.frame_sync
testbench353.i_x353.i_irq_smart.compressor_done
testbench353.i_x353.i_irq_smart.compressor_fifo_done
testbench353.i_x353.i_irq_smart.done_request
testbench353.i_x353.i_irq_smart.rst
testbench353.i_x353.i_irq_smart.sclk
testbench353.i_x353.i_irq_smart.wait_fifo
testbench353.i_x353.i_irq_smart.wait_frame_sync
@1401200
-irq_smart
@c00200
-noMoreData
@22
testbench353.i_x353.i_compressor.ntiles[17:0]
testbench353.i_x353.i_compressor.i_color_proc.nblocks[17:0]
testbench353.i_x353.i_compressor.i_color_proc.bcntr[17:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.bcntrIsZero
testbench353.i_x353.i_compressor.i_color_proc.eot
testbench353.i_x353.i_mcontr.readNextFrame2
@c00022
testbench353.i_x353.i_mcontr.i_descrproc.nextBlocksEn[3:0]
@28
(0)testbench353.i_x353.i_mcontr.i_descrproc.nextBlocksEn[3:0]
(1)testbench353.i_x353.i_mcontr.i_descrproc.nextBlocksEn[3:0]
(2)testbench353.i_x353.i_mcontr.i_descrproc.nextBlocksEn[3:0]
(3)testbench353.i_x353.i_mcontr.i_descrproc.nextBlocksEn[3:0]
@1401200
-group_end
@22
testbench353.i_x353.i_mcontr.i_descrproc.tileX[9:0]
testbench353.i_x353.i_mcontr.i_descrproc.tileY[13:0]
testbench353.SDD[15:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.memWasInit
testbench353.i_x353.i_compressor.go_rq
testbench353.i_x353.i_compressor.not_vlong1_or_not_bonded
testbench353.i_x353.i_compressor.is_compressing
testbench353.i_x353.i_compressor.i_color_proc.eof_rq
testbench353.i_x353.i_compressor.noMoreData
testbench353.i_x353.i_compressor.eot_real
testbench353.i_x353.i_compressor.eot
testbench353.i_x353.i_compressor.go_single
testbench353.i_x353.i_compressor.i_color_proc.go
testbench353.i_x353.i_compressor.i_color_proc.sdram_next
testbench353.i_x353.i_compressor.confirm
testbench353.i_x353.i_compressor.i_color_proc.sdram_rdy
testbench353.i_x353.i_compressor.inc_sdrama
testbench353.i_x353.i_compressor.clk
testbench353.i_x353.cb_break_frames
testbench353.i_x353.i_compressor.i_color_proc.noMoreData
testbench353.i_x353.i_compressor.nextBlocksEn
testbench353.i_x353.i_compressor.nextBlocksEnS[1:0]
testbench353.i_x353.i_compressor.confirm_en
testbench353.i_x353.i_compressor.confirm
testbench353.i_x353.i_compressor.pxrdy
testbench353.i_x353.i_compressor.i_color_proc.tim2next
@1401200
-noMoreData
@c00200
-vacts_filter
@28
testbench353.i_x353.i_sensorpads.i_sensor_phase.reset_fifo_in_cntr
@800022
testbench353.i_sensor12bits.state[3:0]
@28
(0)testbench353.i_sensor12bits.state[3:0]
(1)testbench353.i_sensor12bits.state[3:0]
(2)testbench353.i_sensor12bits.state[3:0]
(3)testbench353.i_sensor12bits.state[3:0]
@1001200
-group_end
@28
testbench353.i_sensor12bits.stopped
testbench353.i_sensor12bits.stoppedd
testbench353.i_sensor12bits.ARO
testbench353.i_x353.VACT
testbench353.i_x353.i_sensortrig.vacts_dly_on
testbench353.i_x353.i_sensortrig.nxt_lf
testbench353.i_x353.i_sensortrig.nxt_line
@22
testbench353.i_x353.i_sensortrig.cmd[3:0]
testbench353.i_x353.i_sensortrig.vact_dly[13:0]
@28
testbench353.i_x353.i_sensortrig.framesync_dly
testbench353.i_x353.i_sensorpads.vacts
testbench353.i_x353.cb_sensor_trigger
testbench353.i_x353.i_sensorpads.i_sensor_phase.en_svact
testbench353.i_x353.i_sensorpads.i_sensor_phase.pre_svact_outfifo
testbench353.i_x353.i_sensorpads.i_sensor_phase.pre_svact
testbench353.i_x353.i_sensorpads.i_sensor_phase.pre_svact_d
testbench353.i_x353.i_sensorpads.i_sensor_phase.svact
@22
testbench353.i_x353.i_camsync.wen[3:0]
@28
testbench353.i_x353.i_camsync.start
testbench353.i_x353.i_camsync.trigger1
testbench353.i_x353.i_camsync.trigger
testbench353.i_x353.i_camsync.input_use_intern
testbench353.i_x353.i_camsync.trigger_condition
@22
testbench353.i_x353.i_camsync.repeat_period[31:0]
testbench353.i_x353.i_camsync.restart_cntr[31:0]
@28
testbench353.i_x353.sensor_trigger
testbench353.i_x353.ARO
testbench353.i_x353.vacts
testbench353.i_x353.vacts_every
testbench353.i_x353.i_sensortrig.vacts_in
testbench353.i_x353.i_sensortrig.pre_vacts_out
testbench353.i_x353.i_sensortrig.pre_vacts_out_d
testbench353.i_x353.i_sensortrig.vacts_dly_on
testbench353.i_x353.i_sensortrig.vacts_out
testbench353.i_x353.vacts_long
testbench353.i_x353.i_sensorpads.i_sensor_phase.en_svact
@22
testbench353.i_x353.i_sensorpads.i_sensor_phase.svact_filter_cntr[7:0]
@28
testbench353.i_x353.i_camsync.outsync
@22
testbench353.i_x353.io_da[11:0]
testbench353.i_x353.io_da_en[11:0]
@800022
testbench353.i_x353.EXT[11:0]
@28
(0)testbench353.i_x353.EXT[11:0]
(1)testbench353.i_x353.EXT[11:0]
(2)testbench353.i_x353.EXT[11:0]
(3)testbench353.i_x353.EXT[11:0]
(4)testbench353.i_x353.EXT[11:0]
(5)testbench353.i_x353.EXT[11:0]
(6)testbench353.i_x353.EXT[11:0]
(7)testbench353.i_x353.EXT[11:0]
(8)testbench353.i_x353.EXT[11:0]
(9)testbench353.i_x353.EXT[11:0]
(10)testbench353.i_x353.EXT[11:0]
(11)testbench353.i_x353.EXT[11:0]
@1001200
-group_end
@1401200
-vacts_filter
@c00200
-compressor-memory
@28
testbench353.BLOCK_HACT
testbench353.i_x353.HACT
testbench353.i_x353.i_compressor.cmprs_start
testbench353.i_x353.vacts
testbench353.i_x353.i_compressor.vacts_long
testbench353.i_x353.i_compressor.not_vlong1_or_not_bonded
testbench353.i_x353.i_compressor.confirmFrame2Compressor
testbench353.i_x353.i_compressor.go_rq
testbench353.i_x353.i_compressor.restart_memory
testbench353.i_x353.i_compressor.noMoreData
testbench353.i_x353.i_compressor.nextBlocksEn
testbench353.i_x353.i_compressor.go_single
testbench353.i_x353.i_compressor.is_compressing
@22
testbench353.i_x353.i_compressor.i_color_proc.bcntr[17:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.bcntrIsZero
testbench353.i_x353.i_compressor.i_color_proc.transfer_ended
testbench353.i_x353.i_compressor.i_stuffer.flush_end
@c00028
testbench353.i_x353.i_compressor.i_stuffer.size_out[2:0]
@28
(0)testbench353.i_x353.i_compressor.i_stuffer.size_out[2:0]
(1)testbench353.i_x353.i_compressor.i_stuffer.size_out[2:0]
(2)testbench353.i_x353.i_compressor.i_stuffer.size_out[2:0]
@1401200
-group_end
@28
testbench353.i_x353.i_compressor.i_stuffer.flush_end_delayed
testbench353.i_x353.i_compressor.i_stuffer.pre_flush_end_delayed
testbench353.i_x353.compressor_done_pulse
testbench353.i_x353.i_compressor.i_stuffer.done
testbench353.i_x353.compressor_started
@22
testbench353.i_x353.debug_mcontr_reset_data[31:0]
testbench353.i_x353.debug_mcontr_count[12:0]
testbench353.i_x353.debug_mcontr_count_start[15:0]
testbench353.i_x353.debug_mcontr_count_end[15:0]
@c00022
testbench353.i_x353.i_mcontr.i_descrproc.restart[3:0]
@28
(0)testbench353.i_x353.i_mcontr.i_descrproc.restart[3:0]
(1)testbench353.i_x353.i_mcontr.i_descrproc.restart[3:0]
(2)testbench353.i_x353.i_mcontr.i_descrproc.restart[3:0]
(3)testbench353.i_x353.i_mcontr.i_descrproc.restart[3:0]
testbench353.i_x353.i_compressor.i_color_proc.memWasInit
testbench353.i_x353.i_compressor.chInitOnehot2
testbench353.i_x353.cb_reset_mcontr
@1401200
-group_end
@22
testbench353.i_x353.i_cmd_sequencer.frame_no[2:0]
@28
testbench353.i_x353.VACT
testbench353.i_x353.HACT
testbench353.i_x353.i_compressor.eot
testbench353.i_x353.i_compressor.done_compress_pulse
testbench353.i_x353.i_irq_smart.irq
@22
testbench353.i_x353.imgptr[23:0]
testbench353.i_x353.imgptr[23:0]
testbench353.i_x353.i_compressor.ntiles[17:0]
@28
testbench353.i_x353.i_compressor.i_color_proc.eof_rq
testbench353.i_x353.i_mcontr.i_descrproc.clk
testbench353.i_x353.i_mcontr.i_descrproc.last_lines_reg
testbench353.i_x353.i_mcontr.i_descrproc.last_lines_source
testbench353.i_x353.i_mcontr.i_descrproc.stepsIe
testbench353.i_x353.i_mcontr.i_descrproc.stepsEn012
testbench353.i_x353.i_mcontr.i_descrproc.rNum[1:0]
testbench353.i_x353.i_compressor.cmprs_repeat
testbench353.i_x353.i_compressor.i_color_proc.tim2next
testbench353.i_x353.i_compressor.pxrdy
testbench353.i_x353.i_compressor.i_color_proc.tim2next
testbench353.i_x353.i_compressor.done_compress
testbench353.i_x353.i_compressor.done_input
testbench353.i_x353.i_compressor.eot_real
@22
testbench353.i_x353.i_mcontr.i_descrproc.tileX[9:0]
testbench353.i_x353.i_mcontr.i_descrproc.tileY[13:0]
@28
testbench353.i_x353.i_mcontr.i_descrproc.restart_en
testbench353.i_x353.i_compressor.i_color_proc.inc_sdrama
testbench353.i_x353.i_compressor.nxtpage
testbench353.i_x353.cb_break_frames
testbench353.i_x353.cb_reset_mcontr
testbench353.i_x353.cb_hact_regen
testbench353.i_x353.cb_use_sensor_clk
@c00022
testbench353.i_x353.chInitOnehot[3:0]
@28
(0)testbench353.i_x353.chInitOnehot[3:0]
(1)testbench353.i_x353.chInitOnehot[3:0]
(2)testbench353.i_x353.chInitOnehot[3:0]
(3)testbench353.i_x353.chInitOnehot[3:0]
@1401200
-group_end
@28
testbench353.i_x353.i_compressor.chInitOnehot2
@c00022
testbench353.i_x353.i_mcontr.chReqInit[3:0]
@28
(0)testbench353.i_x353.i_mcontr.chReqInit[3:0]
(1)testbench353.i_x353.i_mcontr.chReqInit[3:0]
(2)testbench353.i_x353.i_mcontr.chReqInit[3:0]
(3)testbench353.i_x353.i_mcontr.chReqInit[3:0]
testbench353.i_x353.i_mcontr.i_descrproc.rqInitS
testbench353.i_x353.i_mcontr.i_descrproc.chInitNum[1:0]
@22
testbench353.i_x353.i_mcontr.i_descrproc.extRestartRq[3:0]
@28
testbench353.i_x353.i_compressor.restart_memory
@1401200
-group_end
@28
testbench353.i_x353.i_compressor.i_color_proc.clk
@22
testbench353.i_x353.debug_mcontr_count[12:0]
@28
testbench353.i_x353.compressor_started
testbench353.i_x353.compressor_done_input
testbench353.i_x353.sr_ch2rdy
@22
testbench353.i_x353.i_compressor.i_color_proc.seq_cntr[8:0]
@28
testbench353.i_x353.i_mcontr.i_descrproc.setLineNumSource
@22
testbench353.i_x353.i_mcontr.i_descrproc.lineNumSource[13:0]
testbench353.i_x353.i_mcontr.i_descrproc.tileX[9:0]
testbench353.i_x353.i_mcontr.i_descrproc.rnTilesY[13:0]
testbench353.i_x353.i_mcontr.i_descrproc.descr_dyn[21:0]
@28
testbench353.i_x353.i_mcontr.i_descrproc.stepsEn012
testbench353.i_x353.i_mcontr.i_descrproc.srcAtStart
testbench353.i_x353.i_mcontr.i_descrproc.nxtTFw
testbench353.i_x353.i_mcontr.i_descrproc.nxtTFr
testbench353.i_x353.i_mcontr.i_descrproc.nxtTL
@22
testbench353.i_x353.i_mcontr.i_descrproc.tileY[13:0]
@28
testbench353.i_x353.i_mcontr.i_descrproc.setLineNumDest
@22
testbench353.i_x353.i_mcontr.i_descrproc.lineNumDest[13:0]
testbench353.i_x353.i_mcontr.i_descrproc.prevStripSource[13:4]
@28
testbench353.i_x353.i_mcontr.i_descrproc.lastLineDest
@22
testbench353.i_x353.i_mcontr.i_descrproc.descr_stat[17:0]
@28
testbench353.i_x353.i_mcontr.i_descrproc.last_lines_source
testbench353.i_x353.i_mcontr.i_descrproc.notEnoughData
testbench353.i_x353.i_mcontr.i_descrproc.updSuspXfer
testbench353.i_x353.i_mcontr.stch2
@c00028
testbench353.i_x353.i_mcontr.i_descrproc.nxtTF_p[2:0]
@28
(0)testbench353.i_x353.i_mcontr.i_descrproc.nxtTF_p[2:0]
(1)testbench353.i_x353.i_mcontr.i_descrproc.nxtTF_p[2:0]
(2)testbench353.i_x353.i_mcontr.i_descrproc.nxtTF_p[2:0]
@1401200
-group_end
@c00022
testbench353.i_x353.i_mcontr.i_descrproc.stepsEn[3:0]
@28
(0)testbench353.i_x353.i_mcontr.i_descrproc.stepsEn[3:0]
(1)testbench353.i_x353.i_mcontr.i_descrproc.stepsEn[3:0]
(2)testbench353.i_x353.i_mcontr.i_descrproc.stepsEn[3:0]
(3)testbench353.i_x353.i_mcontr.i_descrproc.stepsEn[3:0]
@1401200
-group_end
@28
testbench353.i_x353.i_mcontr.i_descrproc.first_tile
testbench353.i_x353.i_mcontr.i_descrproc.first_tile_dest
@22
testbench353.i_x353.i_mcontr.i_descrproc.descr_dyn[21:0]
testbench353.i_x353.i_mcontr.i_descrproc.tileY[13:0]
@1401200
-compressor-memory
@c00200
-camsync
@28
testbench353.i_x353.i_camsync.start
testbench353.i_x353.i_camsync.start_dly
testbench353.i_x353.i_camsync.dly_cntr_run
testbench353.i_x353.ARO
@22
testbench353.i_x353.psec[31:0]
testbench353.i_x353.pusec[19:0]
testbench353.i_x353.i_camsync.ts_rcv_usec[19:0]
testbench353.i_x353.i_compressor.i_stuffer.usec_r[19:0]
@28
testbench353.i_x353.i_compressor.go_single
testbench353.i_x353.i_compressor.compressor_started
testbench353.i_x353.i_compressor.eot_2x_n
testbench353.i_x353.i_camsync.pclk
testbench353.i_x353.i_camsync.outsync
testbench353.external_sync_line
@c00022
testbench353.i_x353.EXT[11:0]
@28
(0)testbench353.i_x353.EXT[11:0]
(1)testbench353.i_x353.EXT[11:0]
(2)testbench353.i_x353.EXT[11:0]
(3)testbench353.i_x353.EXT[11:0]
(4)testbench353.i_x353.EXT[11:0]
(5)testbench353.i_x353.EXT[11:0]
(6)testbench353.i_x353.EXT[11:0]
(7)testbench353.i_x353.EXT[11:0]
(8)testbench353.i_x353.EXT[11:0]
(9)testbench353.i_x353.EXT[11:0]
(10)testbench353.i_x353.EXT[11:0]
(11)testbench353.i_x353.EXT[11:0]
@1401200
-group_end
@28
testbench353.i_x353.i_camsync.ts_external_pclk
testbench353.i_x353.i_camsync.ts_snd_en
testbench353.i_x353.i_camsync.ts_snap
testbench353.i_x353.i_camsync.input_use_intern
@22
testbench353.i_x353.i_camsync.input_pattern[11:0]
testbench353.i_x353.i_camsync.input_use[11:0]
testbench353.i_x353.i_camsync.repeat_period[31:0]
@28
testbench353.i_x353.i_camsync.pre_start0
testbench353.i_x353.i_camsync.pre_set_bit
testbench353.i_x353.i_camsync.pre_set_period
testbench353.i_x353.i_camsync.start
@22
testbench353.i_x353.i_camsync.bit_length[7:0]
@28
testbench353.i_x353.i_camsync.trigger1
testbench353.i_x353.i_camsync.trigger1_dly16
testbench353.i_x353.i_camsync.dly_cntr_run
@22
testbench353.i_x353.i_camsync.bit_snd_counter[5:0]
@28
testbench353.i_x353.i_camsync.trigger_condition
@22
testbench353.i_x353.i_camsync.trigger_filter_cntr[6:0]
@28
testbench353.i_x353.i_camsync.trigger_condition_filtered
@22
testbench353.i_x353.i_camsync.sr_rcv_first[31:0]
testbench353.i_x353.i_camsync.sr_rcv_second[31:0]
testbench353.i_x353.i_camsync.bit_rcv_duration[7:0]
@28
testbench353.i_x353.i_camsync.rcv_run
testbench353.i_x353.i_camsync.rcv_run_or_deaf
testbench353.i_x353.i_camsync.rcv_done_rq
testbench353.i_x353.i_camsync.rcv_done
testbench353.i_x353.i_camsync.rcv_error
@1401200
-camsync
@28
testbench353.i_x353.i_compressor.i_quantizator.clk
testbench353.i_x353.i_compressor.i_quantizator.sclk
testbench353.i_x353.i_compressor.i_quantizator.ctype
testbench353.i_x353.i_compressor.i_quantizator.ctypei
testbench353.i_x353.i_compressor.i_quantizator.stb
@22
testbench353.i_x353.i_compressor.i_quantizator.start[5:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.start_a
testbench353.i_x353.i_compressor.i_quantizator.dcc_stb
testbench353.i_x353.i_compressor.i_quantizator.start_z
testbench353.i_x353.i_compressor.i_quantizator.start_out
@22
testbench353.i_x353.i_compressor.i_quantizator.block_mem_o[15:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.block_mem_ra[2:0]
testbench353.i_x353.i_compressor.i_quantizator.block_mem_wa[2:0]
testbench353.i_x353.i_compressor.i_quantizator.block_mem_wa_save[2:0]
testbench353.i_x353.i_compressor.i_quantizator.color_first
testbench353.i_x353.i_compressor.i_quantizator.copy_dc_tdo
testbench353.i_x353.i_compressor.i_quantizator.coring_num[2:0]
@22
testbench353.i_x353.i_compressor.i_quantizator.d1[12:0]
testbench353.i_x353.i_compressor.i_quantizator.d2[12:0]
testbench353.i_x353.i_compressor.i_quantizator.d3[12:0]
testbench353.i_x353.i_compressor.i_quantizator.d2_dct[10:0]
testbench353.i_x353.i_compressor.i_quantizator.dc1[8:0]
testbench353.i_x353.i_compressor.i_quantizator.dc[8:0]
testbench353.i_x353.i_compressor.i_quantizator.tba[9:0]
testbench353.i_x353.i_compressor.i_quantizator.tbac[3:0]
testbench353.i_x353.i_compressor.i_quantizator.tdco[3:0]
testbench353.i_x353.i_compressor.i_quantizator.tdo[15:0]
testbench353.i_x353.i_compressor.i_quantizator.tdor[15:0]
testbench353.i_x353.i_compressor.i_quantizator.qmul[27:0]
testbench353.i_x353.i_compressor.i_quantizator.qmulr[20:0]
testbench353.i_x353.i_compressor.i_quantizator.qdo0[12:0]
testbench353.i_x353.i_compressor.i_quantizator.qdo[12:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.zwe
testbench353.i_x353.i_compressor.i_quantizator.coring_range
testbench353.i_x353.i_compressor.i_quantizator.coring_sel[2:0]
testbench353.i_x353.i_compressor.i_quantizator.ctype_prev[1:0]
@22
testbench353.i_x353.i_compressor.i_quantizator.dc_tdo[15:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.dcc_Y
@22
testbench353.i_x353.i_compressor.i_quantizator.dcc_acc[12:0]
testbench353.i_x353.i_compressor.i_quantizator.dcc_data[15:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.dcc_en
testbench353.i_x353.i_compressor.i_quantizator.dcc_first
testbench353.i_x353.i_compressor.i_quantizator.dcc_run
testbench353.i_x353.i_compressor.i_quantizator.dcc_vld
@22
testbench353.i_x353.i_compressor.i_quantizator.dci[8:0]
testbench353.i_x353.i_compressor.i_quantizator.di[12:0]
testbench353.i_x353.i_compressor.i_quantizator.do[12:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.ds
testbench353.i_x353.i_compressor.i_quantizator.dv
testbench353.i_x353.i_compressor.i_quantizator.en
testbench353.i_x353.i_compressor.i_quantizator.first_in
testbench353.i_x353.i_compressor.i_quantizator.first_interm
testbench353.i_x353.i_compressor.i_quantizator.first_out
testbench353.i_x353.i_compressor.i_quantizator.first_stb
@22
testbench353.i_x353.i_compressor.i_quantizator.hfc_acc[12:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.hfc_copy
testbench353.i_x353.i_compressor.i_quantizator.hfc_en
testbench353.i_x353.i_compressor.i_quantizator.hfc_sel[2:0]
@22
testbench353.i_x353.i_compressor.i_quantizator.n000[7:0]
testbench353.i_x353.i_compressor.i_quantizator.n255[7:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.next_dv
@22
testbench353.i_x353.i_compressor.i_quantizator.pre_dc_tdo[15:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.pre_start
testbench353.i_x353.i_compressor.i_quantizator.rpage
testbench353.i_x353.i_compressor.i_quantizator.sel_satnum
@22
testbench353.i_x353.i_compressor.i_quantizator.ta[8:0]
testbench353.i_x353.i_compressor.i_quantizator.tdi[15:0]
@28
testbench353.i_x353.i_compressor.i_quantizator.ts[2:0]
testbench353.i_x353.i_compressor.i_quantizator.tsi[2:0]
testbench353.i_x353.i_compressor.i_quantizator.twce
testbench353.i_x353.i_compressor.i_quantizator.twce_d
testbench353.i_x353.i_compressor.i_quantizator.twqe
testbench353.i_x353.i_compressor.i_quantizator.twqe_d
testbench353.i_x353.i_compressor.i_quantizator.wpage
@22
testbench353.i_x353.i_compressor.i_quantizator.zigzag_q[15:0]
testbench353.i_x353.i_compressor.i_quantizator.zra[5:0]
testbench353.i_x353.i_compressor.i_quantizator.zwa[5:0]
<<<<<<< x353_1.sav
@1401200
-quantizer
@c00200
-IMU
@22
testbench353.i_x353.i_imu_logger.ts_rcv_sec[31:0]
testbench353.i_x353.i_imu_logger.ts_rcv_usec[19:0]
@28
testbench353.i_x353.i_imu_logger.ts_stb
@22
testbench353.i_x353.i_imu_logger.bitHalfPeriod[15:0]
testbench353.i_x353.i_imu_logger.bitHalfPeriod_mclk[15:0]
@28
testbench353.i_x353.i_imu_logger.channel[1:0]
@22
testbench353.i_x353.i_imu_logger.channel_next[3:0]
testbench353.i_x353.i_imu_logger.channel_ready[3:0]
@28
testbench353.i_x353.i_imu_logger.clk
@22
testbench353.i_x353.i_imu_logger.config_gps[3:0]
testbench353.i_x353.i_imu_logger.config_gps_mclk[3:0]
testbench353.i_x353.i_imu_logger.config_gps_pre[3:0]
@28
testbench353.i_x353.i_imu_logger.config_imu[1:0]
testbench353.i_x353.i_imu_logger.config_imu_mclk[1:0]
testbench353.i_x353.i_imu_logger.config_imu_pre[1:0]
@22
testbench353.i_x353.i_imu_logger.config_msg[4:0]
testbench353.i_x353.i_imu_logger.config_msg_mclk[4:0]
testbench353.i_x353.i_imu_logger.config_msg_pre[4:0]
@28
testbench353.i_x353.i_imu_logger.config_rst
testbench353.i_x353.i_imu_logger.config_rst_mclk
testbench353.i_x353.i_imu_logger.config_rst_pre
testbench353.i_x353.i_imu_logger.config_syn
testbench353.i_x353.i_imu_logger.config_syn_mclk
testbench353.i_x353.i_imu_logger.config_syn_pre
@22
testbench353.i_x353.i_imu_logger.ctrl_addr[6:0]
testbench353.i_x353.i_imu_logger.data_out[15:0]
@28
testbench353.i_x353.i_imu_logger.data_out_stb
@22
testbench353.i_x353.i_imu_logger.dbg_cntr[7:0]
testbench353.i_x353.i_imu_logger.debug_state[31:0]
testbench353.i_x353.i_imu_logger.di[15:0]
testbench353.i_x353.i_imu_logger.di_d[15:0]
@28
testbench353.i_x353.i_imu_logger.enable_gps
testbench353.i_x353.i_imu_logger.enable_msg
testbench353.i_x353.i_imu_logger.enable_syn
testbench353.i_x353.i_imu_logger.enable_timestamps
@22
testbench353.i_x353.i_imu_logger.ext_di[11:0]
testbench353.i_x353.i_imu_logger.ext_do[11:0]
testbench353.i_x353.i_imu_logger.ext_en[11:0]
@28
testbench353.i_x353.i_imu_logger.ext_ts_stb[1:0]
@22
testbench353.i_x353.i_imu_logger.extts_data[15:0]
@28
testbench353.i_x353.i_imu_logger.gps_pulse1sec
testbench353.i_x353.i_imu_logger.gps_pulse1sec_d[2:0]
testbench353.i_x353.i_imu_logger.gps_pulse1sec_denoise[1:0]
@22
testbench353.i_x353.i_imu_logger.gps_pulse1sec_denoise_count[7:0]
@28
testbench353.i_x353.i_imu_logger.gps_pulse1sec_single
testbench353.i_x353.i_imu_logger.gps_ts_stb
@22
testbench353.i_x353.i_imu_logger.imu_data[15:0]
@28
testbench353.i_x353.i_imu_logger.message_trig
testbench353.i_x353.i_imu_logger.miso
testbench353.i_x353.i_imu_logger.mosi
@22
testbench353.i_x353.i_imu_logger.msg_data[15:0]
testbench353.i_x353.i_imu_logger.mux_data_final[15:0]
testbench353.i_x353.i_imu_logger.mux_data_source[15:0]
@28
testbench353.i_x353.i_imu_logger.mux_data_valid
testbench353.i_x353.i_imu_logger.mux_rdy_source
@22
testbench353.i_x353.i_imu_logger.nmea_data[15:0]
@28
testbench353.i_x353.i_imu_logger.nmea_sent_start
testbench353.i_x353.i_imu_logger.pre_message_trig
testbench353.i_x353.i_imu_logger.rs232_start
testbench353.i_x353.i_imu_logger.rs232_wait_pause
@22
testbench353.i_x353.i_imu_logger.sample_counter[23:0]
@28
testbench353.i_x353.i_imu_logger.scl
testbench353.i_x353.i_imu_logger.scl_en
testbench353.i_x353.i_imu_logger.sda
testbench353.i_x353.i_imu_logger.sda_en
@22
testbench353.i_x353.i_imu_logger.sec[31:0]
@28
testbench353.i_x353.i_imu_logger.ser_di
testbench353.i_x353.i_imu_logger.ser_do
testbench353.i_x353.i_imu_logger.ser_do_stb
@22
testbench353.i_x353.i_imu_logger.timestamp_ackn[3:0]
testbench353.i_x353.i_imu_logger.timestamp_request[3:0]
testbench353.i_x353.i_imu_logger.timestamp_request_long[3:0]
@28
testbench353.i_x353.i_imu_logger.timestamp_sel[1:0]
@22
testbench353.i_x353.i_imu_logger.timestamps_rdata[15:0]
@28
testbench353.i_x353.i_imu_logger.ts_en
@22
testbench353.i_x353.i_imu_logger.ts_rcv_sec[31:0]
testbench353.i_x353.i_imu_logger.ts_rcv_usec[19:0]
@28
testbench353.i_x353.i_imu_logger.ts_stb
testbench353.i_x353.i_imu_logger.ts_stb_rq
@22
testbench353.i_x353.i_imu_logger.usec[19:0]
@28
testbench353.i_x353.i_imu_logger.wa
testbench353.i_x353.i_imu_logger.we
testbench353.i_x353.i_imu_logger.we_bitHalfPeriod
testbench353.i_x353.i_imu_logger.we_bit_duration
testbench353.i_x353.i_imu_logger.we_config
testbench353.i_x353.i_imu_logger.we_config_gps
testbench353.i_x353.i_imu_logger.we_config_imu
testbench353.i_x353.i_imu_logger.we_config_msg
testbench353.i_x353.i_imu_logger.we_config_syn
testbench353.i_x353.i_imu_logger.we_d
testbench353.i_x353.i_imu_logger.we_gps
testbench353.i_x353.i_imu_logger.we_imu
testbench353.i_x353.i_imu_logger.we_message
testbench353.i_x353.i_imu_logger.we_period
testbench353.i_x353.i_imu_logger.xclk
@1401200
-IMU
@c00200
-imu_spi
@28
testbench353.IMU_103695REVA
@22
testbench353.i_x353.i_imu_logger.config_debug[3:0]
@800022
testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
@1001200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.config_single_wire
testbench353.IMU_MOSI_REVA
testbench353.IMU_NMOSI
testbench353.IMU_SCLK
testbench353.IMU_MOSI
testbench353.IMU_CS
testbench353.IMU_ACTIVE
testbench353.IMU_SCLK_OUT
testbench353.IMU_MOSI_OUT
testbench353.IMU_MISO
@22
testbench353.IMU_LOOPBACK[15:0]
@c00022
testbench353.IMU_TAPS[5:1]
@28
(0)testbench353.IMU_TAPS[5:1]
(1)testbench353.IMU_TAPS[5:1]
(2)testbench353.IMU_TAPS[5:1]
(3)testbench353.IMU_TAPS[5:1]
(4)testbench353.IMU_TAPS[5:1]
@1401200
-group_end
@c00028
testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_stb[2:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_stb[2:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_stb[2:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_stb[2:0]
@1401200
-group_end
@800028
testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_r[1:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_r[1:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_r[1:0]
@1001200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_state[1:0]
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_counter[9:0]
@800022
testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
@1001200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.stall
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi
testbench353.i_x353.i_imu_logger.i_imu_spi.scl
testbench353.i_x353.i_imu_logger.i_imu_spi.sda
testbench353.IMU_DATA_READY
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_ready_reset
@c00022
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(4)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(5)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
@1401200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.skip_stall
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.stall_cntr[7:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.stall
testbench353.i_x353.i_imu_logger.i_imu_spi.set_stall
testbench353.i_x353.i_imu_logger.i_imu_spi.set_mosi_spi
testbench353.i_x353.i_imu_logger.i_imu_spi.shift_mosi
@c00022
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(4)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(5)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(6)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(7)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(8)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(9)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(10)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(11)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(12)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(13)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(14)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(15)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
@1401200
-group_end
@28
testbench353.IMU_MOSI
testbench353.IMU_SCL
testbench353.IMU_CS
testbench353.IMU_MISO
testbench353.i_x353.i_imu_logger.i_imu_spi.stall
testbench353.i_x353.i_imu_logger.i_imu_spi.miso
testbench353.i_x353.i_imu_logger.i_imu_spi.shift_mosi
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.miso_reg[15:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.shift_miso
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_in_buf[15:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_wr_buf
testbench353.i_x353.i_imu_logger.i_imu_spi.last_buf_wr
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.bit_duration[7:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.bit_duration_cntr[7:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.bit_duration_mclk[7:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.bit_duration_zero
testbench353.i_x353.i_imu_logger.i_imu_spi.clk_div[1:0]
@c00022
testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
@1401200
-group_end
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.config_late_clk
testbench353.i_x353.i_imu_logger.i_imu_spi.config_long_sda_en
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.di[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.di_d[15:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.en
testbench353.i_x353.i_imu_logger.i_imu_spi.end_prepare
testbench353.i_x353.i_imu_logger.i_imu_spi.end_spi
testbench353.i_x353.i_imu_logger.i_imu_spi.first_prepare
testbench353.i_x353.i_imu_logger.i_imu_spi.first_prepare_d[1:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_enabled[1:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_enabled_mclk
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_in_buf[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_in_word[4:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_wr_buf
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.miso_reg[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_reg_number[6:1]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_run[1:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_run_confirmed
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_run_mclk
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_first
@c00028
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_grant[1:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_grant[1:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_grant[1:0]
@1401200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_mclk
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_wr_buf
testbench353.i_x353.i_imu_logger.i_imu_spi.last_bit
testbench353.i_x353.i_imu_logger.i_imu_spi.last_bit_ext
testbench353.i_x353.i_imu_logger.i_imu_spi.last_buf_wr
testbench353.i_x353.i_imu_logger.i_imu_spi.miso
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi
testbench353.i_x353.i_imu_logger.i_imu_spi.set_mosi_spi
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.period[31:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.period_counter[31:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.pre_imu_wr_buf
testbench353.i_x353.i_imu_logger.i_imu_spi.pre_seq_counter_zero
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.raddr[4:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.rd_stb
@c00022
testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(4)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(5)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(6)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(7)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(8)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(9)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(10)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(11)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(12)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(13)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(14)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(15)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
@1401200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.rdy
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.reg_seq_number[4:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.scl
testbench353.i_x353.i_imu_logger.i_imu_spi.scl_d
testbench353.i_x353.i_imu_logger.i_imu_spi.scl_en
testbench353.i_x353.i_imu_logger.i_imu_spi.sclk
testbench353.i_x353.i_imu_logger.i_imu_spi.sda
testbench353.i_x353.i_imu_logger.i_imu_spi.sda_d
testbench353.i_x353.i_imu_logger.i_imu_spi.sda_en
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_counter[9:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_counter_zero
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_state[1:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.set_mosi_prepare
testbench353.i_x353.i_imu_logger.i_imu_spi.set_mosi_spi
testbench353.i_x353.i_imu_logger.i_imu_spi.set_stall
testbench353.i_x353.i_imu_logger.i_imu_spi.shift_miso
testbench353.i_x353.i_imu_logger.i_imu_spi.skip_stall
testbench353.i_x353.i_imu_logger.i_imu_spi.stall
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.stall_cntr[7:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.stall_dur[7:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.stall_dur_mclk[7:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.ts
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.wa[4:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.we_div
testbench353.i_x353.i_imu_logger.i_imu_spi.we_period
testbench353.i_x353.i_imu_logger.i_imu_spi.we_ra
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.we_timer[4:1]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.xclk
@1401200
-imu_spi
@c00200
-rs232_rcv
@22
testbench353.i_x353.i_imu_logger.i_rs232_rcv.bitHalfPeriod[15:0]
testbench353.i_x353.i_imu_logger.i_rs232_rcv.bit_cntr[4:0]
testbench353.i_x353.i_imu_logger.i_rs232_rcv.bit_dur_cntr[15:0]
@28
testbench353.i_x353.i_imu_logger.i_rs232_rcv.bit_half_end
@22
testbench353.i_x353.i_imu_logger.i_rs232_rcv.debug0[4:0]
testbench353.i_x353.i_imu_logger.i_rs232_rcv.debug[4:0]
@28
testbench353.i_x353.i_imu_logger.i_rs232_rcv.error
testbench353.i_x353.i_imu_logger.i_rs232_rcv.last_half_bit
testbench353.i_x353.i_imu_logger.i_rs232_rcv.receiving_byte
testbench353.i_x353.i_imu_logger.i_rs232_rcv.reset_bit_duration
testbench353.i_x353.i_imu_logger.i_rs232_rcv.reset_wait_pause
testbench353.i_x353.i_imu_logger.i_rs232_rcv.restart[1:0]
testbench353.i_x353.i_imu_logger.i_rs232_rcv.sample_bit
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_di
@22
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_di_d[4:0]
@28
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_do
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_do_stb
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_filt_di
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_filt_di_d
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_rst
testbench353.i_x353.i_imu_logger.i_rs232_rcv.shift_en
testbench353.i_x353.i_imu_logger.i_rs232_rcv.start
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ts_stb
testbench353.i_x353.i_imu_logger.i_rs232_rcv.wait_just_pause
testbench353.i_x353.i_imu_logger.i_rs232_rcv.wait_pause
testbench353.i_x353.i_imu_logger.i_rs232_rcv.wait_start
testbench353.i_x353.i_imu_logger.i_rs232_rcv.wstart
testbench353.i_x353.i_imu_logger.i_rs232_rcv.xclk
@1401200
-rs232_rcv
=======
@1401200
-quantizer
@c00200
-IMU
@22
testbench353.i_x353.i_imu_logger.ts_rcv_sec[31:0]
testbench353.i_x353.i_imu_logger.ts_rcv_usec[19:0]
@28
testbench353.i_x353.i_imu_logger.ts_stb
@22
testbench353.i_x353.i_imu_logger.bitHalfPeriod[15:0]
testbench353.i_x353.i_imu_logger.bitHalfPeriod_mclk[15:0]
@28
testbench353.i_x353.i_imu_logger.channel[1:0]
@22
testbench353.i_x353.i_imu_logger.channel_next[3:0]
testbench353.i_x353.i_imu_logger.channel_ready[3:0]
@28
testbench353.i_x353.i_imu_logger.clk
@22
testbench353.i_x353.i_imu_logger.config_gps[3:0]
testbench353.i_x353.i_imu_logger.config_gps_mclk[3:0]
testbench353.i_x353.i_imu_logger.config_gps_pre[3:0]
@28
testbench353.i_x353.i_imu_logger.config_imu[1:0]
testbench353.i_x353.i_imu_logger.config_imu_mclk[1:0]
testbench353.i_x353.i_imu_logger.config_imu_pre[1:0]
@22
testbench353.i_x353.i_imu_logger.config_msg[4:0]
testbench353.i_x353.i_imu_logger.config_msg_mclk[4:0]
testbench353.i_x353.i_imu_logger.config_msg_pre[4:0]
@28
testbench353.i_x353.i_imu_logger.config_rst
testbench353.i_x353.i_imu_logger.config_rst_mclk
testbench353.i_x353.i_imu_logger.config_rst_pre
testbench353.i_x353.i_imu_logger.config_syn
testbench353.i_x353.i_imu_logger.config_syn_mclk
testbench353.i_x353.i_imu_logger.config_syn_pre
@22
testbench353.i_x353.i_imu_logger.ctrl_addr[6:0]
testbench353.i_x353.i_imu_logger.data_out[15:0]
@28
testbench353.i_x353.i_imu_logger.data_out_stb
@22
testbench353.i_x353.i_imu_logger.dbg_cntr[7:0]
testbench353.i_x353.i_imu_logger.debug_state[31:0]
testbench353.i_x353.i_imu_logger.di[15:0]
testbench353.i_x353.i_imu_logger.di_d[15:0]
@28
testbench353.i_x353.i_imu_logger.enable_gps
testbench353.i_x353.i_imu_logger.enable_msg
testbench353.i_x353.i_imu_logger.enable_syn
testbench353.i_x353.i_imu_logger.enable_timestamps
@22
testbench353.i_x353.i_imu_logger.ext_di[11:0]
testbench353.i_x353.i_imu_logger.ext_do[11:0]
testbench353.i_x353.i_imu_logger.ext_en[11:0]
@28
testbench353.i_x353.i_imu_logger.ext_ts_stb[1:0]
@22
testbench353.i_x353.i_imu_logger.extts_data[15:0]
@28
testbench353.i_x353.i_imu_logger.gps_pulse1sec
testbench353.i_x353.i_imu_logger.gps_pulse1sec_d[2:0]
testbench353.i_x353.i_imu_logger.gps_pulse1sec_denoise[1:0]
@22
testbench353.i_x353.i_imu_logger.gps_pulse1sec_denoise_count[7:0]
@28
testbench353.i_x353.i_imu_logger.gps_pulse1sec_single
testbench353.i_x353.i_imu_logger.gps_ts_stb
@22
testbench353.i_x353.i_imu_logger.imu_data[15:0]
@28
testbench353.i_x353.i_imu_logger.message_trig
testbench353.i_x353.i_imu_logger.miso
testbench353.i_x353.i_imu_logger.mosi
@22
testbench353.i_x353.i_imu_logger.msg_data[15:0]
testbench353.i_x353.i_imu_logger.mux_data_final[15:0]
testbench353.i_x353.i_imu_logger.mux_data_source[15:0]
@28
testbench353.i_x353.i_imu_logger.mux_data_valid
testbench353.i_x353.i_imu_logger.mux_rdy_source
@22
testbench353.i_x353.i_imu_logger.nmea_data[15:0]
@28
testbench353.i_x353.i_imu_logger.nmea_sent_start
testbench353.i_x353.i_imu_logger.pre_message_trig
testbench353.i_x353.i_imu_logger.rs232_start
testbench353.i_x353.i_imu_logger.rs232_wait_pause
@22
testbench353.i_x353.i_imu_logger.sample_counter[23:0]
@28
testbench353.i_x353.i_imu_logger.scl
testbench353.i_x353.i_imu_logger.scl_en
testbench353.i_x353.i_imu_logger.sda
testbench353.i_x353.i_imu_logger.sda_en
@22
testbench353.i_x353.i_imu_logger.sec[31:0]
@28
testbench353.i_x353.i_imu_logger.ser_di
testbench353.i_x353.i_imu_logger.ser_do
testbench353.i_x353.i_imu_logger.ser_do_stb
@22
testbench353.i_x353.i_imu_logger.timestamp_ackn[3:0]
testbench353.i_x353.i_imu_logger.timestamp_request[3:0]
testbench353.i_x353.i_imu_logger.timestamp_request_long[3:0]
@28
testbench353.i_x353.i_imu_logger.timestamp_sel[1:0]
@22
testbench353.i_x353.i_imu_logger.timestamps_rdata[15:0]
@28
testbench353.i_x353.i_imu_logger.ts_en
@22
testbench353.i_x353.i_imu_logger.ts_rcv_sec[31:0]
testbench353.i_x353.i_imu_logger.ts_rcv_usec[19:0]
@28
testbench353.i_x353.i_imu_logger.ts_stb
testbench353.i_x353.i_imu_logger.ts_stb_rq
@22
testbench353.i_x353.i_imu_logger.usec[19:0]
@28
testbench353.i_x353.i_imu_logger.wa
testbench353.i_x353.i_imu_logger.we
testbench353.i_x353.i_imu_logger.we_bitHalfPeriod
testbench353.i_x353.i_imu_logger.we_bit_duration
testbench353.i_x353.i_imu_logger.we_config
testbench353.i_x353.i_imu_logger.we_config_gps
testbench353.i_x353.i_imu_logger.we_config_imu
testbench353.i_x353.i_imu_logger.we_config_msg
testbench353.i_x353.i_imu_logger.we_config_syn
testbench353.i_x353.i_imu_logger.we_d
testbench353.i_x353.i_imu_logger.we_gps
testbench353.i_x353.i_imu_logger.we_imu
testbench353.i_x353.i_imu_logger.we_message
testbench353.i_x353.i_imu_logger.we_period
testbench353.i_x353.i_imu_logger.xclk
@1401200
-IMU
@800200
-imu_spi
@28
testbench353.IMU_103695REVA
@22
testbench353.i_x353.i_imu_logger.config_debug[3:0]
@800022
testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
@1001200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.config_single_wire
testbench353.IMU_MOSI_REVA
testbench353.IMU_NMOSI
testbench353.IMU_SCLK
testbench353.IMU_MOSI
testbench353.IMU_CS
testbench353.IMU_ACTIVE
testbench353.IMU_SCLK_OUT
testbench353.IMU_MOSI_OUT
testbench353.IMU_MISO
@23
testbench353.IMU_LOOPBACK[15:0]
@c00022
testbench353.IMU_TAPS[5:1]
@28
(0)testbench353.IMU_TAPS[5:1]
(1)testbench353.IMU_TAPS[5:1]
(2)testbench353.IMU_TAPS[5:1]
(3)testbench353.IMU_TAPS[5:1]
(4)testbench353.IMU_TAPS[5:1]
@1401200
-group_end
@c00028
testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_stb[2:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_stb[2:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_stb[2:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_stb[2:0]
@1401200
-group_end
@800028
testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_r[1:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_r[1:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire_r[1:0]
@1001200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.sngl_wire
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_state[1:0]
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_counter[9:0]
@800022
testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
@1001200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.stall
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi
testbench353.i_x353.i_imu_logger.i_imu_spi.scl
testbench353.i_x353.i_imu_logger.i_imu_spi.sda
testbench353.IMU_DATA_READY
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_ready_reset
@c00022
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(4)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
(5)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_data_ready[5:0]
@1401200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.skip_stall
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.stall_cntr[7:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.stall
testbench353.i_x353.i_imu_logger.i_imu_spi.set_stall
testbench353.i_x353.i_imu_logger.i_imu_spi.set_mosi_spi
testbench353.i_x353.i_imu_logger.i_imu_spi.shift_mosi
@c00022
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(4)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(5)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(6)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(7)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(8)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(9)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(10)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(11)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(12)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(13)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(14)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
(15)testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
@1401200
-group_end
@28
testbench353.IMU_MOSI
testbench353.IMU_SCL
testbench353.IMU_CS
testbench353.IMU_MISO
testbench353.i_x353.i_imu_logger.i_imu_spi.stall
testbench353.i_x353.i_imu_logger.i_imu_spi.miso
testbench353.i_x353.i_imu_logger.i_imu_spi.shift_mosi
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.miso_reg[15:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.shift_miso
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_in_buf[15:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_wr_buf
testbench353.i_x353.i_imu_logger.i_imu_spi.last_buf_wr
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.bit_duration[7:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.bit_duration_cntr[7:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.bit_duration_mclk[7:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.bit_duration_zero
testbench353.i_x353.i_imu_logger.i_imu_spi.clk_div[1:0]
@c00022
testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.clk_en[3:0]
@1401200
-group_end
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.config_debug[3:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.config_late_clk
testbench353.i_x353.i_imu_logger.i_imu_spi.config_long_sda_en
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.di[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.di_d[15:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.en
testbench353.i_x353.i_imu_logger.i_imu_spi.end_prepare
testbench353.i_x353.i_imu_logger.i_imu_spi.end_spi
testbench353.i_x353.i_imu_logger.i_imu_spi.first_prepare
testbench353.i_x353.i_imu_logger.i_imu_spi.first_prepare_d[1:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_enabled[1:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_enabled_mclk
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_in_buf[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_in_word[4:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_wr_buf
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.miso_reg[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_reg_number[6:1]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_run[1:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_run_confirmed
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_run_mclk
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_first
@c00028
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_grant[1:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_grant[1:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_grant[1:0]
@1401200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_start_mclk
testbench353.i_x353.i_imu_logger.i_imu_spi.imu_wr_buf
testbench353.i_x353.i_imu_logger.i_imu_spi.last_bit
testbench353.i_x353.i_imu_logger.i_imu_spi.last_bit_ext
testbench353.i_x353.i_imu_logger.i_imu_spi.last_buf_wr
testbench353.i_x353.i_imu_logger.i_imu_spi.miso
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi
testbench353.i_x353.i_imu_logger.i_imu_spi.set_mosi_spi
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.mosi_reg[15:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.period[31:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.period_counter[31:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.pre_imu_wr_buf
testbench353.i_x353.i_imu_logger.i_imu_spi.pre_seq_counter_zero
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.raddr[4:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.rd_stb
@c00022
testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
@28
(0)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(1)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(2)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(3)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(4)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(5)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(6)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(7)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(8)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(9)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(10)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(11)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(12)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(13)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(14)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
(15)testbench353.i_x353.i_imu_logger.i_imu_spi.rdata[15:0]
@1401200
-group_end
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.rdy
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.reg_seq_number[4:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.scl
testbench353.i_x353.i_imu_logger.i_imu_spi.scl_d
testbench353.i_x353.i_imu_logger.i_imu_spi.scl_en
testbench353.i_x353.i_imu_logger.i_imu_spi.sclk
testbench353.i_x353.i_imu_logger.i_imu_spi.sda
testbench353.i_x353.i_imu_logger.i_imu_spi.sda_d
testbench353.i_x353.i_imu_logger.i_imu_spi.sda_en
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_counter[9:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_counter_zero
testbench353.i_x353.i_imu_logger.i_imu_spi.seq_state[1:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.set_mosi_prepare
testbench353.i_x353.i_imu_logger.i_imu_spi.set_mosi_spi
testbench353.i_x353.i_imu_logger.i_imu_spi.set_stall
testbench353.i_x353.i_imu_logger.i_imu_spi.shift_miso
testbench353.i_x353.i_imu_logger.i_imu_spi.skip_stall
testbench353.i_x353.i_imu_logger.i_imu_spi.stall
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.stall_cntr[7:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.stall_dur[7:0]
testbench353.i_x353.i_imu_logger.i_imu_spi.stall_dur_mclk[7:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.ts
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.wa[4:0]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.we_div
testbench353.i_x353.i_imu_logger.i_imu_spi.we_period
testbench353.i_x353.i_imu_logger.i_imu_spi.we_ra
@22
testbench353.i_x353.i_imu_logger.i_imu_spi.we_timer[4:1]
@28
testbench353.i_x353.i_imu_logger.i_imu_spi.xclk
@1000200
-imu_spi
@c00200
-rs232_rcv
@22
testbench353.i_x353.i_imu_logger.i_rs232_rcv.bitHalfPeriod[15:0]
testbench353.i_x353.i_imu_logger.i_rs232_rcv.bit_cntr[4:0]
testbench353.i_x353.i_imu_logger.i_rs232_rcv.bit_dur_cntr[15:0]
@28
testbench353.i_x353.i_imu_logger.i_rs232_rcv.bit_half_end
@22
testbench353.i_x353.i_imu_logger.i_rs232_rcv.debug0[4:0]
testbench353.i_x353.i_imu_logger.i_rs232_rcv.debug[4:0]
@28
testbench353.i_x353.i_imu_logger.i_rs232_rcv.error
testbench353.i_x353.i_imu_logger.i_rs232_rcv.last_half_bit
testbench353.i_x353.i_imu_logger.i_rs232_rcv.receiving_byte
testbench353.i_x353.i_imu_logger.i_rs232_rcv.reset_bit_duration
testbench353.i_x353.i_imu_logger.i_rs232_rcv.reset_wait_pause
testbench353.i_x353.i_imu_logger.i_rs232_rcv.restart[1:0]
testbench353.i_x353.i_imu_logger.i_rs232_rcv.sample_bit
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_di
@22
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_di_d[4:0]
@28
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_do
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_do_stb
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_filt_di
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_filt_di_d
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ser_rst
testbench353.i_x353.i_imu_logger.i_rs232_rcv.shift_en
testbench353.i_x353.i_imu_logger.i_rs232_rcv.start
testbench353.i_x353.i_imu_logger.i_rs232_rcv.ts_stb
testbench353.i_x353.i_imu_logger.i_rs232_rcv.wait_just_pause
testbench353.i_x353.i_imu_logger.i_rs232_rcv.wait_pause
testbench353.i_x353.i_imu_logger.i_rs232_rcv.wait_start
testbench353.i_x353.i_imu_logger.i_rs232_rcv.wstart
testbench353.i_x353.i_imu_logger.i_rs232_rcv.xclk
@1401200
-rs232_rcv
>>>>>>> 1.14
[pattern_trace] 1
[pattern_trace] 0
This source diff could not be displayed because it is too large. You can view the blob instead.
# version: 10.1.03
#
# ProjectNavigator SourceControl export script
#
# This script is generated and executed by ProjectNavigator
# to copy files related to the current project to a
# destination staging area.
#
# The list of files being exported, as controled by
# GUI settings, is placed in the variable export_files.
# Each file will be passed to the procedure CopyOut. This
# procedure will determine the exact destination, and will
# attempt the file copy if the source and destination are different.
#
# This script is not indended for direct customer editing.
#
# Copyright 2006, Xilinx, Inc.
#
#
# CopyOut -- copy a source file to the staging area, with
# extra options for files remote (outside of) the
# project directory.
proc CopyOut { srcfile staging_area copy_option } {
set report_errors true
if { $copy_option == "flatten" } {
set dest [ file join $staging_area [ file tail $srcfile ] ]
} elseif { $copy_option == "nop" } {
set dest $staging_area
set report_errors false
} elseif { [ file pathtype $srcfile ] != "relative" } {
set srcfile2 [ string map {: _} $srcfile ]
set dest [ file join $staging_area absolute $srcfile2 ]
} elseif { [ expr { $copy_option == "absremote" } && { [string equal -length 2 $srcfile ".." ] } ] } {
set dest [ file join $staging_area outside_relative [ string map {.. up} $srcfile ] ]
} else {
set srcfile2 [ string map {: _} $srcfile ]
set dest [ file join $staging_area $srcfile2 ]
}
set dest [ file normalize $dest ]
set src [ file normalize $srcfile ]
if { [ expr { [ string equal $dest $src ] == 0 } && { [ file exists $src ] } ] } {
file mkdir [ file dirname $dest ]
if { [catch { file copy -force $src $dest } ] } {
if { $report_errors } { puts "Could not copy $src to $dest." }
}
}
}
# change to the working directory
set old_working_dir [pwd]
cd [file normalize {/home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3} ]
set copy_option relative
set staging_area "/home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3"
set export_files {
"10364.v"
"camsync.v"
"clkios353.v"
"cmd_sequencer.v"
"color_proc353.v"
"compressor333.v"
"control_regs.v"
"coring.dat"
"csconvert18.v"
"csconvert_mono.v"
"ddr.v"
"ddr_parameters.v"
"descrproc353.v"
"dma_fifo353.v"
"encoderDCAC353.v"
"extjtag.v"
"focus_filt.dat"
"focus_sharp.v"
"glbl.v"
"gps_data.dat"
"histogram353.v"
"huffman.dat"
"huffman333.v"
"i2c_writeonly.v"
"imu_logger.v"
"interrupts_vector333.v"
"ioports353.v"
"irq_smart.v"
"lens_flat.v"
"linear1028rgb.dat"
"macros353.v"
"mcontr353.v"
"motor.dat"
"motors_sim.sh"
"motors_tb.v"
"quantization_100.dat"
"quantizator353.v"
"rtc353.v"
"sdram_phase.v"
"sdseq353.v"
"sensdcclk333.v"
"sensor.dat"
"sensor12bits.v"
"sensor_phase353.v"
"sensorpads353.v"
"sensorpix353.v"
"sensortrig.v"
"stuffer333.v"
"twelve_ios.v"
"x353.ucf"
"x353.v"
"x353_1.sav"
"x353_1.tf"
"x353_guide.ncd"
"x353_sim.sh"
"xdct353.v"
}
foreach file $export_files {
CopyOut $file $staging_area $copy_option
}
# copy export file to staging area
CopyOut "/home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3/x353_import.tcl" "$staging_area" nop
# return back
cd $old_working_dir
# version: 10.1.03
# ProjectNavigator SourceControl recreation script
#
# This script is text version of significant (but possibly not all)
# the information contained in the ISE project file. It is generated
# and used by the ProjectNavigator application's source control
# import feature.
#
# When using this script from the command line to recreate the ISE
# project, it should first be sourced from within an xtclsh shell.
# Next, the import procedure should be called to perform the import.
# When calling the import procedure, pass the new project directory
# and the source directory. If neither are specified, the current
# working directory is assumed for both.
#
# Internally this script has two file lists. One variable (import_files)
# has the set of files to copy into the project directory. The other
# variable (user_files) has the set of files to add into the project.
#
#
# This script is not intended for direct customer editing.
#
# Copyright 2006, Xilinx, Inc.
#
# Helper to copy files from the source staging area
# back into the destination work area.
# This proc will be call for each file copied.
# While not supported, one could do interesting things with this
# proc, since each file hits it.
proc CopyIn { srcfile work_area copy_option } {
set staging_area [pwd]
if { [ expr { [ file pathtype $srcfile ] == "absolute" || \
[string index $srcfile 0 ] == "/" || \
[string index $srcfile 1 ] == ":" } ] } {
set workfile $srcfile
} else {
set workfile [ file join $work_area $srcfile ]
}
if { $copy_option == "flatten" } {
set stagefile [ file join $staging_area [ file tail $srcfile ] ]
} elseif { [ file pathtype $srcfile ] != "relative" } {
set srcfile [ string map {: _} $srcfile ]
set stagefile [ file join $staging_area absolute $srcfile ]
} elseif { [ expr { $copy_option == "absremote" } && { [string equal -length 2 $srcfile ".." ] } ] } {
set stagefile [ file join $staging_area outside_relative [ string map {.. up} $srcfile ] ]
} else {
set srcfile [ string map {: _} $srcfile ]
set stagefile [ file join $staging_area $srcfile ]
}
set stagefile [ file normalize $stagefile ]
set workfile [ file normalize $workfile ]
if { [ file exists $stagefile ] } {
if { $stagefile != $workfile } {
file mkdir [ file dirname $workfile ]
file copy -force $stagefile $workfile
}
} else { WARN "\"$stagefile\" does not exist for import copy." }
}
proc ERR { msg } {
puts "ERROR: $msg"
}
proc WARN { msg } {
puts "WARNING: $msg"
}
proc INFO { msg } {
puts "$msg"
}
# Helper that returns 1 if the string is blank, otherwise 0.
proc IsBlank { str } {
if { [string length $str] == 0 } {
return 1
}
return 0
}
# Helper for determining whether a value is 'NULL'.
# Returns 1 if the value is 0; returns 0 if the value is anything else.
proc IsNull { val } {
if { $val == 0 } {
return 1
}
return 0
}
proc HandleException { script { msg "" } } {
set catch_result [catch {
uplevel 1 $script
} RESULT]
if {$catch_result} {
if {![IsBlank $msg]} {
ERR $msg
}
INFO "$RESULT"
INFO "$::errorInfo"
}
}
# These two procs help to load shared libraries in a platform
# independent way.
proc _LoadLibrary {name} {
set libExt [info sharedlibextension]
set libFullName "$name$libExt"
HandleException {
load $libFullName
} "A problem occured loading library $libFullName."
}
proc _LoadFactoryLibrary {Factory} {
HandleException {
Xilinx::Cit::FactoryLoad $Factory
} "A problem occured loading library $Factory."
}
_LoadLibrary libCit_CoreStub
_LoadLibrary libPrjrep_CommonStub
_LoadFactoryLibrary libPrjrep_Common
_LoadLibrary libDpm_SupportStub
_LoadLibrary libDpm_PnfStub
_LoadLibrary libDpm_DefnDataStub
_LoadLibrary libDpm_DesignDataStub
_LoadLibrary libDpm_HdlStub
_LoadLibrary libPrjrep_RepositoryStub
_LoadLibrary libCitI_CoreStub
_LoadLibrary libHdcI_HdcHDProjectStub
_LoadLibrary libTcltaskI_TaskStub
_LoadLibrary libCommonI_CommonStub
_LoadFactoryLibrary libTcltask_Helpers
_LoadFactoryLibrary libHdcC_HDProject
_LoadLibrary libHdcI_HdcContainerStub
_LoadLibrary libGuiI_Stub
# Helper to exectute code only when the (pointer) variable name is valid.
proc OnOkPtr { var_name script } {
if { [ uplevel info exists $var_name ] } {
upvar $var_name var
if { $var != 0 } { return [ uplevel $script ] }
}
}
# Helper to exectute code only when the (pointer) variable name is 0.
proc OnNullPtr { var_name script } {
if { [ uplevel info exists $var_name ] } {
upvar $var_name var
if { $var == 0 } { return [ uplevel $script ] }
}
}
# Helper to exectute code only when the value of variable name is 1.
proc OnSuccess { var_name script } {
if { $val != 0 } { return [ uplevel $script ] }
}
# Helper to exectute code only when the value of variable name is 0.
proc OnFail { val script } {
if { $val != 1 } { return [ uplevel $script ] }
}
# Helper to get a component interface.
proc GetInterface { iUnk id { name "" } } {
if {$iUnk == 0} { return 0 }
set iIface [ $iUnk GetInterface $id ]
OnNullPtr iIface {
if {![IsBlank $name]} {
ERR " Could not get the \"$name\" interface."
}
}
return $iIface
}
# Helper to create a component and return one of its interfaces.
proc CreateComponent { compId ifaceId { name "" } } {
set iUnk [ ::Xilinx::Cit::FactoryCreate $compId ]
set iIface [ GetInterface $iUnk $ifaceId ]
OnNullPtr iIface {
if {![IsBlank $name]} { ERR "Could not create a \"$name\" component." }
}
return $iIface
}
# Helper to release an object
proc Release { args } {
foreach iUnk $args {
set i_refcount [ GetInterface $iUnk $::xilinx::Prjrep::IRefCountID ]
OnNullPtr i_refcount { set i_refcount [ GetInterface $iUnk $::xilinx::CommonI::IRefCountID ] }
OnOkPtr i_refcount { $i_refcount Release }
}
}
# Helper to loop over IIterator based pointers.
proc ForEachIterEle { _ele_var_name _iter script } {
if {$_iter == 0} { return 0 }
upvar $_ele_var_name ele
for { $_iter First } { ![ $_iter IsEnd ] } { $_iter Next } {
set ele [ $_iter CurrentItem ]
set returned_val [ uplevel $script ]
}
}
# Helper to get the Tcl Project Manager, if possible.
proc GetTclProjectMgr { } {
set TclProjectMgrId "{7d528480-1196-4635-aba9-639446e4aa59}"
set iUnk [ Xilinx::CitP::CreateComponent $TclProjectMgrId ]
if {$iUnk == 0} { return 0 }
set iTclProjectMgr [ $iUnk GetInterface $::xilinx::TcltaskI::ITclProjectMgrID ]
OnNullPtr iTclProjectMgr {
ERR "Could not create a \"TclProjectMgr\" component."
}
return $iTclProjectMgr
}
# Helper to get the current Tcl Project, if one is open.
proc GetCurrentTclProject { } {
set iTclProject 0
set iTclProjectMgr [GetTclProjectMgr]
OnOkPtr iTclProjectMgr {
set errmsg ""
$iTclProjectMgr GetCurrentTclProject iTclProject errmsg
}
return $iTclProject
}
# Helper to get the current HDProject, if one is open.
proc GetCurrentHDProject { } {
set iHDProject 0
set iTclProjectMgr [GetTclProjectMgr]
set errmsg ""
OnOkPtr iTclProjectMgr { $iTclProjectMgr GetCurrentHDProject iHDProject errmsg }
OnNullPtr iHDProject {
ERR "Could not get the current HDProject."
}
return $iHDProject
}
# Helper to create a Project Helper.
proc GetProjectHelper { } {
set ProjectHelperID "{0725c3d2-5e9b-4383-a7b6-a80c932eac21}"
set iProjHelper [CreateComponent $ProjectHelperID $::xilinx::Dpm::IProjectHelperID "Project Helper"]
return $iProjHelper
}
# Helper to find out if a project is currently open.
# Returns 1 if a project is open, otherwise 0.
proc IsProjectOpen { } {
set iTclProject [GetCurrentTclProject]
set isOpen [expr {$iTclProject != 0}]
Release $iTclProject
return $isOpen
}
# Helper to return the lock file for the specified project if there is one.
# Returns an empty string if there is no lock file on the specified project,
# or there is no corresponding .ise file
# This assumes that the project_file is in the current directory.
# It also assumes project_file does not have a path.
proc GetProjectLockFile { project_file } {
if { ![ file isfile "$project_file" ] } {
return
}
INFO "Checking for a lock file for \"$project_file\"."
set lock_file "__ISE_repository_${project_file}_.lock"
if { [ file isfile "$lock_file" ] } {
return $lock_file
}
return
}
# Helper to back up the project file.
# This assumes that the project_file is in the current directory.
proc BackUpProject { project_file backup_file } {
if { ![ file isfile "$project_file" ] } {
WARN "Could not find \"$project_file\"; the project will not be backed up."
return 0
} else {
INFO "Backing up the project to \"$backup_file\"."
file copy -force "$project_file" "$backup_file"
}
return 1
}
# Helper to remove the project file so that a new project can be created
# in its place. Presumably the old project is corrupted and can no longer
# be opened.
proc RemoveProject { project_file } {
file delete -force "$project_file"
# Return failure if the project still exists.
if { [ file isfile "$project_file" ] } {
ERR "Could not remove \"$project_file\"; Unable to restore the project."
return 0
}
return 1
}
# Helper to open a project and return a project facilitator (pointer).
proc OpenFacilProject { project_name } {
# first make sure the tcl project mgr singleton exists
GetTclProjectMgr
# get a Project Helper and open the project.
set iProjHelper [GetProjectHelper]
if {$iProjHelper == 0} { return 0 }
set result [$iProjHelper Open $project_name]
OnFail $result {
if {$result == 576460769483292673} {
ERR "Could not open the project \"$project_name\" because it is locked."
} else {
ERR "Could not open the \"$project_name\" project."
}
Release $iProjHelper
set iProjHelper 0
}
return $iProjHelper
}
# Helper to close and release a project.
proc CloseFacilProject { iProjHelper } {
if {$iProjHelper == 0} { return }
$iProjHelper Close
Release $iProjHelper
}
# Helper to get the Project from the Project Helper.
# Clients must release this.
proc GetProject { iProjHelper } {
if {$iProjHelper == 0} { return 0 }
set dpm_project 0
$iProjHelper GetDpmProject dpm_project
set iProject [ GetInterface $dpm_project $xilinx::Dpm::IProjectID ]
OnNullPtr iProject {
ERR "Could not get the Project from the Project Helper."
}
return $iProject
}
# Helper to get the File Manager from the Project Helper.
# Clients must release this.
proc GetFileManager { iProjHelper } {
set iProject [GetProject $iProjHelper]
set iFileMgr [ GetInterface $iProject $xilinx::Dpm::IFileManagerID ]
OnNullPtr iFileMgr {
ERR "Could not get the File Manager from the Project Helper."
}
# Don't release the project here, clients will release it
# when they release its IFileManager interface.
return $iFileMgr
}
# Helper to get the Source Library Manager from the Project Helper.
# Clients must release this.
proc GetSourceLibraryManager { iProjHelper } {
set iProject [GetProject $iProjHelper]
set iSourceLibraryMgr [ GetInterface $iProject $xilinx::Dpm::ISourceLibraryManagerID ]
OnNullPtr iSourceLibraryMgr {
ERR "Could not get the Source Library Manager from the Project Helper."
}
# Don't release the project here, clients will release it
# when they release its IFileManager interface.
return $iSourceLibraryMgr
}
# Helper to get the ProjSrcHelper from the Project Helper.
# Clients must NOT release this.
proc GetProjSrcHelper { iProjHelper } {
set iSrcHelper [ GetInterface $iProjHelper $::xilinx::Dpm::IProjSrcHelperID IProjSrcHelper ]
OnNullPtr iSrcHelper {
ERR "Could not get the ProjSrcHelper from the Project Helper."
}
return $iSrcHelper
}
# Helper to get the ScratchPropertyManager from the Project Helper.
# Clients must NOT release this.
proc GetScratchPropertyManager { iProjHelper } {
set iPropTableFetch [ GetInterface $iProjHelper $xilinx::Dpm::IPropTableFetchID IPropTableFetch ]
set prop_table_comp 0
OnOkPtr iPropTableFetch {
$iPropTableFetch GetPropTable prop_table_comp
}
set iScratch [ GetInterface $prop_table_comp $xilinx::Dpm::IScratchPropertyManagerID ]
OnNullPtr iScratch {
ERR "Could not get the Scratch Property Manager from the Project Helper."
}
return $iScratch
}
# Helper to get the Design from the Project Helper.
# Clients must release this.
proc GetDesign { iProjHelper } {
set iProject [GetProject $iProjHelper]
set iDesign 0
OnOkPtr iProject { $iProject GetDesign iDesign }
OnNullPtr iDesign {
ERR "Could not get the Design from the Project Helper."
}
Release $iProject
return $iDesign
}
# Helper to get the Data Store from the Project Helper.
# Clients must NOT release this.
proc GetDataStore { iProjHelper } {
set iDesign [ GetDesign $iProjHelper]
set iDataStore 0
OnOkPtr iDesign { $iDesign GetDataStore iDataStore }
OnNullPtr iDataStore {
ERR "Could not get the Data Store from the Project Helper."
}
Release $iDesign
return $iDataStore
}
# Helper to get the View Manager from the Project Helper.
# Clients must NOT release this.
proc GetViewManager { iProjHelper } {
set iDesign [ GetDesign $iProjHelper]
set iViewMgr [ GetInterface $iDesign $xilinx::Dpm::IViewManagerID ]
OnNullPtr iViewMgr {
ERR "Could not get the View Manager from the Project Helper."
}
# Don't release the design here, clients will release it
# when they release its IViewManager interface.
return $iViewMgr
}
# Helper to get the Property Manager from the Project Helper.
# Clients must release this.
proc GetPropertyManager { iProjHelper } {
set iDesign [ GetDesign $iProjHelper]
set iPropMgr 0
OnOkPtr iDesign { $iDesign GetPropertyManager iPropMgr }
OnNullPtr iPropMgr {
ERR "Could not get the Property Manager from the Project Helper."
}
Release $iDesign
return $iPropMgr
}
# Helper to find a property template, based on prop_name
# Clients must NOT release this.
proc GetPropertyTemplate { iProjHelper prop_name } {
set iPropTempl 0
set iUnk 0
set iDefdataId 0
set iPropTemplStore 0
set iDataStore [GetDataStore $iProjHelper]
OnOkPtr iDataStore { $iDataStore GetComponentByName $prop_name iUnk }
OnOkPtr iUnk { set iDefdataId [ GetInterface $iUnk $xilinx::Dpm::IDefDataIdID IDefDataId ] }
OnOkPtr iDefdataId {
set iPropTemplStore [ GetInterface $iDataStore $xilinx::Dpm::IPropertyTemplateStoreID IPropertyTemplateStore ]
}
OnOkPtr iPropTemplStore { $iPropTemplStore GetPropertyTemplate $iDefdataId iPropTempl }
OnNullPtr iPropTempl {
WARN "Could not get the property template for \"$prop_name\"."
}
return $iPropTempl
}
# Helper to get a component's name.
proc GetName { iUnk } {
set name ""
set iName [ GetInterface $iUnk $xilinx::Prjrep::INameID IName ]
OnOkPtr iName { $iName GetName name }
return $name
}
# Helper to get the name of a view's type.
proc GetViewTypeName { iView } {
set typeName ""
set iType 0
set iDefdataType 0
OnOkPtr iView { $iView GetType iType }
OnOkPtr iType {
set iDefdataType [ GetInterface $iType $xilinx::Dpm::IDefDataIdID IDefDataId ]
}
OnOkPtr iDefdataType { $iDefdataType GetID typeName }
return $typeName
}
# Helper to find a view and return its context.
# Must clients release this?
proc GetViewContext { iProjHelper view_id view_name } {
# Simply return if the view_id or view_name is empty.
if { [IsBlank $view_id] || [IsBlank $view_name] } { return 0 }
set foundview 0
set viewiter 0
set iViewMgr [GetViewManager $iProjHelper]
OnOkPtr iViewMgr { $iViewMgr GetViews viewiter }
ForEachIterEle view $viewiter {
set typeName [GetViewTypeName $view]
set name [GetName $view]
if { [ string equal $name $view_name ] && [ string equal $view_id $typeName ] } {
set foundview $view
}
}
set context [ GetInterface $foundview $xilinx::Dpm::IPropertyContextID ]
OnNullPtr context {
WARN "Could not get the context for view \"$view_id\":\"$view_name\"."
}
return $context
}
# Helper to get a string property instance from the property manager.
proc GetStringPropertyInstance { iProjHelper simple_id } {
set iPropMgr [GetPropertyManager $iProjHelper]
if {$iPropMgr == 0} { return 0 }
set iPropInst 0
$iPropMgr GetStringProperty $simple_id iPropInst
OnNullPtr iPropInst { WARN "Could not get the string property instance $simple_id." }
Release $iPropMgr
return $iPropInst
}
# Helper to get a property instance from the property manager.
proc GetPropertyInstance { iProjHelper view_name view_id prop_name } {
set iPropInst 0
set iPropTempl [ GetPropertyTemplate $iProjHelper $prop_name ]
if {$iPropTempl == 0} { return 0 }
set context [ GetViewContext $iProjHelper $view_id $view_name ]
set iPropMgr [GetPropertyManager $iProjHelper]
if {$iPropMgr == 0} { return 0 }
$iPropMgr GetPropertyInstance $iPropTempl $context iPropInst
OnNullPtr iPropInst {
if { ![IsBlank $view_id] && ![IsBlank $view_name] } {
WARN "Could not get the context sensitive property instance $prop_name."
} else {
WARN "Could not get the property instance $prop_name."
}
}
Release $iPropMgr
return $iPropInst
}
# Helper to store properties back into the property manager.
proc RestoreProcessProperties { iProjHelper process_props } {
INFO "Restoring process properties"
foreach { unused view_name view_id simple_id prop_name prop_val } $process_props {
set iPropInst 0
if {![IsBlank $simple_id]} {
set iPropInst [ GetStringPropertyInstance $iProjHelper $simple_id ]
} else {
set iPropInst [ GetPropertyInstance $iProjHelper $view_name $view_id $prop_name ]
}
OnOkPtr iPropInst {
OnFail [ $iPropInst SetStringValue "$prop_val" ] {
WARN "Could not set the value of the $prop_name property to \"$prop_val\"."
}
}
Release $iPropInst
}
}
# Helper to recreate partitions from the variable name with
# a list of instance names.
proc RestorePartitions { namelist } {
INFO "Restoring partitions."
set iHDProject [ GetCurrentHDProject ]
OnOkPtr iHDProject {
foreach name $namelist {
set iPartition [ $iHDProject CreatePartition "$name" ]
}
}
}
# Helper to create and populate a library
#
proc CreateLibrary { iProjHelper libname filelist } {
set iLibMgr [ GetSourceLibraryManager $iProjHelper ]
set iFileMgr [ GetFileManager $iProjHelper ]
if {$iLibMgr == 0} { return 0 }
if {$iFileMgr == 0} { return 0 }
$iLibMgr CreateSourceLibrary "libname" ilib
OnOkPtr ilib {
foreach filename $filelist {
set argfile [ file normalize "$filename" ]
set found 0
set fileiter 0
$iFileMgr GetFiles fileiter
ForEachIterEle ifile $fileiter {
set path ""
set file ""
$ifile getPath path file
set currentfile [ file normalize [ file join "$path" "$file" ] ]
if { $currentfile == $argfile } {
set found 1
$ilib AddFile ifile
break
}
}
OnNullPtr found {
WARN "Could not add the file \"$filename\" to the library \"$libname\"."
}
}
}
}
# Helper to create source libraries and populate them.
proc RestoreSourceLibraries { iProjHelper libraries } {
INFO "Restoring source libraries."
foreach { libname filelist } $libraries {
CreateLibrary $iProjHelper "$libname" $filelist
}
}
# Helper to add user files to the project using the PnF.
proc AddUserFiles { iProjHelper files } {
INFO "Adding User files."
set iconflict 0
set iSrcHelper [ GetProjSrcHelper $iProjHelper ]
if {$iSrcHelper == 0} { return 0 }
foreach filename $files {
INFO "Adding the file \"$filename\" to the project."
set result [$iSrcHelper AddSourceFile "$filename" iconflict]
OnFail $result {
if {$result == 6} {
INFO "The file \"$filename\" is already in the project."
} else {
ERR "A problem occurred adding the file \"$filename\" to the project."
}
}
}
}
# Helper to add files to the project and set their origination.
# Valid origination values are:
# 0 - User
# 1 - Generated
# 2 - Imported
# Files of origination "User" are added through the facilitator,
# otherwise they are added directly to the File Manager.
proc AddImportedFiles { iProjHelper files origination } {
switch $origination {
0 { INFO "Adding User files." }
1 { INFO "Adding Generated files." }
2 { INFO "Adding Imported files." }
default {
ERR "Invalid parameter: origination was set to \"$origination\", but may only be 0, 1, or 2."
return 0
}
}
set iFileMgr [ GetFileManager $iProjHelper ]
if {$iFileMgr == 0} { return 0 }
foreach filename $files {
set file_type 0
set hdl_file 0
set result [$iFileMgr AddFile "$filename" $file_type hdl_file]
OnFail $result {
if {$result == 6} {
INFO "The file \"$filename\" is already in the project."
} elseif { $hdl_file == 0 } {
ERR "A problem occurred adding the file \"$filename\" to the project."
}
}
OnOkPtr hdl_file {
set ifile [ GetInterface $hdl_file $xilinx::Dpm::IFileID IFile ]
OnOkPtr ifile {
set result [ $ifile SetOrigination $origination ]
if {$result != 1} {
ERR "A problem occurred setting the origination of \"$filename\" to \"$origination\"."
}
Release $ifile
}
}
}
return 1
}
proc RestoreProjectSettings { iProjHelper project_settings } {
INFO "Restoring device settings"
set iScratch [GetScratchPropertyManager $iProjHelper]
set iPropIter 0
set iPropSet [ GetInterface $iScratch $xilinx::Dpm::IPropertyNodeSetID IPropertyNodeSet ]
OnOkPtr iPropSet {
$iPropSet GetIterator iPropIter
}
set index 0
set lastindex [llength $project_settings]
ForEachIterEle prop_node $iPropIter {
set prop_instance 0
$prop_node GetPropertyInstance prop_instance
if { $index < $lastindex } {
set argname [ lindex $project_settings $index ]
set argvalue [ lindex $project_settings [ expr $index + 1 ] ]
} else {
set argname {}
set argvalue {}
}
if { $prop_instance != 0 } {
set name {}
$prop_instance GetName name
if { [string equal $name $argname ] } {
$prop_instance SetStringValue $argvalue
incr index
incr index
}
}
Release $prop_instance
}
$iScratch Commit
# initialize
$iProjHelper Init
}
# Helper to load a source control configuration from a stream
# and then store it back into an ise file.
proc RestoreSourceControlOptions { prjfile istream } {
INFO "Restoring source control options"
set config_comp [::Xilinx::Cit::FactoryCreate $::xilinx::Dpm::SourceControlConfigurationCompID ]
OnOkPtr config_comp { set ipersist [ $config_comp GetInterface $xilinx::Prjrep::IPersistID ] }
OnOkPtr config_comp { set igetopts [ $config_comp GetInterface $xilinx::Dpm::SrcCtrl::IGetOptionsID ] }
set helper_comp [::Xilinx::Cit::FactoryCreate $::xilinx::Dpm::SourceControlHelpCompID ]
OnOkPtr helper_comp { set ihelper [ $config_comp GetInterface $xilinx::Dpm::SrcCtrl::IHelperID ] }
OnOkPtr ipersist { $ipersist Load istream }
OnOkPtr ihelper { OnOkPtr igetopts { $ihelper SaveOptions $prjfile $igetopts } }
Release $helper_comp $config_comp
}
# put a string message in a GUI popup message dialog (if possible),
# Get a user Yes/No response. If the GUI isn't active just 'puts'
# the message to stdout and return the default value.
# sMessageGUI - string, the message to display in GUI environment
# sMessageCmdLine - string, the message to display in CMdLine environment
# defaultValue - integer, the response to return on a timeout</In>
# hasCancel - integer, defaulting to 0. If 1, show Yes/No/Cancel buttons</In>
proc dpm_DisplayQuestionDialog { sMessageGUI sMessageCmdLine defaultValue { hasCancel 0} } {
set iMessageDisplay 0
if {[catch {
set iInterface [Xilinx::CitP::GetInstance $::xilinx::GuiI::IMessageDlgID]
set iMessageDisplay [$iInterface GetInterface $::xilinx::GuiI::IMessageDlgID]
}]} {
# if we cannot get the IMessageDlgID interface then we are most likely
# running from command line and not in the GUI.
puts $sMessageCmdLine
} else {
# got a good dialog singleton
set nTimeout 999999
set buttonValue [$iMessageDisplay Question "Project Navigator" $sMessageGUI $hasCancel $nTimeout]
if { $buttonValue == 2 } { ; # cancel
return 3
} elseif { $buttonValue == 3 } { ; # yes
return 1
} elseif { $buttonValue == 4 } { ; # no
return 2
} else { # probably timeout
return $defaultValue
}
}
return $defaultValue
}
proc import { {working_area ""} {staging_area ""} { srcctrl_comp 0 } } {
set project_file "x353.ise"
set old_working_dir [pwd]
# intialize the new project directory (work) and
# source control reference directory (staging) to
# current working directory, when not specified
if { $working_area == "" } { set working_area [pwd] }
if { $staging_area == "" } { set staging_area [pwd] }
set copy_option relative
set import_files {
"10364.v"
"camsync.v"
"clkios353.v"
"cmd_sequencer.v"
"color_proc353.v"
"compressor333.v"
"control_regs.v"
"coring.dat"
"csconvert18.v"
"csconvert_mono.v"
"ddr.v"
"ddr_parameters.v"
"descrproc353.v"
"dma_fifo353.v"
"encoderDCAC353.v"
"extjtag.v"
"focus_filt.dat"
"focus_sharp.v"
"glbl.v"
"gps_data.dat"
"histogram353.v"
"huffman.dat"
"huffman333.v"
"i2c_writeonly.v"
"imu_logger.v"
"interrupts_vector333.v"
"ioports353.v"
"irq_smart.v"
"lens_flat.v"
"linear1028rgb.dat"
"macros353.v"
"mcontr353.v"
"motor.dat"
"motors_sim.sh"
"motors_tb.v"
"quantization_100.dat"
"quantizator353.v"
"rtc353.v"
"sdram_phase.v"
"sdseq353.v"
"sensdcclk333.v"
"sensor.dat"
"sensor12bits.v"
"sensor_phase353.v"
"sensorpads353.v"
"sensorpix353.v"
"sensortrig.v"
"stuffer333.v"
"twelve_ios.v"
"x353.ucf"
"x353.v"
"x353_1.sav"
"x353_1.tf"
"x353_guide.ncd"
"x353_sim.sh"
"xdct353.v"}
INFO "Copying files from \"$staging_area\" to \"$working_area\""
# Must be in the staging directory before calling CopyIn.
cd [file normalize "$staging_area"]
foreach file $import_files {
CopyIn "$file" "$working_area" $copy_option
}
set iProjHelper 0
# Bail if a project currently open.
if {[IsProjectOpen]} {
ERR "The project must be closed before performing this operation."
return 0
}
# Must be in the working area (i.e. project directory) before calling recreating the project.
cd [file normalize "$working_area"]
INFO "Recreating project \"$project_file\"."
HandleException {
set iProjHelper [ OpenFacilProject "$project_file"]
} "A problem occurred while creating the project \"$project_file\"."
if {$iProjHelper == 0} {
cd "$old_working_dir"
return 0
}
set project_settings {
"PROP_DevFamily" "Spartan3E"
"PROP_DevDevice" "xc3s1200e"
"PROP_DevPackage" "ft256"
"PROP_DevSpeed" "-4"
"PROP_Top_Level_Module_Type" "HDL"
"PROP_Synthesis_Tool" "XST (VHDL/Verilog)"
"PROP_Simulator" "ISE Simulator (VHDL/Verilog)"
"PROP_PreferredLanguage" "Verilog"
"PROP_Enable_Message_Capture" "true"
"PROP_Enable_Message_Filtering" "true"
"PROP_Enable_Incremental_Messaging" "true"
}
HandleException {
RestoreProjectSettings $iProjHelper $project_settings
} "A problem occured while restoring project settings."
set user_files {
"10364.v"
"camsync.v"
"clkios353.v"
"cmd_sequencer.v"
"color_proc353.v"
"compressor333.v"
"control_regs.v"
"coring.dat"
"csconvert18.v"
"csconvert_mono.v"
"ddr.v"
"ddr_parameters.v"
"descrproc353.v"
"dma_fifo353.v"
"encoderDCAC353.v"
"extjtag.v"
"focus_filt.dat"
"focus_sharp.v"
"glbl.v"
"gps_data.dat"
"histogram353.v"
"huffman.dat"
"huffman333.v"
"i2c_writeonly.v"
"imu_logger.v"
"interrupts_vector333.v"
"ioports353.v"
"irq_smart.v"
"lens_flat.v"
"linear1028rgb.dat"
"macros353.v"
"mcontr353.v"
"motor.dat"
"motors_sim.sh"
"motors_tb.v"
"quantization_100.dat"
"quantizator353.v"
"rtc353.v"
"sdram_phase.v"
"sdseq353.v"
"sensdcclk333.v"
"sensor.dat"
"sensor12bits.v"
"sensor_phase353.v"
"sensorpads353.v"
"sensorpix353.v"
"sensortrig.v"
"stuffer333.v"
"twelve_ios.v"
"x353.ucf"
"x353.v"
"x353_1.sav"
"x353_1.tf"
"x353_sim.sh"
"xdct353.v"}
HandleException {
AddUserFiles $iProjHelper $user_files
} "A problem occured while restoring user files."
set imported_files {
"x353_guide.ncd"}
set origination 2
HandleException {
AddImportedFiles $iProjHelper $imported_files $origination
} "A problem occured while restoring imported files."
set process_props {
"A" "" "" "" "PROPEXT_SynthMultStyle_virtex2" "Auto"
"A" "" "" "" "PROPEXT_xilxBitgCfg_DCIUpdateMode_spartan3" "As Required"
"A" "" "" "" "PROPEXT_xilxBitgCfg_Rate_spartan3" "Default (6)"
"A" "" "" "" "PROPEXT_xilxBitgCfg_Rate_spartan3e" "Default (1)"
"A" "" "" "" "PROPEXT_xilxMapGenInputK_virtex2" "4"
"A" "" "" "" "PROPEXT_xilxSynthAddBufg_spartan3" "8"
"A" "" "" "" "PROPEXT_xilxSynthAddBufg_spartan3e" "24"
"A" "" "" "" "PROPEXT_xilxSynthMaxFanout_virtex2" "500"
"A" "" "" "" "PROP_AutoGenFile" "false"
"A" "" "" "" "PROP_BehavioralSimTop" "Module|testbench"
"A" "" "" "" "PROP_CPLDFitkeepio" "false"
"A" "" "" "" "PROP_CompxlibAbelLib" "true"
"A" "" "" "" "PROP_CompxlibCPLDDetLib" "true"
"A" "" "" "" "PROP_CompxlibOtherCompxlibOpts" ""
"A" "" "" "" "PROP_CompxlibOutputDir" "$XILINX/<language>/<simulator>"
"A" "" "" "" "PROP_CompxlibOverwriteLib" "Overwrite"
"A" "" "" "" "PROP_CompxlibSimPrimatives" "true"
"A" "" "" "" "PROP_CompxlibXlnxCoreLib" "true"
"A" "" "" "" "PROP_ConstFileAddOption" "true"
"A" "" "" "" "PROP_ConstFileName" ""
"A" "" "" "" "PROP_CorgenRegenCore" "Under Current Project Setting"
"A" "" "" "" "PROP_CurrentFloorplanFile" ""
"A" "" "" "" "PROP_DefaultTBName" "Default"
"A" "" "" "" "PROP_DesignName" ""
"A" "" "" "" "PROP_Dummy" "dum1"
"A" "" "" "" "PROP_EnableWYSIWYG" "None"
"A" "" "" "" "PROP_Enable_Incremental_Messaging" "false"
"A" "" "" "" "PROP_Enable_Message_Capture" "true"
"A" "" "" "" "PROP_Enable_Message_Filtering" "false"
"A" "" "" "" "PROP_FitterReportFormat" "HTML"
"A" "" "" "" "PROP_FlowDebugLevel" "0"
"A" "" "" "" "PROP_FunctionBlockInputLimit" "38"
"A" "" "" "" "PROP_HierarchicalProjectType" "N/A"
"A" "" "" "" "PROP_ISimLibSearchOrderFile" ""
"A" "" "" "" "PROP_ISimOtherCompilerOptions_behav" ""
"A" "" "" "" "PROP_ISimOtherCompilerOptions_fit" ""
"A" "" "" "" "PROP_ISimOtherCompilerOptions_par" ""
"A" "" "" "" "PROP_ISimSDFTimingToBeRead" "Setup Time"
"A" "" "" "" "PROP_ISimSpecifyDefMacroAndValueChkSyntax" ""
"A" "" "" "" "PROP_ISimSpecifySearchDirectoryChkSyntax" ""
"A" "" "" "" "PROP_ISimUseCustomCompilationOrder" "false"
"A" "" "" "" "PROP_ISimUseCustomSimCmdFile_behav_tb" "false"
"A" "" "" "" "PROP_ISimUseCustomSimCmdFile_behav_tbw" "false"
"A" "" "" "" "PROP_ISimUseCustomSimCmdFile_gen_tbw" "false"
"A" "" "" "" "PROP_ISimUseCustomSimCmdFile_launch" "false"
"A" "" "" "" "PROP_ISimUseCustomSimCmdFile_par_tb" "false"
"A" "" "" "" "PROP_ISimUseCustomSimCmdFile_par_tbw" "false"
"A" "" "" "" "PROP_ISimUutInstName" "UUT"
"A" "" "" "" "PROP_ImpactProjectFile" "Default"
"A" "" "" "" "PROP_LastAppliedGoal" "Balanced"
"A" "" "" "" "PROP_LastAppliedStrategy" "Xilinx Default (unlocked)"
"A" "" "" "" "PROP_LastUnlockStatus" "false"
"A" "" "" "" "PROP_LoadPostTrceTSIFile" "false"
"A" "" "" "" "PROP_MSimSDFTimingToBeRead" "Setup Time"
"A" "" "" "" "PROP_MapGlobalOptimization" "false"
"A" "" "" "" "PROP_ModelSimUseConfigName" "false"
"A" "" "" "" "PROP_OverwriteSym" "false"
"A" "" "" "" "PROP_Parse_Edif_Module" "false"
"A" "" "" "" "PROP_Parse_Target" "synthesis"
"A" "" "" "" "PROP_PartitionCreateDelete" ""
"A" "" "" "" "PROP_PartitionForcePlacement" ""
"A" "" "" "" "PROP_PartitionForceSynth" ""
"A" "" "" "" "PROP_PartitionForceTranslate" ""
"A" "" "" "" "PROP_PlsClockEnable" "true"
"A" "" "" "" "PROP_PostFitSimTop" ""
"A" "" "" "" "PROP_PostMapSimTop" "Module|testbench"
"A" "" "" "" "PROP_PostParSimTop" "Module|testbench"
"A" "" "" "" "PROP_PostSynthSimTop" "Module|testbench"
"A" "" "" "" "PROP_PostTrceFastPath" "false"
"A" "" "" "" "PROP_PostTrceGenDatasheet" "true"
"A" "" "" "" "PROP_PostTrceGenTimegroups" "false"
"A" "" "" "" "PROP_PostXlateSimTop" "Module|testbench"
"A" "" "" "" "PROP_PreTrceFastPath" "false"
"A" "" "" "" "PROP_PreTrceGenDatasheet" "true"
"A" "" "" "" "PROP_PreTrceGenTimegroups" "false"
"A" "" "" "" "PROP_PreTrceTSIFile" ""
"A" "" "" "" "PROP_PrecAddIOPads" "true"
"A" "" "" "" "PROP_PrecAdvFsmOptimization" "true"
"A" "" "" "" "PROP_PrecArrayBoundsCheck" "false"
"A" "" "" "" "PROP_PrecCreateUcfFromRtlConstraints" "false"
"A" "" "" "" "PROP_PrecEdif" "true"
"A" "" "" "" "PROP_PrecFsmEncoding" "Auto"
"A" "" "" "" "PROP_PrecFullCase" "false"
"A" "" "" "" "PROP_PrecInputSdcFile" ""
"A" "" "" "" "PROP_PrecOutputFileBase" ""
"A" "" "" "" "PROP_PrecParallelCase" "false"
"A" "" "" "" "PROP_PrecResourceSharing" "true"
"A" "" "" "" "PROP_PrecRptCriticalPaths" "true"
"A" "" "" "" "PROP_PrecRptMissingConstraints" "false"
"A" "" "" "" "PROP_PrecRptTimingSummary" "true"
"A" "" "" "" "PROP_PrecRptTimingViolations" "true"
"A" "" "" "" "PROP_PrecRptclockFreq" "true"
"A" "" "" "" "PROP_PrecRunRetiming" "false"
"A" "" "" "" "PROP_PrecShowClockDomainCrossing" "false"
"A" "" "" "" "PROP_PrecShowNetFanOut" "true"
"A" "" "" "" "PROP_PrecTranSetResetToLatches" "true"
"A" "" "" "" "PROP_PrecUseSafeFsm" "false"
"A" "" "" "" "PROP_PrecVerilog" "false"
"A" "" "" "" "PROP_PrecVhdl" "false"
"A" "" "" "" "PROP_PrecVhdlSyntax" "VHDL 93"
"A" "" "" "" "PROP_ProjectGeneratorType" "ProjNav"
"A" "" "" "" "PROP_SimDo" "true"
"A" "" "" "" "PROP_SimModelGenerateTestbenchFile" "false"
"A" "" "" "" "PROP_SimModelInsertBuffersPulseSwallow" "false"
"A" "" "" "" "PROP_SimModelOtherNetgenOpts" ""
"A" "" "" "" "PROP_SimModelRetainHierarchy" "true"
"A" "" "" "" "PROP_SimUseCustom_behav" "false"
"A" "" "" "" "PROP_SimUseCustom_launchMSim" "false"
"A" "" "" "" "PROP_SimUseCustom_postMap" "false"
"A" "" "" "" "PROP_SimUseCustom_postPar" "false"
"A" "" "" "" "PROP_SimUseCustom_postXlate" "false"
"A" "" "" "" "PROP_SimUserCompileList_launchMSim" ""
"A" "" "" "" "PROP_StartImpView" ""
"A" "" "" "" "PROP_StopImpView" "AbstractSynthesis"
"A" "" "" "" "PROP_SynthCaseImplStyle" "None"
"A" "" "" "" "PROP_SynthDecoderExtract" "true"
"A" "" "" "" "PROP_SynthDisableIOInsertion" "false"
"A" "" "" "" "PROP_SynthEncoderExtract" "Yes"
"A" "" "" "" "PROP_SynthEnumEncoding" "default"
"A" "" "" "" "PROP_SynthExtractMux" "Yes"
"A" "" "" "" "PROP_SynthExtractRAM" "true"
"A" "" "" "" "PROP_SynthExtractROM" "true"
"A" "" "" "" "PROP_SynthFanout" "100"
"A" "" "" "" "PROP_SynthFsmEncode" "Auto"
"A" "" "" "" "PROP_SynthLogicalShifterExtract" "true"
"A" "" "" "" "PROP_SynthModular" "false"
"A" "" "" "" "PROP_SynthNumCriticalPaths" "0"
"A" "" "" "" "PROP_SynthNumStartEndPoints" "0"
"A" "" "" "" "PROP_SynthOpt" "Speed"
"A" "" "" "" "PROP_SynthOptEffort" "High"
"A" "" "" "" "PROP_SynthPipelining" "true"
"A" "" "" "" "PROP_SynthProcBound" "true"
"A" "" "" "" "PROP_SynthResSharing" "true"
"A" "" "" "" "PROP_SynthResourceSharing" "true"
"A" "" "" "" "PROP_SynthRetiming" "false"
"A" "" "" "" "PROP_SynthShiftRegExtract" "false"
"A" "" "" "" "PROP_SynthSymbolicFsm" "true"
"A" "" "" "" "PROP_SynthTop" "Module|x353"
"A" "" "" "" "PROP_SynthUseFsmExplorerData" "false"
"A" "" "" "" "PROP_SynthXORCollapse" "true"
"A" "" "" "" "PROP_ToolPathChipscope" ""
"A" "" "" "" "PROP_ToolPathLeonardoSpectrum" ""
"A" "" "" "" "PROP_ToolPathModelSim" ""
"A" "" "" "" "PROP_ToolPathPrecision" ""
"A" "" "" "" "PROP_ToolPathSynplify" ""
"A" "" "" "" "PROP_ToolPathSynplifyPro" ""
"A" "" "" "" "PROP_Top_Level_Module_Type" "HDL"
"A" "" "" "" "PROP_UseDataGate" "true"
"A" "" "" "" "PROP_UseSmartGuide" "false"
"A" "" "" "" "PROP_UserBrowsedStrategyFiles" ""
"A" "" "" "" "PROP_UserConstraintEditorPreference" "Constraints Editor"
"A" "" "" "" "PROP_UserEditorCustomSetting" ""
"A" "" "" "" "PROP_UserEditorPreference" "ISE Text Editor"
"A" "" "" "" "PROP_Verilog2001" "true"
"A" "" "" "" "PROP_VirtexSynthAutoConstrain" "true"
"A" "" "" "" "PROP_WriteVHDLNetlist" "false"
"A" "" "" "" "PROP_WriteVendorConstFile" "true"
"A" "" "" "" "PROP_WriteVerilogNetlist" "false"
"A" "" "" "" "PROP_XPORTInpFileName" ""
"A" "" "" "" "PROP_XPORTInpFileType" "ABEL"
"A" "" "" "" "PROP_XPORTOutFileType" "VHDL"
"A" "" "" "" "PROP_XPORTlistInpFiles" "false"
"A" "" "" "" "PROP_XPowerOptInputTclScript" ""
"A" "" "" "" "PROP_XPowerOptLoadPCFFile" "Default"
"A" "" "" "" "PROP_XPowerOptLoadVCDFile" "Default"
"A" "" "" "" "PROP_XPowerOptLoadXMLFile" "Default"
"A" "" "" "" "PROP_XPowerOptOutputFile" "Default"
"A" "" "" "" "PROP_XPowerOptVerboseRpt" "false"
"A" "" "" "" "PROP_XPowerOtherXPowerOpts" ""
"A" "" "" "" "PROP_XplorerMode" "Off"
"A" "" "" "" "PROP_bitgen_Encrypt_keySeq0" "None"
"A" "" "" "" "PROP_bitgen_Encrypt_keySeq1" "None"
"A" "" "" "" "PROP_bitgen_Encrypt_keySeq2" "None"
"A" "" "" "" "PROP_bitgen_Encrypt_keySeq3" "None"
"A" "" "" "" "PROP_bitgen_Encrypt_keySeq4" "None"
"A" "" "" "" "PROP_bitgen_Encrypt_keySeq5" "None"
"A" "" "" "" "PROP_bitgen_Encrypt_startCBC" ""
"A" "" "" "" "PROP_bitgen_Encrypt_startKey" "None"
"A" "" "" "" "PROP_bitgen_otherCmdLineOptions" ""
"A" "" "" "" "PROP_cpldBestFit" "false"
"A" "" "" "" "PROP_cpldfitHDLeqStyle" "Source"
"A" "" "" "" "PROP_cpldfit_otherCmdLineOptions" ""
"A" "" "" "" "PROP_fitGenSimModel" "false"
"A" "" "" "" "PROP_hprep6_autosig" "false"
"A" "" "" "" "PROP_hprep6_otherCmdLineOptions" ""
"A" "" "" "" "PROP_ibiswriterGeneratePackageParasitics" "false"
"A" "" "" "" "PROP_ibiswriterShowAllModels" "false"
"A" "" "" "" "PROP_impactConfigFileName_CPLD" ""
"A" "" "" "" "PROP_isimCompileForHdlDebug" "true"
"A" "" "" "" "PROP_isimIncreCompilation" "true"
"A" "" "" "" "PROP_isimSpecifyDefMacroAndValue" ""
"A" "" "" "" "PROP_isimSpecifySearchDirectory" ""
"A" "" "" "" "PROP_isimValueRangeCheck" "false"
"A" "" "" "" "PROP_lockPinsUcfFile" ""
"A" "" "" "" "PROP_mapIgnoreTimingConstraints" "false"
"A" "" "" "" "PROP_mapTimingAnalyzerLoadDesign" "true"
"A" "" "" "" "PROP_mapUseRLOCConstraints" "true"
"A" "" "" "" "PROP_map_otherCmdLineOptions" ""
"A" "" "" "" "PROP_mpprRsltToCopy" ""
"A" "" "" "" "PROP_mpprViewPadRptsForAllRslt" "true"
"A" "" "" "" "PROP_mpprViewParRptsForAllRslt" "true"
"A" "" "" "" "PROP_ngdbuildUseLOCConstraints" "true"
"A" "" "" "" "PROP_ngdbuild_otherCmdLineOptions" ""
"A" "" "" "" "PROP_parIgnoreTimingConstraints" "false"
"A" "" "" "" "PROP_parTimingAnalyzerLoadDesign" "true"
"A" "" "" "" "PROP_parUseTimingConstraints" "true"
"A" "" "" "" "PROP_par_otherCmdLineOptions" ""
"A" "" "" "" "PROP_primeCorrelateOutput" "false"
"A" "" "" "" "PROP_primeFlatternOutputNetlist" "false"
"A" "" "" "" "PROP_primeTopLevelModule" ""
"A" "" "" "" "PROP_primetimeBlockRamData" ""
"A" "" "" "" "PROP_taengine_otherCmdLineOptions" ""
"A" "" "" "" "PROP_usedsp48" "Auto"
"A" "" "" "" "PROP_xcpldFitDesInit" "Low"
"A" "" "" "" "PROP_xcpldFitDesInputLmt_xbr" "32"
"A" "" "" "" "PROP_xcpldFitDesMultiLogicOpt" "true"
"A" "" "" "" "PROP_xcpldFitDesSlew" "Fast"
"A" "" "" "" "PROP_xcpldFitDesTimingCst" "true"
"A" "" "" "" "PROP_xcpldFitDesTriMode" "Keeper"
"A" "" "" "" "PROP_xcpldFitDesUnused" "Keeper"
"A" "" "" "" "PROP_xcpldFitDesVolt" "LVCMOS18"
"A" "" "" "" "PROP_xcpldFitTemplate_xpla3" "Optimize Density"
"A" "" "" "" "PROP_xcpldFittimRptOption" "Summary"
"A" "" "" "" "PROP_xcpldUseGlobalClocks" "true"
"A" "" "" "" "PROP_xcpldUseGlobalOutputEnables" "true"
"A" "" "" "" "PROP_xcpldUseGlobalSetReset" "true"
"A" "" "" "" "PROP_xcpldUseLocConst" "Always"
"A" "" "" "" "PROP_xilxBitgCfg_Clk" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_Code" "0xFFFFFFFF"
"A" "" "" "" "PROP_xilxBitgCfg_DCMBandgap" "false"
"A" "" "" "" "PROP_xilxBitgCfg_DCMShutdown" "false"
"A" "" "" "" "PROP_xilxBitgCfg_Done" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_ASCIIFile" "false"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_BinaryFile" "false"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_BitFile" "true"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_Compress" "false"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_DRC" "true"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_EnableCRC" "true"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_GClkDel0" "11111"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_GClkDel1" "11111"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_GClkDel2" "11111"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_GClkDel3" "11111"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_IEEE1532File" "false"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_IEEE1532File_xbr" "false"
"A" "" "" "" "PROP_xilxBitgCfg_GenOpt_ReadBack" "false"
"A" "" "" "" "PROP_xilxBitgCfg_M0" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_M1" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_M2" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_Pgm" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_PwrDown" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_TCK" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_TDI" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_TDO" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_TMS" "Pull Up"
"A" "" "" "" "PROP_xilxBitgCfg_Unused" "Pull Down"
"A" "" "" "" "PROP_xilxBitgReadBk_Sec" "Enable Readback and Reconfiguration"
"A" "" "" "" "PROP_xilxBitgStart_Clk" "CCLK"
"A" "" "" "" "PROP_xilxBitgStart_Clk_Done" "Default (4)"
"A" "" "" "" "PROP_xilxBitgStart_Clk_DriveDone" "false"
"A" "" "" "" "PROP_xilxBitgStart_Clk_EnOut" "Default (5)"
"A" "" "" "" "PROP_xilxBitgStart_Clk_MatchCycle" "Auto"
"A" "" "" "" "PROP_xilxBitgStart_Clk_RelDLL" "Default (NoWait)"
"A" "" "" "" "PROP_xilxBitgStart_Clk_RelSet" "Default (6)"
"A" "" "" "" "PROP_xilxBitgStart_Clk_WrtEn" "Default (6)"
"A" "" "" "" "PROP_xilxBitgStart_IntDone" "false"
"A" "" "" "" "PROP_xilxMapAllowLogicOpt" "false"
"A" "" "" "" "PROP_xilxMapCoverMode" "Speed"
"A" "" "" "" "PROP_xilxMapDisableRegOrdering" "false"
"A" "" "" "" "PROP_xilxMapPackRegInto" "Off"
"A" "" "" "" "PROP_xilxMapReplicateLogic" "true"
"A" "" "" "" "PROP_xilxMapReportDetail" "true"
"A" "" "" "" "PROP_xilxMapSliceLogicInUnusedBRAMs" "false"
"A" "" "" "" "PROP_xilxMapTimingDrivenPacking" "true"
"A" "" "" "" "PROP_xilxMapTrimUnconnSig" "true"
"A" "" "" "" "PROP_xilxNgdbldIOPads" "false"
"A" "" "" "" "PROP_xilxNgdbldMacro" ""
"A" "" "" "" "PROP_xilxNgdbldNTType" "Timestamp"
"A" "" "" "" "PROP_xilxNgdbldPresHierarchy" "false"
"A" "" "" "" "PROP_xilxNgdbldUR" ""
"A" "" "" "" "PROP_xilxNgdbldUnexpBlks" "false"
"A" "" "" "" "PROP_xilxNgdbld_AUL" "false"
"A" "" "" "" "PROP_xilxPARplacerCostTable" "3"
"A" "" "" "" "PROP_xilxPARplacerEffortLevel" "High"
"A" "" "" "" "PROP_xilxPARrouterEffortLevel" "High"
"A" "" "" "" "PROP_xilxPARstrat" "Normal Place and Route"
"A" "" "" "" "PROP_xilxPARuseBondedIO" "false"
"A" "" "" "" "PROP_xilxPostTrceAdvAna" "false"
"A" "" "" "" "PROP_xilxPostTrceEndpointPath" ""
"A" "" "" "" "PROP_xilxPostTrceRpt" "Verbose Report"
"A" "" "" "" "PROP_xilxPostTrceRptLimit" "3"
"A" "" "" "" "PROP_xilxPostTrceStamp" ""
"A" "" "" "" "PROP_xilxPostTrceTSIFile" ""
"A" "" "" "" "PROP_xilxPostTrceUncovPath" ""
"A" "" "" "" "PROP_xilxPreTrceAdvAna" "false"
"A" "" "" "" "PROP_xilxPreTrceEndpointPath" ""
"A" "" "" "" "PROP_xilxPreTrceRpt" "Verbose Report"
"A" "" "" "" "PROP_xilxPreTrceRptLimit" "3"
"A" "" "" "" "PROP_xilxPreTrceUncovPath" ""
"A" "" "" "" "PROP_xilxSynthAddIObuf" "true"
"A" "" "" "" "PROP_xilxSynthGlobOpt" "AllClockNets"
"A" "" "" "" "PROP_xilxSynthKeepHierarchy" "No"
"A" "" "" "" "PROP_xilxSynthKeepHierarchy_CPLD" "Yes"
"A" "" "" "" "PROP_xilxSynthMacroPreserve" "true"
"A" "" "" "" "PROP_xilxSynthRegBalancing" "No"
"A" "" "" "" "PROP_xilxSynthRegDuplication" "true"
"A" "" "" "" "PROP_xilxSynthXORPreserve" "true"
"A" "" "" "" "PROP_xilxTriStateBuffTXMode" "Off"
"A" "" "" "" "PROP_xstAsynToSync" "false"
"A" "" "" "" "PROP_xstAutoBRAMPacking" "false"
"A" "" "" "" "PROP_xstBRAMUtilRatio" "100"
"A" "" "" "" "PROP_xstBusDelimiter" "<>"
"A" "" "" "" "PROP_xstCase" "Maintain"
"A" "" "" "" "PROP_xstCoresSearchDir" ""
"A" "" "" "" "PROP_xstCrossClockAnalysis" "false"
"A" "" "" "" "PROP_xstDSPUtilRatio" "100"
"A" "" "" "" "PROP_xstEquivRegRemoval" "true"
"A" "" "" "" "PROP_xstFsmStyle" "LUT"
"A" "" "" "" "PROP_xstGenerateRTLNetlist" "Yes"
"A" "" "" "" "PROP_xstGenericsParameters" ""
"A" "" "" "" "PROP_xstHierarchySeparator" "/"
"A" "" "" "" "PROP_xstIniFile" ""
"A" "" "" "" "PROP_xstLibSearchOrder" ""
"A" "" "" "" "PROP_xstNetlistHierarchy" "As Optimized"
"A" "" "" "" "PROP_xstOptimizeInsPrimtives" "false"
"A" "" "" "" "PROP_xstPackIORegister" "Auto"
"A" "" "" "" "PROP_xstReadCores" "true"
"A" "" "" "" "PROP_xstSlicePacking" "true"
"A" "" "" "" "PROP_xstSliceUtilRatio" "100"
"A" "" "" "" "PROP_xstTristate2Logic" "Yes"
"A" "" "" "" "PROP_xstUseClockEnable" "Yes"
"A" "" "" "" "PROP_xstUseSyncReset" "Yes"
"A" "" "" "" "PROP_xstUseSyncSet" "Yes"
"A" "" "" "" "PROP_xstUseSynthConstFile" "true"
"A" "" "" "" "PROP_xstUserCompileList" ""
"A" "" "" "" "PROP_xstVeriIncludeDir_Global" ""
"A" "" "" "" "PROP_xstVerilog2001" "true"
"A" "" "" "" "PROP_xstVerilogMacros" ""
"A" "" "" "" "PROP_xstWorkDir" "./xst"
"A" "" "" "" "PROP_xstWriteTimingConstraints" "false"
"A" "" "" "" "PROP_xst_otherCmdLineOptions" ""
"A" "" "" "PROP_SteCreatedBy" "PROP_SteCreatedBy" ""
"A" "AutoGeneratedView" "VIEW_AbstractSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_AnalyzedDesign" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_AnnotatedPreSimulation" "" "PROP_ISimIncreCompilation" "true"
"A" "AutoGeneratedView" "VIEW_AnnotatedPreSimulation" "" "PROP_ISimSpecifyDefMacroAndValue" ""
"A" "AutoGeneratedView" "VIEW_AnnotatedPreSimulation" "" "PROP_ISimSpecifySearchDirectory" ""
"A" "AutoGeneratedView" "VIEW_AnnotatedPreSimulation" "" "PROP_ISimValueRangeCheck" "false"
"A" "AutoGeneratedView" "VIEW_AnnotatedPreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_AnnotatedResultsFuse" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_AnnotatedResultsISim" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_BehavioralFuse" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_BehavioralSimulationISim" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_FPGAConfiguration" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_FPGAConfigureDevice" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_FPGAGeneratePROM" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Map" "" "PROP_SmartGuide" "false"
"A" "AutoGeneratedView" "VIEW_Map" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Par" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-MapAbstractSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-MapPreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-ParAbstractSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-ParFuse" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-ParPreSimulation" "" "PROP_ISimCompileForHdlDebug" "true"
"A" "AutoGeneratedView" "VIEW_Post-ParPreSimulation" "" "PROP_ISimIncreCompilation" "true"
"A" "AutoGeneratedView" "VIEW_Post-ParPreSimulation" "" "PROP_ISimSpecifyDefMacroAndValue" ""
"A" "AutoGeneratedView" "VIEW_Post-ParPreSimulation" "" "PROP_ISimSpecifySearchDirectory" ""
"A" "AutoGeneratedView" "VIEW_Post-ParPreSimulation" "" "PROP_ISimValueRangeCheck" "false"
"A" "AutoGeneratedView" "VIEW_Post-ParPreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-ParSimulationISim" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-SynthesisAbstractSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-TranslateAbstractSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Post-TranslatePreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_PostAbstractSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_PreSimulation" "" "PROP_ISimCompileForHdlDebug" "true"
"A" "AutoGeneratedView" "VIEW_PreSimulation" "" "PROP_ISimIncreCompilation" "true"
"A" "AutoGeneratedView" "VIEW_PreSimulation" "" "PROP_ISimSpecifyDefMacroAndValue" ""
"A" "AutoGeneratedView" "VIEW_PreSimulation" "" "PROP_ISimSpecifySearchDir" ""
"A" "AutoGeneratedView" "VIEW_PreSimulation" "" "PROP_ISimSpecifySearchDirectory" ""
"A" "AutoGeneratedView" "VIEW_PreSimulation" "" "PROP_ISimValueRangeCheck" "false"
"A" "AutoGeneratedView" "VIEW_PreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Structural" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_TBWBehavioralFuse" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_TBWBehavioralSimulationISim" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_TBWPost-MapPreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_TBWPost-ParFuse" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_TBWPost-ParPreSimulation" "" "PROP_ISimCompileForHdlDebug" "true"
"A" "AutoGeneratedView" "VIEW_TBWPost-ParPreSimulation" "" "PROP_ISimIncreCompilation" "true"
"A" "AutoGeneratedView" "VIEW_TBWPost-ParPreSimulation" "" "PROP_ISimSpecifyDefMacroAndValue" ""
"A" "AutoGeneratedView" "VIEW_TBWPost-ParPreSimulation" "" "PROP_ISimSpecifySearchDirectory" ""
"A" "AutoGeneratedView" "VIEW_TBWPost-ParPreSimulation" "" "PROP_ISimValueRangeCheck" "false"
"A" "AutoGeneratedView" "VIEW_TBWPost-ParPreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_TBWPost-ParSimulationISim" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_TBWPost-TranslatePreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_TBWPreSimulation" "" "PROP_ISimCompileForHdlDebug" "true"
"A" "AutoGeneratedView" "VIEW_TBWPreSimulation" "" "PROP_ISimIncreCompilation" "true"
"A" "AutoGeneratedView" "VIEW_TBWPreSimulation" "" "PROP_ISimSpecifyDefMacroAndValue" ""
"A" "AutoGeneratedView" "VIEW_TBWPreSimulation" "" "PROP_ISimSpecifySearchDirectory" ""
"A" "AutoGeneratedView" "VIEW_TBWPreSimulation" "" "PROP_ISimValueRangeCheck" "false"
"A" "AutoGeneratedView" "VIEW_TBWPreSimulation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_Translation" "" "PROP_SmartGuide" "false"
"A" "AutoGeneratedView" "VIEW_Translation" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_UpdatedBitstream" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_XSTAbstractSynthesis" "" "PROP_SmartGuide" "false"
"A" "AutoGeneratedView" "VIEW_XSTAbstractSynthesis" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_XSTPreSynthesis" "" "PROP_TopDesignUnit" ""
"A" "AutoGeneratedView" "VIEW_XSTPreSynthesis" "" "PROP_xstVeriIncludeDir" ""
"A" "VIEW_Initial" "VIEW_Initial" "" "PROP_TopDesignUnit" ""
"B" "" "" "" "PROPEXT_SynthFrequencySyn_virtex" "0.0"
"B" "" "" "" "PROP_AceActiveName" ""
"B" "" "" "" "PROP_DevFamily" "Spartan3E"
"B" "" "" "" "PROP_FitterOptimization_xpla3" "Density"
"B" "" "" "" "PROP_ISimCustomCompilationOrderFile" ""
"B" "" "" "" "PROP_ISimCustomSimCmdFileName_behav_tb" ""
"B" "" "" "" "PROP_ISimCustomSimCmdFileName_behav_tbw" ""
"B" "" "" "" "PROP_ISimCustomSimCmdFileName_gen_tbw" ""
"B" "" "" "" "PROP_ISimCustomSimCmdFileName_launch" ""
"B" "" "" "" "PROP_ISimCustomSimCmdFileName_par_tb" ""
"B" "" "" "" "PROP_ISimCustomSimCmdFileName_par_tbw" ""
"B" "" "" "" "PROP_ISimGenVCDFile_par_tb" "false"
"B" "" "" "" "PROP_ISimGenVCDFile_par_tbw" "false"
"B" "" "" "" "PROP_ISimSimulationRun_behav_tb" "true"
"B" "" "" "" "PROP_ISimSimulationRun_behav_tbw" "true"
"B" "" "" "" "PROP_ISimSimulationRun_par_tb" "true"
"B" "" "" "" "PROP_ISimSimulationRun_par_tbw" "true"
"B" "" "" "" "PROP_ISimStoreAllSignalTransitions_behav_tb" "false"
"B" "" "" "" "PROP_ISimStoreAllSignalTransitions_behav_tbw" "false"
"B" "" "" "" "PROP_ISimStoreAllSignalTransitions_par_tb" "false"
"B" "" "" "" "PROP_ISimStoreAllSignalTransitions_par_tbw" "false"
"B" "" "" "" "PROP_MapEffortLevel" "High"
"B" "" "" "" "PROP_MapEquivalentRegisterRemoval" "true"
"B" "" "" "" "PROP_MapLogicOptimization" "true"
"B" "" "" "" "PROP_MapPlacerCostTable" "5"
"B" "" "" "" "PROP_MapPowerReduction" "false"
"B" "" "" "" "PROP_MapRegDuplication" "true"
"B" "" "" "" "PROP_MapRetiming" "false"
"B" "" "" "" "PROP_ModelSimConfigName" "Default"
"B" "" "" "" "PROP_ModelSimDataWin" "false"
"B" "" "" "" "PROP_ModelSimListWin" "false"
"B" "" "" "" "PROP_ModelSimProcWin" "false"
"B" "" "" "" "PROP_ModelSimSignalWin" "true"
"B" "" "" "" "PROP_ModelSimSimRes" "Default (1 ps)"
"B" "" "" "" "PROP_ModelSimSimRunTime_tb" "1000ns"
"B" "" "" "" "PROP_ModelSimSimRunTime_tbw" "1000ns"
"B" "" "" "" "PROP_ModelSimSourceWin" "false"
"B" "" "" "" "PROP_ModelSimStructWin" "true"
"B" "" "" "" "PROP_ModelSimUutInstName_postFit" "UUT"
"B" "" "" "" "PROP_ModelSimUutInstName_postMap" "UUT"
"B" "" "" "" "PROP_ModelSimUutInstName_postPar" "UUT"
"B" "" "" "" "PROP_ModelSimVarsWin" "false"
"B" "" "" "" "PROP_ModelSimWaveWin" "true"
"B" "" "" "" "PROP_PrecNumOfCriticalPaths" "1"
"B" "" "" "" "PROP_PrecNumOfSumPaths" "10"
"B" "" "" "" "PROP_SimCustom_behav" ""
"B" "" "" "" "PROP_SimCustom_launchMSim" ""
"B" "" "" "" "PROP_SimCustom_postMap" ""
"B" "" "" "" "PROP_SimCustom_postPar" ""
"B" "" "" "" "PROP_SimCustom_postXlate" ""
"B" "" "" "" "PROP_SimGenVcdFile" "false"
"B" "" "" "" "PROP_SimModelRenTopLevInstTo" "UUT"
"B" "" "" "" "PROP_SimSyntax" "93"
"B" "" "" "" "PROP_SimUseExpDeclOnly" "true"
"B" "" "" "" "PROP_SimUserCompileList_behav" ""
"B" "" "" "" "PROP_Simulator" "ISE Simulator (VHDL/Verilog)"
"B" "" "" "" "PROP_SmartGuideFileName" "x353_guide.ncd"
"B" "" "" "" "PROP_SynthConstraintsFile" ""
"B" "" "" "" "PROP_SynthMuxStyle" "Auto"
"B" "" "" "" "PROP_SynthRAMStyle" "Auto"
"B" "" "" "" "PROP_XPowerOptAdvancedVerboseRpt" "false"
"B" "" "" "" "PROP_XPowerOptMaxNumberLines" "1000"
"B" "" "" "" "PROP_XPowerOptUseTimeBased" "false"
"B" "" "" "" "PROP_XplorerEnableRetiming" "true"
"B" "" "" "" "PROP_XplorerNumIterations" "7"
"B" "" "" "" "PROP_XplorerOtherCmdLineOptions" ""
"B" "" "" "" "PROP_XplorerRunType" "Yes"
"B" "" "" "" "PROP_XplorerSearchPathForSource" ""
"B" "" "" "" "PROP_XplorerWarnToBackup" "true"
"B" "" "" "" "PROP_bitgen_Encrypt_Encrypt" "false"
"B" "" "" "" "PROP_impactBaud" "None"
"B" "" "" "" "PROP_impactConfigFileName" ""
"B" "" "" "" "PROP_impactConfigMode" "None"
"B" "" "" "" "PROP_impactPort" "Auto - default"
"B" "" "" "" "PROP_mapTimingMode" "Non Timing Driven"
"B" "" "" "" "PROP_mpprViewPadRptForSelRslt" ""
"B" "" "" "" "PROP_mpprViewParRptForSelRslt" ""
"B" "" "" "" "PROP_parGenAsyDlyRpt" "false"
"B" "" "" "" "PROP_parGenClkRegionRpt" "false"
"B" "" "" "" "PROP_parGenSimModel" "false"
"B" "" "" "" "PROP_parGenTimingRpt" "true"
"B" "" "" "" "PROP_parMpprNodelistFile" ""
"B" "" "" "" "PROP_parMpprParIterations" "5"
"B" "" "" "" "PROP_parMpprResultsDirectory" "mppr_result"
"B" "" "" "" "PROP_parMpprResultsToSave" "5"
"B" "" "" "" "PROP_parPowerReduction" "false"
"B" "" "" "" "PROP_parTimingMode" "Performance Evaluation"
"B" "" "" "" "PROP_vcom_otherCmdLineOptions" ""
"B" "" "" "" "PROP_vlog_otherCmdLineOptions" ""
"B" "" "" "" "PROP_vsim_otherCmdLineOptions" ""
"B" "" "" "" "PROP_xcpldFitDesInReg_xbr" "true"
"B" "" "" "" "PROP_xcpldFitDesPtermLmt_xbr" "28"
"B" "" "" "" "PROP_xilxBitgCfg_GenOpt_DbgBitStr" "false"
"B" "" "" "" "PROP_xilxBitgCfg_GenOpt_LogicAllocFile" "false"
"B" "" "" "" "PROP_xilxBitgCfg_GenOpt_MaskFile" "false"
"B" "" "" "" "PROP_xilxBitgReadBk_GenBitStr" "false"
"B" "" "" "" "PROP_xilxMapPackfactor" "100"
"B" "" "" "" "PROP_xilxPAReffortLevel" "Standard"
"B" "" "" "" "PROP_xstMoveFirstFfStage" "true"
"B" "" "" "" "PROP_xstMoveLastFfStage" "true"
"B" "" "" "" "PROP_xstROMStyle" "Auto"
"B" "" "" "" "PROP_xstSafeImplement" "No"
"B" "AutoGeneratedView" "VIEW_Map" "" "PROP_ParSmartGuideFileName" "x353_guide.ncd"
"B" "AutoGeneratedView" "VIEW_Translation" "" "PROP_MapSmartGuideFileName" "x353_guide.ncd"
"C" "" "" "" "PROP_CompxlibLang" "VHDL"
"C" "" "" "" "PROP_CompxlibSimPath" "Search in Path"
"C" "" "" "" "PROP_CompxlibSmartModels" "false"
"C" "" "" "" "PROP_CompxlibUpdateIniForSmartModel" "false"
"C" "" "" "" "PROP_DevDevice" "xc3s1200e"
"C" "" "" "" "PROP_DevFamilyPMName" "spartan3e"
"C" "" "" "" "PROP_ISimSimulationRunTime_behav_tb" "1000 ns"
"C" "" "" "" "PROP_ISimSimulationRunTime_behav_tbw" "1000 ns"
"C" "" "" "" "PROP_ISimSimulationRunTime_par_tb" "1000 ns"
"C" "" "" "" "PROP_ISimSimulationRunTime_par_tbw" "1000 ns"
"C" "" "" "" "PROP_ISimVCDFileName_par_tb" "xpower.vcd"
"C" "" "" "" "PROP_ISimVCDFileName_par_tbw" "xpower.vcd"
"C" "" "" "" "PROP_MapExtraEffort" "Normal"
"C" "" "" "" "PROP_MapPowerActivityFile" ""
"C" "" "" "" "PROP_SimModelGenMultiHierFile" "false"
"C" "" "" "" "PROP_XPowerOptBaseTimeUnit" ""
"C" "" "" "" "PROP_XPowerOptNumberOfUnits" "0"
"C" "" "" "" "PROP_bitgen_Encrypt_key0" ""
"C" "" "" "" "PROP_bitgen_Encrypt_key1" ""
"C" "" "" "" "PROP_bitgen_Encrypt_key2" ""
"C" "" "" "" "PROP_bitgen_Encrypt_key3" ""
"C" "" "" "" "PROP_bitgen_Encrypt_key4" ""
"C" "" "" "" "PROP_bitgen_Encrypt_key5" ""
"C" "" "" "" "PROP_bitgen_Encrypt_keyFile" ""
"C" "" "" "" "PROP_parPowerActivityFile" ""
"C" "" "" "" "PROP_xilxBitgCfg_GenOpt_ReadBack_virtex2" "false"
"C" "" "" "" "PROP_xilxPARextraEffortLevel" "Normal"
"D" "" "" "" "PROP_CompxlibUni9000Lib" "true"
"D" "" "" "" "PROP_CompxlibUniSimLib" "true"
"D" "" "" "" "PROP_DevPackage" "ft256"
"D" "" "" "" "PROP_Synthesis_Tool" "XST (VHDL/Verilog)"
"D" "" "" "" "PROP_xilxBitgCfg_GenOpt_LogicAllocFile_virtex2" "false"
"D" "" "" "" "PROP_xilxBitgCfg_GenOpt_MaskFile_virtex2" "false"
"D" "" "" "" "PROP_xilxBitgReadBk_GenBitStr_virtex2" "false"
"E" "" "" "" "PROP_DevSpeed" "-4"
"E" "" "" "" "PROP_PreferredLanguage" "Verilog"
"F" "" "" "" "PROP_ChangeDevSpeed" "-4"
"F" "" "" "" "PROP_HdlTemplateLang" "Verilog"
"F" "" "" "" "PROP_SimModelTarget" "Verilog"
"F" "" "" "" "PROP_coregenFuncModelTargetLang" "Verilog"
"F" "" "" "" "PROP_hdlInstTempTargetLang" "Verilog"
"F" "" "" "" "PROP_schFuncModelTargetLang" "Verilog"
"F" "" "" "" "PROP_schInstTempTargetLang" "Verilog"
"F" "" "" "" "PROP_sysgenInstTempTargetLang" "Verilog"
"F" "" "" "" "PROP_tbwTestbenchTargetLang" "Verilog"
"F" "" "" "" "PROP_xawHdlSourceTargetLang" "Verilog"
"F" "" "" "" "PROP_xilxPostTrceSpeed" "-4"
"F" "" "" "" "PROP_xilxPreTrceSpeed" "-4"
"F" "" "" "" "PROP_xmpInstTempTargetLang" "Verilog"
"G" "" "" "" "PROP_HdlTemplateName" ""
"G" "" "" "" "PROP_PostSynthSimModelName" ""
"G" "" "" "" "PROP_SimModelAutoInsertGlblModuleInNetlist" "true"
"G" "" "" "" "PROP_SimModelGenArchOnly" "false"
"G" "" "" "" "PROP_SimModelIncSdfAnnInVerilogFile" "true"
"G" "" "" "" "PROP_SimModelIncSimprimInVerilogFile" "false"
"G" "" "" "" "PROP_SimModelIncUnisimInVerilogFile" "false"
"G" "" "" "" "PROP_SimModelIncUselibDirInVerilogFile" "false"
"G" "" "" "" "PROP_SimModelNoEscapeSignal" "false"
"G" "" "" "" "PROP_SimModelOutputExtIdent" "false"
"G" "" "" "" "PROP_SimModelRenTopLevArchTo" "Structure"
"G" "" "" "" "PROP_SimModelRenTopLevMod" ""
"G" "" "" "" "PROP_bencherPostMapTestbenchName" "testbench.map_tfw"
"G" "" "" "" "PROP_bencherPostParTestbenchName" "testbench.timesim_tfw"
"G" "" "" "" "PROP_bencherPostXlateTestbenchName" "testbench.translate_tfw"
"G" "" "" "" "PROP_netgenPostMapSimModelName" "x353_map.v"
"G" "" "" "" "PROP_netgenPostParSimModelName" "x353_timesim.v"
"G" "" "" "" "PROP_netgenPostSynthesisSimModelName" "x353_synthesis.v"
"G" "" "" "" "PROP_netgenPostXlateSimModelName" "x353_translate.v"
"G" "AutoGeneratedView" "VIEW_Map" "" "PROP_PostMapSimModelName" "x353_map.v"
"G" "AutoGeneratedView" "VIEW_Par" "" "PROP_PostParSimModelName" "x353_timesim.v"
"G" "AutoGeneratedView" "VIEW_Post-MapAbstractSimulation" "" "PROP_tbwPostMapTestbenchName" "testbench.map_tfw"
"G" "AutoGeneratedView" "VIEW_Post-ParAbstractSimulation" "" "PROP_tbwPostParTestbenchName" "testbench.timesim_tfw"
"G" "AutoGeneratedView" "VIEW_Post-TranslateAbstractSimulation" "" "PROP_tbwPostXlateTestbenchName" "testbench.translate_tfw"
"G" "AutoGeneratedView" "VIEW_Structural" "" "PROP_PostSynthesisSimModelName" "x353_synthesis.v"
"G" "AutoGeneratedView" "VIEW_Translation" "" "PROP_PostXlateSimModelName" "x353_translate.v"
"H" "" "" "" "PROP_SimModelBringOutGsrNetAsAPort" "false"
"H" "" "" "" "PROP_SimModelBringOutGtsNetAsAPort" "false"
"H" "" "" "" "PROP_SimModelPathUsedInSdfAnn" "Default"
"H" "" "" "" "PROP_netgenRenameTopLevEntTo" ""
"H" "AutoGeneratedView" "VIEW_Map" "" "PROP_SimModelRenTopLevEntTo" ""
"H" "AutoGeneratedView" "VIEW_Par" "" "PROP_SimModelRenTopLevEntTo" ""
"H" "AutoGeneratedView" "VIEW_Structural" "" "PROP_SimModelRenTopLevEntTo" ""
"H" "AutoGeneratedView" "VIEW_Translation" "" "PROP_SimModelRenTopLevEntTo" ""
"I" "" "" "" "PROP_SimModelGsrPortName" "GSR_PORT"
"I" "" "" "" "PROP_SimModelGtsPortName" "GTS_PORT"
"I" "" "" "" "PROP_SimModelRocPulseWidth" "100"
"I" "" "" "" "PROP_SimModelTocPulseWidth" "0"}
HandleException {
RestoreProcessProperties $iProjHelper $process_props
} "A problem occured while restoring process properties."
# library names and their members
set libraries {
}
HandleException {
RestoreSourceLibraries $iProjHelper $libraries
} "A problem occured while restoring source libraries."
# partition names for recreation
set partition_names {
}
HandleException {
RestorePartitions $partition_names
} "A problem occured while restoring partitions."
set opts_stream [ [Xilinx::Cit::FactoryCreate $::xilinx::Dpm::StreamBufferCompID ] GetInterface $xilinx::Prjrep::IStreamID ]
$opts_stream WriteString "5"
$opts_stream WriteString "5"
$opts_stream WriteString "5"
$opts_stream WriteString "5"
$opts_stream WriteString "0"
$opts_stream WriteString "0"
$opts_stream WriteString "3"
$opts_stream WriteString "1"
$opts_stream WriteString "1"
$opts_stream WriteString "1"
$opts_stream WriteString "2"
$opts_stream WriteString "0"
$opts_stream WriteString "0"
$opts_stream WriteString "1"
RestoreSourceControlOptions "$project_file" $opts_stream
Release $opts_stream
if { $srcctrl_comp != 0 } {
set i_prjref [ $srcctrl_comp GetInterface $::xilinx::Dpm::IProjectHelperReferenceID ]
$i_prjref Set iProjHelper
} elseif {$iProjHelper != 0} {
$iProjHelper Close
}
Release $iProjHelper
# return back
cd $old_working_dir
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Release 10.1.03 - par K.39 (lin)
Copyright (c) 1995-2008 Xilinx, Inc. All rights reserved.
<<<<<<< x353_pad.txt
Tue Jan 10 02:27:06 2012
=======
Sun Apr 24 11:53:34 2011
>>>>>>> 1.17
INFO: The IO information is provided in three file formats as part of the Place and Route (PAR) process. These formats are:
1. The <design name>_pad.txt file (this file) designed to provide information on IO usage in a human readable ASCII text format viewable through common text editors.
2. The <design namd>_pad.csv file for use with spreadsheet programs such as MS Excel. This file can also be read by PACE to communicate post PAR IO information.
3. The <design name>.pad file designed for parsing by customers. It uses the "|" as a data field separator.
INPUT FILE: x353_map.ncd
OUTPUT FILE: /home/andrey/cvs_sync/elphel353-8.0.6.4/elphel353/fpga/x3x3/mppr_result.dir/H_H_3_pad.txt
PART TYPE: xc3s1200e
SPEED GRADE: -4
PACKAGE: ft256
Pinout by Pin Number:
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|Pin Number|Signal Name|Pin Usage|Pin Name |Direction |IO Standard |IO Bank Number|Drive (mA)|Slew Rate|Termination|IOB Delay|Voltage|Constraint|DCI Value|IO Register|Signal Integrity|
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|A1 | | |GND | | | | | | | | | | | | |
|A2 | | |TDI | | | | | | | | | | | | |
|A3 | |IBUF |IP |UNUSED | |0 | | | | | | | | | |
|A4 |EXT<2> |IOB |IO_L17N_0/VREF_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|A5 |EXT<3> |IOB |IO_L17P_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|A6 | | |VCCAUX | | | | | | | |2.5 | | | | |
|A7 |D<16> |IOB |IO |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|A8 |CLK3 |IBUF |IP_L10P_0/GCLK8 |INPUT |LVCMOS33 |0 | | | |NONE | |LOCATED | |NO |NONE |
|A9 |CLK0 |IBUF |IO_L09N_0/GCLK7 |INPUT |LVCMOS33 |0 | | | |NONE | |LOCATED | |NO |NONE |
|A10 |CLK1 |IBUF |IO_L09P_0/GCLK6 |INPUT |LVCMOS33 |0 | | | |NONE | |LOCATED | |NO |NONE |
|A11 | | |VCCAUX | | | | | | | |2.5 | | | | |
|A12 |D<15> |IOB |IO |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|A13 |D<11> |IOB |IO_L03N_0/VREF_0 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|A14 |DACK1 |IBUF |IO_L01N_0 |INPUT |LVCMOS33 |0 | | | |NONE | |LOCATED | |NO |NONE |
|A15 | | |TCK | | | | | | | | | | | | |
|A16 | | |GND | | | | | | | | | | | | |
|B1 |CNVSYNC |IOB |IO_L01P_3 |BIDIR |LVCMOS25* |3 |12 |SLOW |NONE** |IFD | |LOCATED | |YES |NONE |
|B2 |CNVCLK |IOB |IO_L01N_3 |BIDIR |LVCMOS25* |3 |12 |SLOW |NONE** |IFD | |LOCATED | |YES |NONE |
|B3 | |DIFFS |IO_L19N_0/HSWAP |UNUSED | |0 | | | | | | | | | |
|B4 |D<19> |IOB |IO |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|B5 | | |VCCO_0 | | |0 | | | | |3.30 | | | | |
|B6 |D<23> |IOB |IO |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|B7 |EXT<7> |IOB |IO_L13P_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|B8 | |DIFFSI |IP_L10N_0/GCLK9 |UNUSED | |0 | | | | | | | | | |
|B9 | | |GND | | | | | | | | | | | | |
|B10 |D<14> |IOB |IO |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|B11 |D<12> |IOB |IO_L05N_0/VREF_0 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|B12 | | |VCCO_0 | | |0 | | | | |3.30 | | | | |
|B13 |BROUT |IOB |IO_L03P_0 |OUTPUT |LVCMOS33 |0 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|B14 |DACK0 |IBUF |IO_L01P_0 |INPUT |LVCMOS33 |0 | | | |NONE | |LOCATED | |NO |NONE |
|B15 | | |TMS | | | | | | | | | | | | |
|B16 |BRIN |IBUF |IP |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |NO |NONE |
|C1 |ARO |IOB |IO_L02P_3 |OUTPUT |LVCMOS25* |3 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|C2 | |DIFFS |IO_L02N_3/VREF_3 |UNUSED/VREF| |3 | | | | |1.25 | | | | |
|C3 |D<21> |IOB |IO_L19P_0 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|C4 |EXT<0> |IOB |IO_L18N_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|C5 |EXT<1> |IOB |IO_L18P_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|C6 |EXT<5> |IOB |IO_L15P_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|C7 |EXT<6> |IOB |IO_L13N_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|C8 |D<30> |IOB |IO_L11P_0/GCLK10 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|C9 | |DIFFSI |IP_L07N_0 |UNUSED | |0 | | | | | | | | | |
|C10 | |DIFFMI |IP_L07P_0 |UNUSED | |0 | | | | | | | | | |
|C11 |D<10> |IOB |IO_L05P_0 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|C12 | |DIFFSI |IP_L02N_0 |UNUSED | |0 | | | | | | | | | |
|C13 | |IBUF |IP |UNUSED | |0 | | | | | | | | | |
|C14 | | |TDO | | | | | | | | | | | | |
|C15 |DREQ0 |IOB |IO_L19N_1/LDC2 |OUTPUT |LVCMOS33 |1 |4 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|C16 |SYS_BUSEN |IOB |IO_L19P_1/LDC1 |OUTPUT |LVCMOS33 |1 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|D1 |SENSPGM |IOB |IO_L05P_3 |BIDIR |LVCMOS25* |3 |12 |SLOW |PULLUP |NONE | |LOCATED | |NO |NONE |
|D2 | |IBUF |IP |UNUSED | |3 | | | | | | | | | |
|D3 | | |PROG_B | | | | | | | | | | | | |
|D4 | | |VCCINT | | | | | | | |1.2 | | | | |
|D5 | |DIFFMI |IP_L16P_0 |UNUSED | |0 | | | | | | | | | |
|D6 |EXT<4> |IOB |IO_L15N_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|D7 |EXT<9> |IOB |IO_L14N_0/VREF_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|D8 |D<31> |IOB |IO_L11N_0/GCLK11 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|D9 |D<13> |IOB |IO/VREF_0 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|D10 |DREQ1 |IOB |IO_L06P_0 |OUTPUT |LVCMOS33 |0 |4 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|D11 |BG |IOB |IO_L04P_0 |TRISTATE |LVCMOS33 |0 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|D12 | |DIFFMI |IP_L02P_0 |UNUSED | |0 | | | | | | | | | |
|D13 | | |VCCINT | | | | | | | |1.2 | | | | |
|D14 |A<0> |IBUF |IO_L18N_1/LDC0 |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |YES |NONE |
|D15 |IRQ |IOB |IO_L18P_1/HDC |OUTPUT |LVCMOS33 |1 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|D16 |CE |IBUF |IP/VREF_1 |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |NO |NONE |
|E1 |ARST |IOB |IO_L05N_3 |OUTPUT |LVCMOS25* |3 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|E2 | | |VCCO_3 | | |3 | | | | |2.50 | | | | |
|E3 |MRST |IOB |IO_L03P_3 |BIDIR |LVCMOS25* |3 |12 |SLOW |PULLUP |NONE | |LOCATED | |NO |NONE |
|E4 |SDA0 |IOB |IO_L03N_3 |BIDIR |LVCMOS25* |3 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|E5 | | |VCCINT | | | | | | | |1.2 | | | | |
|E6 | |DIFFSI |IP_L16N_0 |UNUSED | |0 | | | | | | | | | |
|E7 |EXT<8> |IOB |IO_L14P_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|E8 |EXT<11> |IOB |IO_L12P_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|E9 |D<18> |IOB |IO_L08P_0/GCLK4 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|E10 |D<25> |IOB |IO_L06N_0 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|E11 |A<3> |IBUF |IO_L04N_0 |INPUT |LVCMOS33 |0 | | | |NONE | |LOCATED | |YES |NONE |
|E12 | | |VCCINT | | | | | | | |1.2 | | | | |
|E13 |A<4> |IBUF |IO_L17P_1 |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |YES |NONE |
|E14 |CE1 |IBUF |IP |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |NO |NONE |
|E15 | | |VCCO_1 | | |1 | | | | |3.30 | | | | |
|E16 |A<5> |IBUF |IO_L17N_1 |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |YES |NONE |
|F1 | | |VCCAUX | | | | | | | |2.5 | | | | |
|F2 | |IBUF |IP |UNUSED | |3 | | | | | | | | | |
|F3 | |DIFFM |IO_L04P_3 |UNUSED | |3 | | | | | | | | | |
|F4 | |DIFFS |IO_L04N_3/VREF_3 |UNUSED/VREF| |3 | | | | |1.25 | | | | |
|F5 | |IBUF |IP |UNUSED | |3 | | | | | | | | | |
|F6 | | |GND | | | | | | | | | | | | |
|F7 | | |VCCO_0 | | |0 | | | | |3.30 | | | | |
|F8 |EXT<10> |IOB |IO_L12N_0 |BIDIR |LVCMOS33 |0 |12 |SLOW |NONE** |NONE | |LOCATED | |NO |NONE |
|F9 |D<20> |IOB |IO_L08N_0/GCLK5 |BIDIR |LVCMOS33 |0 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|F10 | | |VCCO_0 | | |0 | | | | |3.30 | | | | |
|F11 | | |GND | | | | | | | | | | | | |
|F12 |A<2> |IBUF |IO_L16N_1 |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |YES |NONE |
|F13 |A<1> |IBUF |IO_L16P_1 |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |YES |NONE |
|F14 |A<6> |IBUF |IO_L15P_1 |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |YES |NONE |
|F15 |A<7> |IBUF |IO_L15N_1 |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |YES |NONE |
|F16 | | |VCCAUX | | | | | | | |2.5 | | | | |
|G1 | |IBUF |IP/VREF_3 |UNUSED/VREF| |3 | | | | |1.25 | | | | |
|G2 |SCL0 |IOB |IO_L07N_3 |BIDIR |LVCMOS25* |3 |12 |SLOW |PULLUP |NONE | |LOCATED | |NO |NONE |
|G3 |PXD<8> |IBUF |IO_L07P_3 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|G4 |PXD<7> |IBUF |IO_L06N_3 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|G5 |PXD<5> |IBUF |IO_L06P_3 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|G6 | | |VCCO_3 | | |3 | | | | |2.50 | | | | |
|G7 | | |GND | | | | | | | | | | | | |
|G8 | | |GND | | | | | | | | | | | | |
|G9 | | |GND | | | | | | | | | | | | |
|G10 | | |GND | | | | | | | | | | | | |
|G11 | | |VCCO_1 | | |1 | | | | |3.30 | | | | |
|G12 | |IBUF |IP |UNUSED | |1 | | | | | | | | | |
|G13 | |DIFFM |IO_L14P_1 |UNUSED | |1 | | | | | | | | | |
|G14 | |DIFFS |IO_L14N_1/A0 |UNUSED | |1 | | | | | | | | | |
|G15 | |DIFFM |IO_L13P_1/A2 |UNUSED | |1 | | | | | | | | | |
|G16 | |DIFFS |IO_L13N_1/A1 |UNUSED | |1 | | | | | | | | | |
|H1 | |IBUF |IP |UNUSED | |3 | | | | | | | | | |
|H2 | | |GND | | | | | | | | | | | | |
|H3 |PXD<9> |IBUF |IO_L09P_3/LHCLK2 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|H4 |PXD<6> |IBUF |IO_L09N_3/LHCLK3/IRDY2 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|H5 |PXD<3> |IBUF |IO_L08P_3/LHCLK0 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|H6 |PXD<1> |IBUF |IO_L08N_3/LHCLK1 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|H7 | | |GND | | | | | | | | | | | | |
|H8 | | |GND | | | | | | | | | | | | |
|H9 | | |GND | | | | | | | | | | | | |
|H10 | | |GND | | | | | | | | | | | | |
|H11 |D<22> |IOB |IO_L12N_1/A3/RHCLK7 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|H12 | |DIFFM |IO_L12P_1/A4/RHCLK6 |UNUSED | |1 | | | | | | | | | |
|H13 | |IBUF |IP/VREF_1 |UNUSED | |1 | | | | | | | | | |
|H14 |BA<0> |IOB |IO_L11N_1/A5/RHCLK5 |TRISTATE |LVCMOS33 |1 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|H15 |BA<1> |IOB |IO_L11P_1/A6/RHCLK4/IRDY1|TRISTATE |LVCMOS33 |1 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|H16 | |IBUF |IP |UNUSED | |1 | | | | | | | | | |
|J1 |PXD<4> |IBUF |IO_L12P_3 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|J2 |PXD<2> |IBUF |IO_L10P_3/LHCLK4/TRDY2 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|J3 |PXD<0> |IBUF |IO_L10N_3/LHCLK5 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|J4 |DUMMYVFEF |IOB |IO_L11N_3/LHCLK7 |BIDIR |SSTL2_I |3 | |NONE* |NONE** |NONE | |LOCATED | |NO |NONE |
|J5 |HACT |IBUF |IO_L11P_3/LHCLK6 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|J6 |ALWAYS0 |IBUF |IP |INPUT |LVCMOS25* |3 | | |PULLDOWN |NONE | |LOCATED | |NO |NONE |
|J7 | | |GND | | | | | | | | | | | | |
|J8 | | |GND | | | | | | | | | | | | |
|J9 | | |GND | | | | | | | | | | | | |
|J10 | | |GND | | | | | | | | | | | | |
|J11 | |IBUF |IP |UNUSED | |1 | | | | | | | | | |
|J12 |SYS_SDCLKI |IBUF |IP |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |NO |NONE |
|J13 |SYS_SDWE |IOB |IO_L10N_1/A7/RHCLK3/TRDY1|TRISTATE |LVCMOS33 |1 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|J14 |SYS_SDCLK |IOB |IO_L10P_1/A8/RHCLK2 |TRISTATE |LVCMOS33 |1 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|J15 | | |GND | | | | | | | | | | | | |
|J16 |SYS_SDCAS |IOB |IO_L09N_1/A9/RHCLK1 |TRISTATE |LVCMOS33 |1 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|K1 |VACT |IBUF |IO_L12N_3 |INPUT |LVCMOS25* |3 | | | |IFD | |LOCATED | |YES |NONE |
|K2 |SDA<3> |IOB |IO_L13P_3 |OUTPUT |SSTL2_I |3 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|K3 |SDA<1> |IOB |IO_L13N_3 |OUTPUT |SSTL2_I |3 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|K4 | |IBUF |IP |UNUSED | |3 | | | | | | | | | |
|K5 |BPF |IBUF |IO_L15P_3 |INPUT |LVCMOS25* |3 | | | |NONE | |LOCATED | |NO |NONE |
|K6 | | |VCCO_3 | | |3 | | | | |2.50 | | | | |
|K7 | | |GND | | | | | | | | | | | | |
|K8 | | |GND | | | | | | | | | | | | |
|K9 | | |GND | | | | | | | | | | | | |
|K10 | | |GND | | | | | | | | | | | | |
|K11 | | |VCCO_1 | | |1 | | | | |3.30 | | | | |
|K12 |D<17> |IOB |IO_L07N_1/A11 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|K13 |D<29> |IOB |IO_L07P_1/A12 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|K14 |D<24> |IOB |IO_L08N_1/VREF_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|K15 |D<26> |IOB |IO_L08P_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|K16 |SYS_SDRAS |IOB |IO_L09P_1/A10/RHCLK0 |TRISTATE |LVCMOS33 |1 |12 |SLOW |NONE** | | |LOCATED | |NO |NONE |
|L1 | | |VCCAUX | | | | | | | |2.5 | | | | |
|L2 | |DIFFS |IO_L14N_3/VREF_3 |UNUSED/VREF| |3 | | | | |1.25 | | | | |
|L3 |DCLK |IOB |IO_L14P_3 |BIDIR |LVCMOS25* |3 |2 |SLOW |NONE** |IFD | |LOCATED | |YES |NONE |
|L4 |SDA<14> |IOB |IO_L17N_3 |OUTPUT |SSTL2_I |3 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|L5 | |DIFFS |IO_L15N_3 |UNUSED | |3 | | | | | | | | | |
|L6 | | |GND | | | | | | | | | | | | |
|L7 | | |VCCO_2 | | |2 | | | | |2.50 | | | | |
|L8 |SDD<7> |IOB |IO_L09N_2/D6/GCLK13 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|L9 | |DIFFM |IO_L13P_2/M0 |UNUSED | |2 | | | | | | | | | |
|L10 | | |VCCO_2 | | |2 | | | | |2.50 | | | | |
|L11 | | |GND | | | | | | | | | | | | |
|L12 |D<9> |IOB |IO_L05P_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|L13 |D<3> |IOB |IO_L05N_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|L14 |D<27> |IOB |IO_L06P_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|L15 |D<28> |IOB |IO_L06N_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|L16 | | |VCCAUX | | | | | | | |2.5 | | | | |
|M1 |SDA<2> |IOB |IO_L16P_3 |OUTPUT |SSTL2_I |3 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|M2 | | |VCCO_3 | | |3 | | | | |2.50 | | | | |
|M3 | |IBUF |IP |UNUSED | |3 | | | | | | | | | |
|M4 |SDA<5> |IOB |IO_L17P_3 |OUTPUT |SSTL2_I |3 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|M5 | | |VCCINT | | | | | | | |1.2 | | | | |
|M6 |SDRAS |IOB |IO_L05P_2 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|M7 |SDWE |IOB |IO |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|M8 |SDLDM |IOB |IO_L09P_2/D7/GCLK12 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|M9 |SDD<6> |IOB |IO_L13N_2/DIN/D0 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|M10 |SDD<10> |IOB |IO_L15N_2 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|M11 | |DIFFSI |IP_L17N_2 |UNUSED | |2 | | | | | | | | | |
|M12 | | |VCCINT | | | | | | | |1.2 | | | | |
|M13 |WE |IBUF |IP |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |YES |NONE |
|M14 |OE |IBUF |IP |INPUT |LVCMOS33 |1 | | | |NONE | |LOCATED | |NO |NONE |
|M15 | | |VCCO_1 | | |1 | | | | |3.30 | | | | |
|M16 |D<0> |IOB |IO_L04N_1/VREF_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|N1 |SDA<10> |IOB |IO_L16N_3 |OUTPUT |SSTL2_I |3 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|N2 | |IBUF |IP/VREF_3 |UNUSED/VREF| |3 | | | | |1.25 | | | | |
|N3 | |IBUF |IP |UNUSED | |3 | | | | | | | | | |
|N4 | | |VCCINT | | | | | | | |1.2 | | | | |
|N5 |SDA<8> |IOB |IO_L03N_2/MOSI/CSI_B |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|N6 |SDCLKE |IOB |IO_L05N_2 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |NO |NONE |
|N7 |SDCAS |IOB |IO_L07P_2 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|N8 |LDQS |IOB |IO_L10P_2/D4/GCLK14 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|N9 |SDD<5> |IOB |IO_L12N_2/D1/GCLK3 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|N10 |SDD<3> |IOB |IO_L15P_2 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|N11 | |DIFFMI |IP_L17P_2 |UNUSED | |2 | | | | | | | | | |
|N12 |SDD<2> |IOB |IO_L18N_2/A20 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|N13 | | |VCCINT | | | | | | | |1.2 | | | | |
|N14 |D<5> |IOB |IO_L03P_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|N15 |D<1> |IOB |IO_L03N_1/VREF_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|N16 |D<2> |IOB |IO_L04P_1 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|P1 |SDA<0> |IOB |IO_L18N_3 |OUTPUT |SSTL2_I |3 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|P2 |SDA<13> |IOB |IO_L18P_3 |OUTPUT |SSTL2_I |3 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|P3 | |DIFFM |IO_L01P_2/CSO_B |UNUSED | |2 | | | | | | | | | |
|P4 | |DIFFS |IO_L01N_2/INIT_B |UNUSED | |2 | | | | | | | | | |
|P5 |SDA<7> |IOB |IO_L03P_2/DOUT/BUSY |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|P6 |SDA<11> |IOB |IO_L06N_2 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|P7 |SDA<12> |IOB |IO_L07N_2 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|P8 |UDQS |IOB |IO_L10N_2/D3/GCLK15 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|P9 |SDD<8> |IOB |IO_L12P_2/D2/GCLK2 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|P10 |SDD<9> |IOB |IO_L14P_2 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|P11 |SDD<11> |IOB |IO_L16N_2/A22 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|P12 |SDD<12> |IOB |IO_L18P_2/A21 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|P13 | |IOB |IO/VREF_2 |UNUSED/VREF| |2 | | | | |1.25 | | | | |
|P14 |SDD<15> |IOB |IO_L20P_2/VS0/A17 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|P15 |D<7> |IOB |IO_L02N_1/A13 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|P16 |D<4> |IOB |IO_L02P_1/A14 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|R1 |SDNCLK |DIFFS |IO_L19N_3 |OUTPUT |DIFF_SSTL2_I|3 | | |NONE** | | |LOCATED | |NO |NONE |
|R2 |SDCLK |DIFFM |IO_L19P_3 |OUTPUT |DIFF_SSTL2_I|3 | | |NONE** | | |LOCATED | |NO |NONE |
|R3 |SDCLK_FB |DIFFSI |IP_L02N_2 |INPUT |DIFF_SSTL2_I|2 | | | |NONE | |LOCATED | |NO |NONE |
|R4 | |IOB |IO/VREF_2 |UNUSED/VREF| |2 | | | | |1.25 | | | | |
|R5 | | |VCCO_2 | | |2 | | | | |2.50 | | | | |
|R6 |SDA<9> |IOB |IO_L06P_2 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|R7 | |DIFFMI |IP_L08P_2 |UNUSED | |2 | | | | | | | | | |
|R8 | | |GND | | | | | | | | | | | | |
|R9 | |DIFFSI |IP_L11N_2/M2/GCLK1 |UNUSED | |2 | | | | | | | | | |
|R10 | |DIFFS |IO_L14N_2/VREF_2 |UNUSED/VREF| |2 | | | | |1.25 | | | | |
|R11 |SDD<4> |IOB |IO_L16P_2/A23 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|R12 | | |VCCO_2 | | |2 | | | | |2.50 | | | | |
|R13 |SDD<13> |IOB |IO_L19N_2/VS1/A18 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|R14 |SDD<0> |IOB |IO_L20N_2/CCLK |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|R15 |D<8> |IOB |IO_L01N_1/A15 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|R16 |D<6> |IOB |IO_L01P_1/A16 |BIDIR |LVCMOS33 |1 |8 |SLOW |NONE** |NONE | |LOCATED | |YES |NONE |
|T1 | | |GND | | | | | | | | | | | | |
|T2 | |IBUF |IP |UNUSED | |2 | | | | | | | | | |
|T3 |SDNCLK_FB |DIFFMI |IP_L02P_2 |INPUT |DIFF_SSTL2_I|2 | | | |NONE | |LOCATED | |NO |NONE |
|T4 |SDA<4> |IOB |IO_L04P_2 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|T5 |SDA<6> |IOB |IO_L04N_2 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|T6 | | |VCCAUX | | | | | | | |2.5 | | | | |
|T7 | |DIFFSI |IP_L08N_2/VREF_2 |UNUSED/VREF| |2 | | | | |1.25 | | | | |
|T8 |SDUDM |IOB |IO/D5 |OUTPUT |SSTL2_I |2 | |NONE* |NONE** | | |LOCATED | |YES |NONE |
|T9 | |DIFFMI |IP_L11P_2/RDWR_B/GCLK0 |UNUSED | |2 | | | | | | | | | |
|T10 | |IOB |IO/M1 |UNUSED | |2 | | | | | | | | | |
|T11 | | |VCCAUX | | | | | | | |2.5 | | | | |
|T12 |SDD<1> |IOB |IO |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|T13 |SDD<14> |IOB |IO_L19P_2/VS2/A19 |BIDIR |SSTL2_I |2 | |NONE* |NONE** |NONE | |LOCATED | |YES |NONE |
|T14 | |IBUF |IP |UNUSED | |2 | | | | | | | | | |
|T15 | | |DONE | | | | | | | | | | | | |
|T16 | | |GND | | | | | | | | | | | | |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
* Default value.
** This default Pullup/Pulldown value can be overridden in Bitgen.
****** Special VCCO requirements may apply. Please consult the device
family datasheet for specific guideline on VCCO requirements.
#!/bin/sh
UNISIMS="../unisims"
rm -vf x353.lxt
echo "Using UNISIM library $UNISIMS"
time iverilog -Dlegacy_model -gno-specify -v -o x353mjpeg_test -sglbl -stestbench353 \
-y$UNISIMS \
x353_1.tf \
x353.v \
macros353.v \
sdram_phase.v \
ioports353.v \
sensorpads353.v \
clkios353.v \
sensor_phase353.v \
mcontr353.v \
descrproc353.v \
sdseq353.v \
sensdcclk333.v \
sensortrig.v \
sensorpix353.v \
lens_flat.v \
histogram353.v \
compressor333.v \
dma_fifo353.v \
color_proc353.v \
csconvert18.v \
csconvert_mono.v \
xdct353.v \
quantizator353.v \
encoderDCAC353.v \
huffman333.v \
stuffer333.v \
rtc353.v \
interrupts_vector333.v \
twelve_ios.v \
extjtag.v \
ddr.v \
sensor12bits.v \
camsync.v \
focus_sharp.v \
i2c_writeonly.v \
irq_smart.v \
cmd_sequencer.v \
control_regs.v \
10364.v \
imu_logger.v \
glbl.v \
|| { echo "iverilog failed"; exit 1; }
time vvp -v x353mjpeg_test -lxt2 || { echo "vvp failed"; exit 1; }
gtkwave x353.lxt x353_1.sav &
exit 0
/**********************************************************************
** -----------------------------------------------------------------------------**
** xdct333.v
**
** 8x8 discrete Cosine Transform
**
** Copyright (C) 2002-2008 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X333
** X333 is free software - hardware description language (HDL) code.
**
** 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, either version 3 of the License, or
** (at your option) any later version.
**
** 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/>.
** -----------------------------------------------------------------------------**
**
** Modified by Andrey Filippov - goal to make it work in start/stop mode, using
** "start" input (going together with the first data, no restriction on the gap between 64-pixel blocks (>=0)
** Removed "RST" input ("en" is only used to reset ping-pong transpose memory address)
** Split module in 2 stages
** Lost architecture-independence, but it is OK for me
** Also saved some area - original design compiled by XST to 865 slices (XC2S300e), this one - 780!
**
** It is based on the original design (Xilix app. note XAPP610) by:
** Author: Latha Pillai
** Senior Applications Engineer
**
** Video Applications
** Advanced Products Group
** Xilinx, Inc.
**
** Copyright (c) 2001 Xilinx, Inc.
** All rights reserved
**
** Date: Feb. 10, 2002
**
** RESTRICTED RIGHTS LEGEND
**
** This software has not been published by the author, and
** has been disclosed to others for the purpose of enhancing
** and promoting design productivity in Xilinx products.
**
** Therefore use, duplication or disclosure, now and in the
** future should give consideration to the productivity
** enhancements afforded the user of this code by the author's
** efforts. Thank you for using our products !
**
** Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
** WHATSOEVER AND XILINX SPECIFICALLY DISCLAIMS ANY
** IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
** A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
***********************************************************************/
/*
after I added DC subtraction before DCT I got 9-bit (allthough not likely to go out of 8bit range) signed data.
also increased transpose memory to 9 bits (anyway it is 16-bit wide) - see if it will help to prevent saturation
without significant increase in gates
Saturatuion is still visible on real pictures, but there was a bug - addsub<i>a_comp, addsub<i>b_comp where not using their
MSB. I added 1 more bit to add_sub<i>a and add_sub<i>b and fixed that bug. Only 2 mofre slices were used
Device utilization summary:
Number of External GCLKIOBs 1 out of 4 25%
Number of External IOBs 23 out of 178 12%
Number of LOCed External IOBs 0 out of 23 0%
Number of BLOCKRAMs 1 out of 16 6%
Number of SLICEs 855 out of 3072 27%
Number of GCLKs 1 out of 4 25%
*/
// still not enough - maybe one tiny bit more??
/*
Device utilization summary:
Number of External GCLKIOBs 1 out of 4 25%
Number of External IOBs 26 out of 178 14%
Number of LOCed External IOBs 0 out of 26 0%
Number of BLOCKRAMs 1 out of 16 6%
Number of SLICEs 837 out of 3072 27%
Number of GCLKs 1 out of 4 25%
*/
`timescale 1ns/1ps
// For xdct353 - increasing data in 9 bits -> 10 bits, out 12 bits ->13 bits
module xdct ( clk, // top level module
en, // if zero will reset transpose memory page njumbers
start, // single-cycle start pulse that goes with the first pixel data. Other 63 should follow
xin, // [7:0] - input data
last_in, // output high during input of the last of 64 pixels in a 8x8 block
pre_first_out,// 1 cycle ahead of the first output in a 64 block
dv, // data output valid. Will go high on the 94-th cycle after the start
d_out);// [8:0]output data
input clk;
input en,start;
input [9:0] xin;
output last_in;
output pre_first_out;
output dv;
output [12:0] d_out;
wire clk, en,start,dv,stage1_done, tm_page,tm_we;
wire [9:0] xin;
wire [12:0] d_out;
wire [6:0] tm_ra;
wire [6:0] tm_wa;
wire [15:0] tm_out;
wire [15:0] tm_di;
reg last_in;
wire pre_first_out;
always @ (posedge clk) last_in <= (tm_wa[5:0]== 6'h30);
dct_stage1 i_dct_stage1( .clk(clk),
.en(en),
.start(start),
.xin(xin), // [7:0]
.we(tm_we), // write to transpose memory
.wr_cntr(tm_wa), // [6:0] transpose memory write address
.z_out(tm_di[15:0]),
.page(tm_page),
.done(stage1_done));
dct_stage2 i_dct_stage2( .clk(clk),
.en(en),
.start(stage1_done), // stage 1 finished, data available in transpose memory
.page(tm_page), // transpose memory page finished, valid at start
.rd_cntr(tm_ra[6:0]), // [6:0] transpose memory read address
.tdin(tm_out[15:0]), // [7:0] - data from transpose memory
.endv(pre_first_out),
.dv(dv), // data output valid
.dct2_out(d_out[12:0]));// [10:0]output data
RAMB16_S18_S18 i_transpose_mem (
.DOA(), // Port A 16-bit Data Output
.DOPA(), // Port A 2-bit Parity Output
.ADDRA({3'b0,tm_wa[6:0]}), // Port A 10-bit Address Input
.CLKA(clk), // Port A Clock
// .DIA({6'b0,tm_di[9:0]}), // Port A 16-bit Data Input
.DIA(tm_di[15:0]), // Port A 16-bit Data Input
.DIPA(2'b0), // Port A 2-bit parity Input
.ENA(1'b1), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(tm_we), // Port A Write Enable Input
.DOB(tm_out[15:0]), // Port B 16-bit Data Output
.DOPB(), // Port B 2-bit Parity Output
.ADDRB({3'b0,tm_ra[6:0]}), // Port B 10-bit Address Input
.CLKB(clk), // Port B Clock
.DIB(16'b0), // Port B 16-bit Data Input
.DIPB(2'b0), // Port-B 2-bit parity Input
.ENB(1'b1), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
endmodule
// 01/24/2004: Moved all clocks in stage 1 to "negedge" to reduce current pulses
module dct_stage1 ( clk,
en,
start, // single-cycle start pulse to replace RST
xin, // [7:0]
we, // write to transpose memory
wr_cntr, // [6:0] transpose memory write address
z_out, //data to transpose memory
page, // transpose memory page just filled (valid @ done)
done); // last cycle writing to transpose memory - may use after it (move it earlier?)
input clk;
input en,start;
input [9:0] xin;
output we;
output [6:0] wr_cntr;
output [15:0] z_out;
output page;
output done;
/* constants */
parameter C3= 16'd54491;
parameter S3= 16'd36410;
parameter C4= 16'd46341;
parameter C6= 16'd25080;
parameter S6= 16'd60547;
parameter C7= 16'd12785;
parameter S7= 16'd64277;
reg[16:0] memory1a, memory2a, memory3a, memory4a;
/* 1D section */
/* The max value of a pixel after processing (to make their expected mean to zero)
is 127. If all the values in a row are 127, the max value of the product terms
would be (127*2)*(23170/256) and that of z_out_int would be (127*8)*23170/256.
This value divided by 2raised to 8 is equivalent to ignoring the 8 lsb bits of the value */
reg[9:0] xa0_in, xa1_in, xa2_in, xa3_in, xa4_in, xa5_in, xa6_in, xa7_in;
reg[9:0] xa0_reg, xa1_reg, xa2_reg, xa3_reg, xa4_reg, xa5_reg, xa6_reg, xa7_reg;
reg[9:0] addsub1a_comp,addsub2a_comp,addsub3a_comp,addsub4a_comp;
reg[10:0] add_sub1a,add_sub2a,add_sub3a,add_sub4a;
reg save_sign1a, save_sign2a, save_sign3a, save_sign4a;
reg[17:0] p1a,p2a,p3a,p4a;
wire[35:0] p1a_all,p2a_all,p3a_all,p4a_all;
reg toggleA;
reg[18:0] z_out_int1,z_out_int2;
reg[18:0] z_out_int;
wire[15:0] z_out_prelatch;
reg [2:0] indexi;
/* clks and counters */
reg [6:0] wr_cntr_prelatch;
/* memory section */
reg done_prelatch;
reg we_prelatch;
wire enwe;
wire pre_sxregs;
reg sxregs;
reg page_prelatch;
// outputs from output latches to cross clock edge boundary
//wire[9:0] z_out;
//wire[6:0] wr_cntr;
//wire done;
//wire we;
//wire page;
// outputs from output latches to cross clock edge boundary
reg [15:0] z_out;
reg [ 6:0] wr_cntr;
reg done;
reg we;
reg page;
// to conserve energy by disabling toggleA
wire sxregs_d8;
reg enable_toggle;
SRL16_1 i_sxregs_d8 (.Q(sxregs_d8), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(clk),.D(sxregs)); // dly=7+1
always @ (negedge clk) enable_toggle <= en && (sxregs || (enable_toggle && !sxregs_d8));
always @ (negedge clk) done_prelatch<= (wr_cntr_prelatch[5:0]==6'h3f);
always @ (negedge clk) if (wr_cntr_prelatch[5:0]==6'h3f) page_prelatch <= wr_cntr_prelatch[6];
always @ (negedge clk) we_prelatch<= enwe || (en && we_prelatch && (wr_cntr_prelatch[5:0]!=6'h3f));
always @ (negedge clk )
if (!en) wr_cntr_prelatch <= 7'b0;
else if (we_prelatch) wr_cntr_prelatch <= wr_cntr_prelatch + 1;
SRL16_1 i_pre_sxregs (.Q(pre_sxregs), .A0(1'b0), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(clk), .D(start)); // dly=6+1
SRL16_1 i_enwe (.Q(enwe), .A0(1'b1), .A1(1'b0), .A2(1'b1), .A3(1'b0), .CLK(clk), .D(pre_sxregs)); // dly=5+1
always @ (negedge clk ) sxregs <= pre_sxregs || ((wr_cntr_prelatch[2:0]==3'h1) && (wr_cntr_prelatch[5:3]!=3'h7));
always @ (negedge clk) toggleA <= sxregs || (enable_toggle && (~toggleA));
always @ (negedge clk)
if (sxregs) indexi <= 3'h7;
else if (enable_toggle) indexi<=indexi+1;
/* 1D-DCT BEGIN */
// store 1D-DCT constant coeeficient values for multipliers */
always @ (negedge clk)
begin
case (indexi)
0 : begin memory1a <= {1'b0,C4}; //8'd91
memory2a <= {1'b0,C4}; //8'd91
memory3a <= {1'b0,C4}; //8'd91
memory4a <= {1'b0,C4}; //8'd91
end
1 : begin memory1a <= {1'b0,S7}; //8'd126;
memory2a <= {1'b0,C3}; //8'd106;
memory3a <= {1'b0,S3}; //8'd71;
memory4a <= {1'b0,C7}; //8'd25;
end
2 : begin memory1a <= {1'b0,S6}; //8'd118;
memory2a <= {1'b0,C6}; //8'd49;
memory3a <= {1'b1,C6}; //-8'd49;
memory4a <= {1'b1,S6}; //-8'd118
end
3 : begin memory1a <= {1'b0,C3}; // 8'd106;
memory2a <= {1'b1,C7}; //-8'd25;
memory3a <= {1'b1,S7}; //-8'd126;
memory4a <= {1'b1,S3}; //-8'd71;
end
4 : begin memory1a <= {1'b0,C4}; // 8'd91;
memory2a <= {1'b1,C4}; //-8'd91;
memory3a <= {1'b1,C4}; //-8'd91;
memory4a <= {1'b0,C4}; // 8'd91;
end
5 : begin memory1a <= {1'b0,S3}; // 8'd71;
memory2a <= {1'b1,S7}; //-8'd126;
memory3a <= {1'b0,C7}; // 8'd25;
memory4a <= {1'b0,C3}; // 8'd106;
end
6 : begin memory1a <= {1'b0,C6}; // 8'd49;
memory2a <= {1'b1,S6}; //-8'd118;
memory3a <= {1'b0,S6}; // 8'd118;
memory4a <= {1'b1,C6}; //-8'd49;
end
7 : begin memory1a <= {1'b0,C7}; // 8'd25;
memory2a <= {1'b1,S3}; //-8'd71;
memory3a <= {1'b0,C3}; // 8'd106;
memory4a <= {1'b1,S7}; //-8'd126;
end
endcase
end
/* 8-bit input shifted 8 times thru a shift register*/
// xa0_in will see output registers from posedge, may be replaced by latches if needed - but currently delay is under 5ns
always @ (negedge clk)
begin
xa0_in <= xin; xa1_in <= xa0_in; xa2_in <= xa1_in; xa3_in <= xa2_in;
xa4_in <= xa3_in; xa5_in <= xa4_in; xa6_in <= xa5_in; xa7_in <= xa6_in;
end
/* shifted inputs registered every 8th clk (using cntr8)*/
always @ (negedge clk)
if (sxregs)
begin
xa0_reg <= {xa0_in}; xa1_reg <= {xa1_in};
xa2_reg <= {xa2_in}; xa3_reg <= {xa3_in};
xa4_reg <= {xa4_in}; xa5_reg <= {xa5_in};
xa6_reg <= {xa6_in}; xa7_reg <= {xa7_in};
end
/* adder / subtractor block */
always @ (negedge clk)
if (toggleA == 1'b1) begin
add_sub1a <= ({xa7_reg[9],xa7_reg[9:0]} + {xa0_reg[9],xa0_reg[9:0]});
add_sub2a <= ({xa6_reg[9],xa6_reg[9:0]} + {xa1_reg[9],xa1_reg[9:0]});
add_sub3a <= ({xa5_reg[9],xa5_reg[9:0]} + {xa2_reg[9],xa2_reg[9:0]});
add_sub4a <= ({xa4_reg[9],xa4_reg[9:0]} + {xa3_reg[9],xa3_reg[9:0]});
end else begin
add_sub1a <= ({xa7_reg[9],xa7_reg[9:0]} - {xa0_reg[9],xa0_reg[9:0]});
add_sub2a <= ({xa6_reg[9],xa6_reg[9:0]} - {xa1_reg[9],xa1_reg[9:0]});
add_sub3a <= ({xa5_reg[9],xa5_reg[9:0]} - {xa2_reg[9],xa2_reg[9:0]});
add_sub4a <= ({xa4_reg[9],xa4_reg[9:0]} - {xa3_reg[9],xa3_reg[9:0]});
end
// First valid add_sub appears at the 10th clk (8 clks for shifting inputs,
// 9th clk for registering shifted input and 10th clk for add_sub
// to synchronize the i value to the add_sub value, i value is incremented
// only after 10 clks
always @ (negedge clk) begin
save_sign1a <= add_sub1a[10];
save_sign2a <= add_sub2a[10];
save_sign3a <= add_sub3a[10];
save_sign4a <= add_sub4a[10];
addsub1a_comp <= add_sub1a[10]? (-add_sub1a) : add_sub1a;
addsub2a_comp <= add_sub2a[10]? (-add_sub2a) : add_sub2a;
addsub3a_comp <= add_sub3a[10]? (-add_sub3a) : add_sub3a;
addsub4a_comp <= add_sub4a[10]? (-add_sub4a) : add_sub4a;
end
assign p1a_all = addsub1a_comp * memory1a[15:0];
assign p2a_all = addsub2a_comp * memory2a[15:0];
assign p3a_all = addsub3a_comp * memory3a[15:0];
assign p4a_all = addsub4a_comp * memory4a[15:0];
always @ (negedge clk)
begin
p1a <= (save_sign1a ^ memory1a[16]) ? (-p1a_all[26:9]) :(p1a_all[26:9]);
p2a <= (save_sign2a ^ memory2a[16]) ? (-p2a_all[26:9]) :(p2a_all[26:9]);
p3a <= (save_sign3a ^ memory3a[16]) ? (-p3a_all[26:9]) :(p3a_all[26:9]);
p4a <= (save_sign4a ^ memory4a[16]) ? (-p4a_all[26:9]) :(p4a_all[26:9]);
end
//
/* Final adder. Adding the ouputs of the 4 multipliers */
always @ (negedge clk)
begin
z_out_int1 <= ({p1a[17],p1a} + {p2a[17],p2a});
z_out_int2 <= ({p3a[17],p3a} + {p4a[17],p4a});
z_out_int <= (z_out_int1 + z_out_int2);
end
// rounding of the value
//assign z_out_rnd[15:0] = z_out_int[17:2];
//assign z_out_prelatch[15:0] = z_out_int[17:2]+ z_out_int[1]; // correct rounding
assign z_out_prelatch[15:0] = z_out_int[18:3]+ z_out_int[2]; // correct rounding
//wire TEST_zout= z_out_int[17] ^z_out_int[16];
// outputs from output latches to cross clock edge boundary
always @ (posedge clk)
begin
z_out[15:0] <= z_out_prelatch[15:0];
wr_cntr[6:0] <= wr_cntr_prelatch[6:0];
done <= done_prelatch;
we <= we_prelatch;
page <= page_prelatch;
end
/* 1D-DCT END */
endmodule
module dct_stage2 ( clk,
en,
start, // stage 1 finished, data available in transpose memory
page, // transpose memory page finished, valid at start
rd_cntr, // [6:0] transpose memory read address
tdin, // [15:0] - data from transpose memory
endv, // one cycle ahead of starting (continuing) dv
dv, // data output valid
dct2_out);// [8:0]output data
input clk;
input en,start,page;
// input [9:0] tdin;
input [15:0] tdin; //added 6 bit fractional part
output [6:0] rd_cntr;
// output [11:0] dct2_out;
output [12:0] dct2_out;
output dv;
output endv;
// wire [11:0] dct2_out;
wire [12:0] dct2_out;
/* constants */
parameter C3= 16'd54491;
parameter S3= 16'd36410;
parameter C4= 16'd46341;
parameter C6= 16'd25080;
parameter S6= 16'd60547;
parameter C7= 16'd12785;
parameter S7= 16'd64277;
//reg[7:0] memory1a, memory2a, memory3a, memory4a;
reg[16:0] memory1a, memory2a, memory3a, memory4a;
reg [2:0] indexi;
reg dv;
/* 2D section */
//reg[9:0] xb0_in, xb1_in, xb2_in, xb3_in, xb4_in, xb5_in, xb6_in, xb7_in;
//reg[9:0] xb0_reg, xb1_reg, xb2_reg, xb3_reg, xb4_reg, xb5_reg, xb6_reg, xb7_reg;
//reg[9:0] addsub1b_comp,addsub2b_comp,addsub3b_comp,addsub4b_comp;
//reg[10:0] add_sub1b,add_sub2b,add_sub3b,add_sub4b;
reg[15:0] xb0_in, xb1_in, xb2_in, xb3_in, xb4_in, xb5_in, xb6_in, xb7_in;
reg[15:0] xb0_reg, xb1_reg, xb2_reg, xb3_reg, xb4_reg, xb5_reg, xb6_reg, xb7_reg;
reg[16:0] add_sub1b,add_sub2b,add_sub3b,add_sub4b;
reg[15:0] addsub1b_comp,addsub2b_comp,addsub3b_comp,addsub4b_comp;
reg save_sign1b, save_sign2b, save_sign3b, save_sign4b;
//reg[17:0] p1b,p2b,p3b,p4b;
reg[18:0] p1b,p2b,p3b,p4b;
wire[35:0] p1b_all,p2b_all,p3b_all,p4b_all;
reg toggleB;
reg[19:0] dct2d_int1,dct2d_int2;
reg[20:0] dct_2d_int;
wire[12:0] dct_2d_rnd;
// transpose memory read address
wire [6:0] rd_cntr;
reg [5:0] rd_cntrs;
reg rd_page;
// start with the same as stage1
//wire pre_sxregs;
wire endv;
wire sxregs;
// to conserve energy by disabling toggleB
wire sxregs_d8;
reg enable_toggle;
reg en_started;
SRL16 i_endv (.Q(endv), .A0(1'b0), .A1(1'b1), .A2(1'b1), .A3(1'b1), .CLK(clk), .D(start)); // dly=14+1
SRL16 i_disdv (.Q(disdv), .A0(1'b0), .A1(1'b1), .A2(1'b1), .A3(1'b1), .CLK(clk), .D(rd_cntr[5:0]==6'h3f)); // dly=14+1
SRL16 i_sxregs (.Q(sxregs), .A0(1'b0), .A1(1'b0), .A2(1'b0), .A3(1'b1), .CLK(clk),.D((rd_cntr[5:3]==3'h0) && en_started)); // dly=8+1
SRL16 i_sxregs_d8 (.Q(sxregs_d8), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b0), .CLK(clk),.D(sxregs && en_started)); // dly=7+1
always @ (posedge clk) enable_toggle <= en && (sxregs || (enable_toggle && !sxregs_d8));
always @ (posedge clk) en_started <= en && (start || en_started);
always @ (posedge clk) dv <= en && (endv || (dv && ~disdv));
// always @ (posedge clk) toggleB <= sxregs || (~toggleB);
always @ (posedge clk) toggleB <= sxregs || (enable_toggle && (~toggleB));
always @ (posedge clk)
if (sxregs) indexi <= 3'h7;
// else indexi<=indexi+1;
else if (enable_toggle) indexi<=indexi+1;
always @ (posedge clk) begin
if (start) rd_page <= page;
if (start) rd_cntrs[5:0] <=6'b0; // will always count, but that does not matter- What about saving energy ;-) ? Saved...
else if (rd_cntrs[5:0]!=6'h3f) rd_cntrs[5:0] <= rd_cntrs[5:0]+1;
// else rd_cntrs[5:0] <= rd_cntrs[5:0]+1;
end
assign rd_cntr[6:0]= {rd_page,rd_cntrs[2:0],rd_cntrs[5:3]};
// duplicate memory<i>a from stage 1
// store 1D-DCT constant coeeficient values for multipliers */
always @ (posedge clk)
begin
case (indexi)
0 : begin memory1a <= {1'b0,C4}; //8'd91
memory2a <= {1'b0,C4}; //8'd91
memory3a <= {1'b0,C4}; //8'd91
memory4a <= {1'b0,C4}; //8'd91
end
1 : begin memory1a <= {1'b0,S7}; //8'd126;
memory2a <= {1'b0,C3}; //8'd106;
memory3a <= {1'b0,S3}; //8'd71;
memory4a <= {1'b0,C7}; //8'd25;
end
2 : begin memory1a <= {1'b0,S6}; //8'd118;
memory2a <= {1'b0,C6}; //8'd49;
memory3a <= {1'b1,C6}; //-8'd49;
memory4a <= {1'b1,S6}; //-8'd118
end
3 : begin memory1a <= {1'b0,C3}; // 8'd106;
memory2a <= {1'b1,C7}; //-8'd25;
memory3a <= {1'b1,S7}; //-8'd126;
memory4a <= {1'b1,S3}; //-8'd71;
end
4 : begin memory1a <= {1'b0,C4}; // 8'd91;
memory2a <= {1'b1,C4}; //-8'd91;
memory3a <= {1'b1,C4}; //-8'd91;
memory4a <= {1'b0,C4}; // 8'd91;
end
5 : begin memory1a <= {1'b0,S3}; // 8'd71;
memory2a <= {1'b1,S7}; //-8'd126;
memory3a <= {1'b0,C7}; // 8'd25;
memory4a <= {1'b0,C3}; // 8'd106;
end
6 : begin memory1a <= {1'b0,C6}; // 8'd49;
memory2a <= {1'b1,S6}; //-8'd118;
memory3a <= {1'b0,S6}; // 8'd118;
memory4a <= {1'b1,C6}; //-8'd49;
end
7 : begin memory1a <= {1'b0,C7}; // 8'd25;
memory2a <= {1'b1,S3}; //-8'd71;
memory3a <= {1'b0,C3}; // 8'd106;
memory4a <= {1'b1,S7}; //-8'd126;
end
endcase
end
always @ (posedge clk)
begin
xb0_in <= tdin; xb1_in <= xb0_in; xb2_in <= xb1_in; xb3_in <= xb2_in;
xb4_in <= xb3_in; xb5_in <= xb4_in; xb6_in <= xb5_in; xb7_in <= xb6_in;
end
/* register inputs, inputs read in every eighth clk*/
always @ (posedge clk)
if (sxregs) begin
xb0_reg <= xb0_in; xb1_reg <= xb1_in;
xb2_reg <= xb2_in; xb3_reg <= xb3_in;
xb4_reg <= xb4_in; xb5_reg <= xb5_in;
xb6_reg <= xb6_in; xb7_reg <= xb7_in;
end
always @ (posedge clk)
if (toggleB == 1'b1) begin
// add_sub1b <= ({xb7_reg[9],xb7_reg[9:0]} + {xb0_reg[9],xb0_reg[9:0]});
// add_sub2b <= ({xb6_reg[9],xb6_reg[9:0]} + {xb1_reg[9],xb1_reg[9:0]});
// add_sub3b <= ({xb5_reg[9],xb5_reg[9:0]} + {xb2_reg[9],xb2_reg[9:0]});
// add_sub4b <= ({xb4_reg[9],xb4_reg[9:0]} + {xb3_reg[9],xb3_reg[9:0]});
add_sub1b <= ({xb7_reg[15],xb7_reg[15:0]} + {xb0_reg[15],xb0_reg[15:0]});
add_sub2b <= ({xb6_reg[15],xb6_reg[15:0]} + {xb1_reg[15],xb1_reg[15:0]});
add_sub3b <= ({xb5_reg[15],xb5_reg[15:0]} + {xb2_reg[15],xb2_reg[15:0]});
add_sub4b <= ({xb4_reg[15],xb4_reg[15:0]} + {xb3_reg[15],xb3_reg[15:0]});
end else begin
// add_sub1b <= ({xb7_reg[9],xb7_reg[9:0]} - {xb0_reg[9],xb0_reg[9:0]});
// add_sub2b <= ({xb6_reg[9],xb6_reg[9:0]} - {xb1_reg[9],xb1_reg[9:0]});
// add_sub3b <= ({xb5_reg[9],xb5_reg[9:0]} - {xb2_reg[9],xb2_reg[9:0]});
// add_sub4b <= ({xb4_reg[9],xb4_reg[9:0]} - {xb3_reg[9],xb3_reg[9:0]});
add_sub1b <= ({xb7_reg[15],xb7_reg[15:0]} - {xb0_reg[15],xb0_reg[15:0]});
add_sub2b <= ({xb6_reg[15],xb6_reg[15:0]} - {xb1_reg[15],xb1_reg[15:0]});
add_sub3b <= ({xb5_reg[15],xb5_reg[15:0]} - {xb2_reg[15],xb2_reg[15:0]});
add_sub4b <= ({xb4_reg[15],xb4_reg[15:0]} - {xb3_reg[15],xb3_reg[15:0]});
end
always @ (posedge clk) begin
// save_sign1b <= add_sub1b[10];
// save_sign2b <= add_sub2b[10];
// save_sign3b <= add_sub3b[10];
// save_sign4b <= add_sub4b[10];
// addsub1b_comp <= add_sub1b[10]? (-add_sub1b) : add_sub1b;
// addsub2b_comp <= add_sub2b[10]? (-add_sub2b) : add_sub2b;
// addsub3b_comp <= add_sub3b[10]? (-add_sub3b) : add_sub3b;
// addsub4b_comp <= add_sub4b[10]? (-add_sub4b) : add_sub4b;
save_sign1b <= add_sub1b[16];
save_sign2b <= add_sub2b[16];
save_sign3b <= add_sub3b[16];
save_sign4b <= add_sub4b[16];
addsub1b_comp <= add_sub1b[16]? (-add_sub1b) : add_sub1b;
addsub2b_comp <= add_sub2b[16]? (-add_sub2b) : add_sub2b;
addsub3b_comp <= add_sub3b[16]? (-add_sub3b) : add_sub3b;
addsub4b_comp <= add_sub4b[16]? (-add_sub4b) : add_sub4b;
end
// assign p1b_all = addsub1b_comp * memory1a[15:0];
// assign p2b_all = addsub2b_comp * memory2a[15:0];
// assign p3b_all = addsub3b_comp * memory3a[15:0];
// assign p4b_all = addsub4b_comp * memory4a[15:0];
assign p1b_all = addsub1b_comp[15:0] * memory1a[15:0];
assign p2b_all = addsub2b_comp[15:0] * memory2a[15:0];
assign p3b_all = addsub3b_comp[15:0] * memory3a[15:0];
assign p4b_all = addsub4b_comp[15:0] * memory4a[15:0];
always @ (posedge clk)
begin
/// Next line was simulated differently in Icarus 0.9 (wrong?) than in Icarus 0.8 (right?)
/// Xilinx probably did as 0.8
/// p1b_all[31:14] - 18-bit number, p1b - 19-bit. in 0.9 (-p1b_all[31:14]) was also 18, not expand to 19 bits, 0.8 - did
/// p1b <= (save_sign1b ^ memory1a[16]) ? (-p1b_all[31:14]) :(p1b_all[31:14]);
p1b[18:0] <= (save_sign1b ^ memory1a[16]) ? (-p1b_all[32:14]) :(p1b_all[32:14]);
p2b[18:0] <= (save_sign2b ^ memory2a[16]) ? (-p2b_all[32:14]) :(p2b_all[32:14]);
p3b[18:0] <= (save_sign3b ^ memory3a[16]) ? (-p3b_all[32:14]) :(p3b_all[32:14]);
p4b[18:0] <= (save_sign4b ^ memory4a[16]) ? (-p4b_all[32:14]) :(p4b_all[32:14]);
end
/* multiply the outputs of the add/sub block with the 8 sets of stored coefficients */
/* Final adder. Adding the ouputs of the 4 multipliers */
always @ (posedge clk)
begin
dct2d_int1 <= ({p1b[18],p1b[18:0]} + {p2b[18],p2b[18:0]});
dct2d_int2 <= ({p3b[18],p3b[18:0]} + {p4b[18],p4b[18:0]});
dct_2d_int <= ({dct2d_int1[19],dct2d_int1[19:0]} + {dct2d_int2[19],dct2d_int2[19:0]});
end
assign dct_2d_rnd[12:0] = dct_2d_int[20:8];
assign dct2_out[12:0] = dct_2d_rnd[12:0] + dct_2d_int[7];
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment