If I have a vector and I want to read a part of it starting somewhere. Can I use the syntax vector[staring_point +: output_length]
with starting_point
being an integer? Is it synthesizable?
If I write a code like this:
module my_mod(
input logic din,
input logic clk,
input logic[2:0] start_ptr,
output logic[3:0] dout);
logic[10:0] vector = 0;
always_ff@(posedge clk) vector <= {vector[9:0], din}; --shift register
always_comb dout <= vector[start_ptr +: 4];
endmodule
The design is just this and the input and output are bounded to GPIOs. I'm expecting a mux for each output bit. Surprisingly Vivado will synthesize 1FF and 1LUTRAM that is an SRL16 so a shift register with integrated mux, but the primitive has only one output and the "dout" signal is driven only with the first bit.
The other 3bits are buffered to 0.
Is the syntax +:
correct? Is that consistent or it's a bug of Vivado?
I cleaned code and built in Vivado 2020.2 As pointed out some outputs are inappropriately tied off in synthesis.
Cleaned up code:
module my_mod(
input logic din,
input logic clk,
input logic[2:0] start_ptr,
output logic[3:0] dout);
logic[10:0] vector;
always_ff@(posedge clk)
vector <= {vector[9:0], din}; //shift register
always_comb
dout = vector[start_ptr +: 4];
endmodule
And the RTL that the code infers:
Vivado is not doing the right thing (its a bug). This is worth reporting to Xilinx. The +: operator is capable of generating a mux/barrel shifter. How: Change the code to infer regs instead of SRL's (added a RTL reset) then it infers the design intent.
module my_mod(
input logic din,
input logic clk,
input logic[2:0] start_ptr,
input logic rst,
output logic[3:0] dout);
logic[10:0] vector;
always_ff@(posedge clk)
if(rst)
vector <= 0;
else
vector <= {vector[9:0], din}; //shift register
always_comb
dout = vector[start_ptr +: 4];
endmodule
To stay closer to what you posted (no reset) you can use the right shift operator. This also infers the mux as intended. This does not give an initial value of 0, in the reg, so you need to add the reset if you need an initial value.
module my_mod(
input logic din,
input logic clk,
input logic[2:0] start_ptr,
output logic[3:0] dout);
logic[10:0] vector;
always_ff@(posedge clk)
vector <= {vector[9:0], din}; //shift register
always_comb
dout = vector >> start_ptr ;
endmodule
Here is the RTL view of the design using the shift operator (>>).
At one point I was thinking Xilinx intended for the +: and -: operators to be used at elaboration time only, for example in a generate loop. If that were the case then Xilinx should state that in the synthesis guide UG901 (they do not). Also Vivado infers the combinational logic for a design with registers, why should it not work with SRL's?
To me its a bug.
Good catch.