/// LSU EE 4755 -- Fall 2021 -- Digital Design / HDL // /// Synthesis Hints and Assertions /// References // // Genus HDL Modeling Guide, August 2021 /////////////////////////////////////////////////////////////////////////////// /// Rationale for Assertions and Constraints /// :Def: Hint // A suggestion of what some tool should do. // For example, to use a tech library's multiplexor rather than basic gates. // // Hints typically impact cos and performance, but not correctness. // That is, ignoring a good hint will hurt cost and performance but // will not affect correctness. /// :Def: Assertion // A description using some mechanism .. // .. of something which can be assumed to be true. // // Assertions impact cost, performance, *and* correctness. // // Ignoring a good assertion will result in lower cost or performance. // Using a bad assertion CAN RESULT IN INCORRECT hardware. // // Note: this not the same as the C library assert macro. // Such as. assert( x > 0 ); /// :Def: Constraint // A limit on certain values, such as arrival times of signals. /// Specifying Hints and Assertions // // Most an be specified using a pragma. // Some can be specified using SystemVerilog keywords. // Some can be specified using synthesis program settings. /////////////////////////////////////////////////////////////////////////////// /// Synthesis Pragmata // /// :Def: pragma // Something placed in source code written in language X .. // .. which is not defined by language X .. // .. but is understood by compilers or other tools for language X. // // :Def: pragmata // Plural of pragma. /// Using Pragmata // // Since a pragma is not recognized by the language it must be specified // in some special way. // // Typically they are included in comments. This is true for SystemVerilog. // // cadence PRAGMA_NAME PRAGMA_ARGS... /////////////////////////////////////////////////////////////////////////////// /// Pragmata for Case Statements // // /// full_case typedef enum { Cmd_Reset = 0, Cmd_Nop=1, Cmd_Write=2, Cmd_Shift=3, Cmd_Reserved = 4, Cmd_Also_Reserved = 5, Cmd_SIZE } Command; module fc_demo #( int wi = 8 ) ( output logic [wi-1:0] dout, input uwire [3:0] cmd, input uwire [wi-1:0] din, input uwire clk ); always_ff @( posedge clk ) begin // Tell synthesis program that only the four values of cmd are // possible. // case ( cmd ) // cadence full_case Cmd_Reset: dout <= 0; Cmd_Nop: dout <= dout + 1; Cmd_Write: dout <= din; Cmd_Shift: dout <= dout << din; endcase // /// With full_case: // // The synthesis program won't check whether cmd[2] is zero. // Register dout will not need an enable signal. // /// If full_case were not used: // // Synthesis program would expect all 8 possible values of cmd, // and so would need to make sure that bit cmd[2] were zero for // the four cases above, increasing the cost slightly. end endmodule /// parallel_case module pc_demo #( int kwid = 8 ) ( output logic [7:0] mindex, input [kwid:1] key, input [kwid:1] keys [4] ); // Use parallel_case to indicate that exactly one case is expected // to be true. That is, if keys[1] == key then we don't expected // keys[0] == key, keys[2]=key, nor keys[3]=key. // always_comb case ( key ) // cadence parallel_case keys[0]: mindex = 0; keys[1]: mindex = 1; keys[2]: mindex = 2; keys[3]: mindex = 3; default: mindex = -1; endcase // Note: // unique case: At most one match. // priority case: Execute the first match only. endmodule module quick; always_comb begin if ( a < 1 ) begin foo; end else if ( b > 3 ) begin bar; end if ( b > 3 ) begin bar; end if ( a >= 1 && b > 3 ) begin bar; end end endmodule /////////////////////////////////////////////////////////////////////////////// /// Inlining Pragmata module use_mults #( int w = 64, logic [w-1:0] plr2 = 123 ) ( output uwire [2*w-1:0] p10, p11, p12, p20, p21, p22, input uwire [w-1:0] cand, plr1 ); /// None of the Inputs are Constant // mult_linear_inlined #(w) m10( p10, cand, plr1 ); mult_linear #(w) m11( p11, cand, plr1 ); mult_linear #(w) /* cadence inline_instance */ m12( p12, cand, plr1 ); // // All three multipliers above should have the same cost and delay. // The synthesis time spent on the two inlined modules was wasted. /// The Multiplier (plr2) is a Constant // mult_linear_inlined #(w) m20( p20, cand, plr2 ); mult_linear #(w) m21( p21, cand, plr2 ); mult_linear #(w) /* cadence inline_instance */ m22( p22, cand, plr2 ); // // The inlined multipliers, m20 and m22, will be fast and lower // cost than m10 because they were optimized for the constant // (plr2). The synthesis program may or may not inline m21, // depending on synthesis effort options. If m21 is not inlined it // will be the same cost and speed as m10,m11, and m12, which is // slower and more costly than m20 and m22. endmodule module mult_linear_inlined #(int w = 16) (output logic [2*w-1:0] prod, input uwire [w-1:0] cand, plier); // Force each instantiation of this module to be optimized separately. // // cadence inline uwire [2*w-1:0] b[w:0]; assign b[0] = 0; assign prod = b[w]; for ( genvar pos = 0; pos < w; pos++ ) begin uwire [2*w-1:0] pp = plier[pos] ? cand << pos : 0; assign b[pos+1] = pp + b[pos]; end endmodule module mult_linear #(int w = 16) (output logic [2*w-1:0] prod, input uwire [w-1:0] cand, plier); uwire [2*w-1:0] b[w:0]; assign b[0] = 0; assign prod = b[w]; for ( genvar pos = 0; pos < w; pos++ ) begin uwire [2*w-1:0] pp = plier[pos] ? cand << pos : 0; assign b[pos+1] = pp + b[pos]; end endmodule ////////////////////////////////////////////////////////////////////////////// /// Component Selection /// map_to_mux // // Try to use a tech library multiplexor. ////////////////////////////////////////////////////////////////////////////// /// Don't Bother With Optimization /// Suppress DCE (dead-code elimination) of Nets and Registers // // keep_signal_name FOO // preserve_sequential (Don't eliminate reg.) module no_dce_demo_r ( output logic [7:0] val, input uwire clk ); // Tell synthesis program to infer a register for next_val whether // it's live-out or not. logic [7:0] next_val /* cadence preserve_sequential */ ; always_ff @( posedge clk ) begin next_val = val + 1; val = next_val; end endmodule // Useful Pragmata: // translate_on // translate_off // Set attribute hdl_report_case_info to true to.. // map_to_mux // Use a mux in the tech library. // preserve_sequential // Don't delete flip flops during optimization. // syn_keep // Used after a net declaration. // The logic driving that net is protected from DCE. // inline // Used in a module. // Indicates that instances of this module will be inlined. // Look at: // black_box // infer_multibit // one_cold // script_begin // synthesis_on