// ================================================================ // NVDLA Open Source Project // // Copyright(c) 2016 - 2017 NVIDIA Corporation. Licensed under the // NVDLA Open Hardware License; Check "LICENSE" which comes with // this distribution for more information. // ================================================================ // File Name: NV_NVDLA_CDP_DP_INTP_unit.v module NV_NVDLA_CDP_DP_INTP_unit ( nvdla_core_clk ,nvdla_core_rstn ,interp_in0_pd ,interp_in1_pd ,interp_in_pd ,interp_in_scale ,interp_in_shift ,interp_in_vld ,interp_out_rdy ,interp_in_rdy ,interp_out_pd ,interp_out_vld ); ///////////////////////////////////////////////////////////////// input nvdla_core_clk; input nvdla_core_rstn; input [38:0] interp_in0_pd; input [37:0] interp_in1_pd; input [16:0] interp_in_pd; input [16:0] interp_in_scale; input [5:0] interp_in_shift; input interp_in_vld; input interp_out_rdy; output interp_in_rdy; output [16:0] interp_out_pd; output interp_out_vld; ///////////////////////////////////////////////////////////////// reg [88:0] int_add; reg [56:0] int_mul; reg [57:0] int_mul_for_Rshift; reg [39:0] int_sub; reg int_vld_d0; reg int_vld_d1; reg int_vld_d2; reg [16:0] interp_in0_pd_d0; reg [16:0] interp_in0_pd_d1; reg [16:0] interp_in_offset_d0; reg [5:0] interp_in_shift_d0; reg [5:0] interp_in_shift_d1; wire int_in_load; wire int_in_load_d0; wire int_in_load_d1; wire int_in_rdy; wire int_in_vld; wire [15:0] int_interp_out_pd; wire [87:0] int_mul_rs; wire [31:0] int_mul_shift_frac; wire [87:0] int_mul_shift_int; wire int_rdy_d0; wire int_rdy_d1; wire int_rdy_d2; wire [5:0] interp_in_shift_abs; wire [4:0] intp_in_shift_inv; wire [5:0] intp_in_shift_inv_inc; ///////////////////////////////////////////////////////////////// /////////////////////////////////////////// //interp_in_vld assign interp_in_rdy = int_in_rdy; /////////////////////////////////////////// assign int_in_vld = interp_in_vld; assign int_in_rdy = ~int_vld_d0 | int_rdy_d0; assign int_in_load = int_in_vld & int_in_rdy; /////////////////// //X1-X0 always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin if (!nvdla_core_rstn) begin int_sub[39:0] <= {40{1'b0}}; interp_in0_pd_d0 <= {17{1'b0}}; interp_in_offset_d0 <= {17{1'b0}}; interp_in_shift_d0 <= {6{1'b0}}; end else begin if(int_in_load) begin int_sub[39:0] <= $signed({interp_in1_pd[37],interp_in1_pd[37:0]}) - $signed(interp_in0_pd[38:0]); interp_in0_pd_d0 <= interp_in_pd[16:0]; interp_in_offset_d0 <= interp_in_scale[16:0]; interp_in_shift_d0 <= interp_in_shift[5:0]; end end end always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin if (!nvdla_core_rstn) begin int_vld_d0 <= 1'b0; end else begin if(int_in_vld) int_vld_d0 <= 1'b1; else if(int_rdy_d0) int_vld_d0 <= 1'b0; end end assign int_rdy_d0 = ~int_vld_d1 | int_rdy_d1; assign int_in_load_d0 = int_vld_d0 & int_rdy_d0; /////////////////// //(X1-X0)*frac always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin if (!nvdla_core_rstn) begin int_mul[56:0] <= {57{1'b0}}; interp_in0_pd_d1 <= {17{1'b0}}; interp_in_shift_d1 <= {6{1'b0}}; end else begin if(int_in_load_d0) begin int_mul[56:0] <= $signed(int_sub[39:0]) * $signed(interp_in_offset_d0); interp_in0_pd_d1 <= interp_in0_pd_d0[16:0]; interp_in_shift_d1 <= interp_in_shift_d0[5:0]; end end end //>>16 proc for ((X1-X0)*frac) >>16 assign intp_in_shift_inv[4:0] = ~interp_in_shift_d1[4:0]; assign intp_in_shift_inv_inc[5:0] = intp_in_shift_inv[4:0] + 5'd1; assign interp_in_shift_abs[5:0] = interp_in_shift_d1[5] ? intp_in_shift_inv_inc[5:0]: interp_in_shift_d1[5:0]; `ifdef SPYGLASS_ASSERT_ON `else // spyglass disable_block NoWidthInBasedNum-ML // spyglass disable_block STARC-2.10.3.2a // spyglass disable_block STARC05-2.1.3.1 // spyglass disable_block STARC-2.1.4.6 // spyglass disable_block W116 // spyglass disable_block W154 // spyglass disable_block W239 // spyglass disable_block W362 // spyglass disable_block WRN_58 // spyglass disable_block WRN_61 `endif // SPYGLASS_ASSERT_ON `ifdef ASSERT_ON `ifdef FV_ASSERT_ON `define ASSERT_RESET nvdla_core_rstn `else `ifdef SYNTHESIS `define ASSERT_RESET nvdla_core_rstn `else `ifdef ASSERT_OFF_RESET_IS_X `define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b0 : nvdla_core_rstn) `else `define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b1 : nvdla_core_rstn) `endif // ASSERT_OFF_RESET_IS_X `endif // SYNTHESIS `endif // FV_ASSERT_ON // VCS coverage off nv_assert_never #(0,0,"CDP_out of range shifter abs shouldn't out of data range of signed-int6") zzz_assert_never_1x (nvdla_core_clk, `ASSERT_RESET, int_in_load_d1 & ((interp_in_shift_d1[5] & (interp_in_shift_abs > 6'd32)) | ((~interp_in_shift_d1[5]) & (interp_in_shift_abs > 6'd31)))); // spyglass disable W504 SelfDeterminedExpr-ML // VCS coverage on `undef ASSERT_RESET `endif // ASSERT_ON `ifdef SPYGLASS_ASSERT_ON `else // spyglass enable_block NoWidthInBasedNum-ML // spyglass enable_block STARC-2.10.3.2a // spyglass enable_block STARC05-2.1.3.1 // spyglass enable_block STARC-2.1.4.6 // spyglass enable_block W116 // spyglass enable_block W154 // spyglass enable_block W239 // spyglass enable_block W362 // spyglass enable_block WRN_58 // spyglass enable_block WRN_61 `endif // SPYGLASS_ASSERT_ON assign {int_mul_shift_int[87:0],int_mul_shift_frac[31:0]} = interp_in_shift_d1[5] ? {{{31{int_mul[56]}}, int_mul[56:0]},32'd0} << interp_in_shift_abs[5:0] : {{{31{int_mul[56]}}, int_mul[56:0]},32'd0} >> interp_in_shift_abs[5:0]; //rounding process for right shift always @( int_mul_shift_int or int_mul_shift_frac ) begin //if(int_mul_shift_int[55]) begin if(int_mul_shift_int[56]) begin if(int_mul_shift_frac[31]) begin if(~(|int_mul_shift_frac[30:0])) int_mul_for_Rshift = {int_mul_shift_int[56],int_mul_shift_int[56:0]}; else int_mul_for_Rshift = $signed(int_mul_shift_int[56:0]) + $signed({56'd0,1'b1}); end else begin int_mul_for_Rshift = {int_mul_shift_int[56],int_mul_shift_int[56:0]}; end end else begin int_mul_for_Rshift = $signed(int_mul_shift_int[56:0]) + $signed({56'd0,int_mul_shift_frac[31]}); end end assign int_mul_rs[87:0] = interp_in_shift_d1[5] ? int_mul_shift_int[87:0] : ({{30{int_mul_for_Rshift[57]}}, int_mul_for_Rshift[57:0]}); always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin if (!nvdla_core_rstn) begin int_vld_d1 <= 1'b0; end else begin if(int_vld_d0) int_vld_d1 <= 1'b1; else if(int_rdy_d1) int_vld_d1 <= 1'b0; end end assign int_rdy_d1 = ~int_vld_d2 | int_rdy_d2; assign int_in_load_d1 = int_vld_d1 & int_rdy_d1; //Xo = X0+[(X1-X0)*frac>>16] always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin if (!nvdla_core_rstn) begin int_add[88:0] <= {89{1'b0}}; end else begin if(int_in_load_d1) begin int_add[88:0] <= $signed(int_mul_rs[87:0]) + $signed({{71{interp_in0_pd_d1[16]}}, interp_in0_pd_d1[16:0]}); end end end assign int_interp_out_pd[15:0] = int_add[88] ? (&int_add[88:15] ? {int_add[88],int_add[14:0]} : 16'h8000) : (|int_add[88:15] ? 16'h7fff : int_add[15:0]); always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin if (!nvdla_core_rstn) begin int_vld_d2 <= 1'b0; end else begin if(int_vld_d1) int_vld_d2 <= 1'b1; else if(int_rdy_d2) int_vld_d2 <= 1'b0; end end assign int_rdy_d2 = interp_out_rdy; ////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// assign interp_out_vld = int_vld_d2; assign interp_out_pd[16:0] = {int_interp_out_pd[15],int_interp_out_pd[15:0]}; /////////////////////////////////////////// endmodule // NV_NVDLA_CDP_DP_INTP_unit