Best way to do a dynamic bit slice?
2 views (last 30 days)
I am still learning my way around HDL coder, but I'm starting to think I can't get optimal results in Verilog from the set of built in components. My current struggle is what I call a dynamic bit slice. In my case I need a single bit out of a ufixN input (I have N = 4, 16, 32, 71 in my current model). So I make a subsystem with N Extract Bits components (Bit Slice would work too, but these are unsigned inputs so Extract Bits works just as well) and an Nx1 switch. For N = 71, this results in a Verilog file that is 819 lines long and thus more annoying when doing a code audit. So I tried a function block:
function dout = fcn(din, sel)
% Take an unsigned integer (din) and output a given bit based on an input select (sel)
dout = bitget(din, sel+1);
That results in a much more compact Verilog file (57 lines), but it brings in lines of code that I don't I want. There are 4 lines starting with reg and there is a + 1 in one line using these reg variables and a -1 in another. Is this unavoidable because bitget uses Matlab indexing (starting with 1) and Verilog/Hardware uses 0? Now I realize synthesis tools may do their own optimization and I may not end up with two adders being consumed on an FPGA or ASIC, but I'd really rather not have it in the Verilog in the first place.
What is the right way to create a dynamic bit slice? I can't write in straight Verilog yet, but I'm guessing what I want is incredibly compact if I were hand coding HDL directly. And in my opinion, if you can't get HDL coder to put out as good a file as someone who is hand coding in a simple example, then that should be a top priority for improvement.
Whatever the right solution, I'd like the option of flattening into the subsystem above (i.e. I'd like just a few lines of Verilog inline with the other processing I'm doing when implementing this operation).
Tim McBrayer on 7 Mar 2017
Simulink has limited bit-manipulation capabilities; it's designed to address a higher level of abstraction, for the most part. That said, with the appropriate settings, your MATLAB function generates pretty good Verilog code. While the file is 53 lines long, the functional always block is only 6 lines, including two ends and range checking of the input:
always @(data, bitsel) begin
if (((bitsel + 8'd1) >= 8'd1) && ((bitsel + 8'd1) <= 8'd31)) begin
bit_idx = (bitsel + 8'd1) - 8'd1;
MATLAB_Function_out1 = data[bit_idx];
The array indexing issue does remain, due to Verilog being 0-based and MATLAB being 1-based, as you mentioned. The calculation of bit_idx will generate no logic in practice. To get this code all I needed to adjust was to deselect the saturation setting on the MATLAB code. To adjust this, open the file in the MATLAB editor and choose "Edit Data" from the Simulink section of the Edit ribbon.
The flattening of MATLAB Function Blocks into their parent subsystems is controlled globally for a design in HDL Coder. Open the Configuration Parameters dialog and choose the HDL Code Generation pane. Navigate to Global Settings > Coding style. In the "RTL customizations" section, select "Inline MATLAB Function block code".