/*!
* Module:dct1d_chen_reorder_out
* @file dct1d_chen_reorder_out.v
* @date 2016-06-08
* @author Andrey Filippov
*
* @brief Reorder data from dct1d_chen output to natural sequence
*
* @copyright Copyright (c) 2016 Elphel, Inc.
*
* License:
*
*dct1d_chen_reorder_out.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.
*
* dct1d_chen_reorder_out.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*/
`timescale 1ns/1ps
module dct1d_chen_reorder_out#(
parameter WIDTH = 24
)(
input clk,
input rst,
input en, // sampled at timeslot of pre2_start
input [WIDTH -1:0] din, // pre2_start-X-F4-X-F2-X-F6-F5-F0-F3-X-F1-X-F7
input pre2_start, // Two cycles ahead of F4
output [WIDTH -1:0] dout, // data in natural order: F0-F1-F2-F3-F4-F5-F6-F7
output start_out, // 1 ahead of the first F0
output reg dv, // output data valid
output en_out // to be sampled when start_out is expected
);
reg [WIDTH -1:0] reord_buf_ram[0:15];
reg [WIDTH -1:0] dout_r;
reg [3:0] cntr_in;
reg pre_we_r;
reg we_r;
reg [3:0] ina_rom;
wire [3:0] waddr = {ina_rom[3] ^ cntr_in[3], ina_rom[2:0]};
reg [3:0] raddr;
reg [2:0] per_type; // idle/last:0, first cycle - 1, 2-nd - 2, other - 3,... ~en->6 ->7 -> 0 (to generate pre2_start_out)
reg start_out_r;
reg en_out_r;
wire stop_out; // qualify with en
assign dout = dout_r;
assign start_out = start_out_r;
assign en_out = en_out_r;
always @(posedge clk) begin
if (rst) per_type <= 0;
else if (pre2_start) per_type <= 3'h1;
else if (&cntr_in[2:0]) begin
if (!per_type[2] && !en) per_type <= 3'h6;
else if ((per_type != 0) && (per_type != 3)) per_type <= per_type + 1;
end
if (rst) pre_we_r <= 0;
else if (pre2_start) pre_we_r <= 1;
else if ((per_type == 0) || ((cntr_in==3) && per_type[2])) pre_we_r <= 0;
we_r <= pre_we_r;
if (rst) cntr_in <= 0;
else if (pre2_start) cntr_in <= {~cntr_in[3],3'b0};
else if (pre_we_r) cntr_in <= cntr_in + 1;
case (cntr_in[2:0])
3'h0: ina_rom <= {1'b0,3'h4};
3'h1: ina_rom <= {1'b1,3'h1};
3'h2: ina_rom <= {1'b0,3'h2};
3'h3: ina_rom <= {1'b1,3'h7};
3'h4: ina_rom <= {1'b0,3'h6};
3'h5: ina_rom <= {1'b0,3'h5};
3'h6: ina_rom <= {1'b0,3'h0};
3'h7: ina_rom <= {1'b1,3'h3};
endcase
if (we_r) reord_buf_ram[waddr] <= din;
if ((per_type == 2) && (cntr_in == 1)) raddr <= {~cntr_in[3], 3'b0};
else if ((raddr[2:0] != 0) || (per_type !=0)) raddr <= raddr + 1;
if (en_out_r) dout_r <= reord_buf_ram[raddr];
start_out_r <= (per_type == 2) && (cntr_in == 1);
if (rst ||(per_type == 0) ) en_out_r <= 0;
// else if (cntr_in == 1) en_out_r <= (per_type == 2) || !per_type[2];
else if ((cntr_in == 1) && (per_type == 2)) en_out_r <= 1;
else if (stop_out && !en) en_out_r <= 0;
//stop_out
dv <= en_out_r;
// if (rst) dv <= 0;
// else if (start_out_r) dv <= 1;
// else if ((raddr[2:0] == 0) && !en_out_r) dv <= 0;
end
dly01_16 dly01_16_i (
.clk (clk), // input
.rst (rst), // input
.dly (4'd8), // input[3:0]
.din ((&cntr_in[2:0]) && !en), // input
.dout (stop_out) // output
);
endmodule