Commit a670c623 authored by Andrey Filippov's avatar Andrey Filippov

module to convert 16-bit data to 8 bit using piecewise-linear table conversion

parent a6ac2cd2
/*******************************************************************************
* Module: sens_gamma
* Date:2015-05-24
* Author: andrey
* Description: table based piecewise-linear conversion of 16 -> 8 bit data
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* sens_gamma.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sens_gamma.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module sens_gamma #(
parameter SENS_GAMMA_ADDR = 'h338,
parameter SENS_GAMMA_ADDR_MASK = 'h3fc,
parameter SENS_GAMMA_CTRL = 'h0,
// parameter SENS_GAMMA_STATUS = 'h1,
parameter SENS_GAMMA_TADDR = 'h2,
parameter SENS_GAMMA_TDATA = 'h3 // 1.. 2^16, 0 - use HACT
// parameter SENS_GAMMA_STATUS_REG = 'h32
) (
input rst,
input pclk, // global clock input, pixel rate (96MHz for MT9P006)
//input en, // @(posedge pclk) // 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.
input [15:0] pxd_in, // @(posedge pclk)
input hact_in,
input sof_in, // start of frame, single pclk, input
input eof_in, // end of frame
input trig,
output [7:0] pxd_out,
output hact_out,
output sof_out, // start of frame, single pclk, output
output eof_out, // end of frame
// programming interface
input mclk, // global clock, half DDR3 clock, synchronizes all I/O through the command port
input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb // strobe (with first byte) for the command a/d
/*
output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
output status_rq, // input request to send status downstream
input status_start // Acknowledge of the first status packet byte (address)
*/
);
localparam SENS_GAMMA_MODE_WIDTH=10;
wire [1:0] cmd_a;
wire [31:0] cmd_data;
wire cmd_we;
// wire set_status_w;
wire set_ctrl_w;
wire set_taddr_w;
wire set_tdata_w;
reg [10:0] taddr;
reg [SENS_GAMMA_MODE_WIDTH-1:0] mode=0;
reg [SENS_GAMMA_MODE_WIDTH-1:0] mode_mclk=0;
wire [1:0] bayer;
wire table_page; //part of the mode register
wire en_input;
wire repet_mode;
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
// reg hact_m;
reg [3:0] hact_d; // combine sevaral delays?
// reg en_d;
reg [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 in table word - msb - sign (0 plus, 1 - minus), other 7 bits - +/-127 difference to the next value
wire [9:0] table_base_w; // 10 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;
reg [17:7] table_mult_r;
reg [ 9:0] table_base_r;
wire [9:0] interp_data;
wire [7:0] pxd_in_d2;
reg [7:0] pxd_in_r3; // register to be absorbed in mpy
reg vblank; // from sof to first hact
reg pend_trig; // pending trigger (if trig came outside of vblank
wire sof_masked;
reg frame_run;
assign pxd_out = cdata;
assign hact_out = hact_d[3];
assign set_ctrl_w = cmd_we && (cmd_a == SENS_GAMMA_CTRL );
// assign set_status_w = cmd_we && (cmd_a == SENS_GAMMA_STATUS );
assign set_taddr_w = cmd_we && (cmd_a == SENS_GAMMA_TADDR );
assign set_tdata_w = cmd_we && (cmd_a == SENS_GAMMA_TDATA );
assign bayer = mode[1:0];
assign table_page = mode[2]; // TODO: re-assign?
assign en_input = mode[3];
assign repet_mode = mode[4]; // TODO: re-assign?
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 table_mult=table_diff*{1'b0,pxd_in_r3[7:0]}; // 11 bits, signed* 9 bits, positive
assign sof_masked= sof_in && (pend_trig || repet_mode) && en_input;
always @ (posedge rst or posedge mclk) begin
if (rst) taddr <= 0;
else if (set_taddr_w) taddr <= cmd_data[10:0];
else if (set_tdata_w) taddr <= taddr + 1;
if (rst) mode_mclk <= 0;
else if (set_ctrl_w) mode_mclk <= cmd_data[SENS_GAMMA_MODE_WIDTH-1:0];
end
// reg vblank; // from sof to first hact
// reg pend_trig; // pending trigger (if trig came outside of vblank
always @ (posedge rst or posedge pclk) begin
if (rst) begin
mode <= 0;
// hact_m <= 0;
// en_d <= 0;
hact_d[3:0] <= 0;
bayer_nset <= 0;
bayer0_latched <= 0;
color[1:0] <= 0;
cdata[7:0] <= 0;
vblank <= 0; // from sof to first hact
pend_trig <= 0; // pending trigger (if trig came outside of vblank
frame_run <= 0;
end else begin
mode <= mode_mclk;
// hact_m <= hact_in && en;
// en_d <= en;
hact_d[3:0] <= {hact_d[2:0],hact_in};
bayer_nset <= frame_run && (bayer_nset || hact_in);
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 };
pxd_in_r3 <= pxd_in_d2;
cdata[7:0] <= interp_data[9:2];
vblank <= sof_in || (vblank && !hact_in);
pend_trig <= (trig && !vblank) || (pend_trig && !sof_in);
frame_run <= sof_masked || (frame_run && !eof_in);
end
end
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]};
table_mult_r[17:7] <= table_mult[17:7];
table_base_r[ 9:0] <= table_base[ 9:0];
end
cmd_deser #(
.ADDR (SENS_GAMMA_ADDR),
.ADDR_MASK (SENS_GAMMA_ADDR_MASK),
.NUM_CYCLES (6),
.ADDR_WIDTH (2),
.DATA_WIDTH (32)
) cmd_deser_sens_io_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (cmd_a), // output[15:0]
.data (cmd_data), // output[31:0]
.we (cmd_we) // output
);
/*
status_generate #(
.STATUS_REG_ADDR(SENS_GAMMA_STATUS_REG),
.PAYLOAD_BITS(15) // STATUS_PAYLOAD_BITS)
) status_generate_sens_io_i (
.rst (rst), // input
.clk (mclk), // input
.we (set_status_w), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status), // input[25:0]
.ad (status_ad), // output[7:0]
.rq (status_rq), // output
.start (status_start) // input
);
*/
dly_16 #(
.WIDTH(8)
) dly_16_pxd_i (
.clk (pclk), // input
.rst (rst), // input
.dly (2), // input[3:0]
.din (pxd_in[7:0]), // input[0:0]
.dout(pxd_in_d2) // output[0:0]
);
dly_16 #(
.WIDTH(2)
) dly_16_sof_eof_i (
.clk (pclk), // input
.rst (rst), // input
.dly (3), // input[3:0]
.din ({eof_in, sof_masked}), // input[0:0]
.dout({eof_out,sof_out}) // output[0:0]
);
//sof_masked
ramp_var_w_var_r #(
.REGISTERS (1), // try to delay i2c_byte_start by one more cycle
.LOG2WIDTH_WR (4),
.LOG2WIDTH_RD (4)
) i_gamma_table (
.rclk (pclk), // input
.raddr ({table_page,color[1:0],pxd_in[15:8]}), // input[11:0]
.ren (hact_in), // input TODO: add "en"?
.regen (hact_d[0]), // input
.data_out ({table_diff_w[7:0],table_base_w[9:0]}), // output[7:0]
.wclk (mclk), // input
.waddr (taddr), // input[9:0]
.we (set_tdata_w), // input
.web (8'hff), // input[7:0]
.data_in (cmd_data[17:0]) // input[31:0]
);
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