I hate multicycle paths. They have their uses, but they are not simulatable. When you declare something:
set_multicycle_path -setup -from a_in -to c_out 2
set_multicycle_path -hold -from a_in -to c_out 1
You are essentially telling the tool that it has one extra clock cycle (a total of 2 clocks) to generate c_out. Now, if a_in is stable for 2 clocks guaranteed, then it can make sense to take advantage of this fact, however, if you make a mistake or the design changes. Often you can get rid of the multicycle by pipelining. Especially in math operations in an FPGA, this can often be done without adding resources.
Question:
I have the following code:
logic [63:0] a_in;
logic [31:0] b_in;
logic [x:0] c_out;
always_ff @(posedge clk) c_out <= a_in * b_in;
there is a two clock cycle multicycle path from a_in and b_in to c_out.
- What is the size of c_out?
- Can you rewrite this code so that it still takes two clock cycles, yet there is no longer a multicycle path?
Assumption: You can do a 63×32 multiply in 2 cycles and a 32×32 multiply in one cycle.
Answerwhen you add two numbers, the result is 1 larger than largest input.
- When you multiply two numbers, the result is the addition of both sizes. therefore x = 64+32=96 bits.
// The way to achieve this is to use partial products. We can split a_in into a_low and a_high: logic [31:0] a_low, a_high; assign {a_high, a_low} = a_in; // Now the partial products, just like 10 x 5 = (1*5) * 10 + (0*5) * 1 logic [63:0] part_low, part_high; always_ff @(posedge clk) begin part_high <= a_high * b_in; part_low <= a_low * b_in; end // Now add the partial products always_ff @(posedge clk) begin c_out <= (part_high << 32) + part_low; end
The above code still takes the same two clocks. The register stages are part of the DSP blocks, so no additional logic is used. Now we no longer have the multicycle paths to worry about.