Sorting By Functions in Verilog

Sometimes we’ll want to sort a collection by something other than its natural order. For example, suppose we wanted to sort strings by their length instead of alphabetically. Here’s an example of custom sorts in Verilog.

module sorting_by_functions;

  // Define a string type (not natively supported in Verilog)
  typedef struct {
    reg [7:0] chars [0:15];  // Assuming max length of 16 characters
    integer len;
  } string_t;

  // Define a person type
  typedef struct {
    string_t name;
    integer age;
  } person_t;

  // Function to compare string lengths
  function integer compare_lengths(input string_t a, input string_t b);
    compare_lengths = (a.len < b.len) ? -1 : ((a.len > b.len) ? 1 : 0);
  endfunction

  // Function to compare ages
  function integer compare_ages(input person_t a, input person_t b);
    compare_ages = (a.age < b.age) ? -1 : ((a.age > b.age) ? 1 : 0);
  endfunction

  // Bubble sort implementation (as Verilog doesn't have built-in sorting)
  task sort_strings_by_length(inout string_t fruits[]);
    integer i, j;
    string_t temp;
    for (i = 0; i < $size(fruits) - 1; i = i + 1) begin
      for (j = 0; j < $size(fruits) - i - 1; j = j + 1) begin
        if (compare_lengths(fruits[j], fruits[j+1]) > 0) begin
          temp = fruits[j];
          fruits[j] = fruits[j+1];
          fruits[j+1] = temp;
        end
      end
    end
  endtask

  task sort_people_by_age(inout person_t people[]);
    integer i, j;
    person_t temp;
    for (i = 0; i < $size(people) - 1; i = i + 1) begin
      for (j = 0; j < $size(people) - i - 1; j = j + 1) begin
        if (compare_ages(people[j], people[j+1]) > 0) begin
          temp = people[j];
          people[j] = people[j+1];
          people[j+1] = temp;
        end
      end
    end
  endtask

  initial begin
    // Initialize fruits
    string_t fruits[3];
    fruits[0] = '{"peach", 5};
    fruits[1] = '{"banana", 6};
    fruits[2] = '{"kiwi", 4};

    // Sort fruits by length
    sort_strings_by_length(fruits);
    $display("Sorted fruits: %s, %s, %s", fruits[0].chars, fruits[1].chars, fruits[2].chars);

    // Initialize people
    person_t people[3];
    people[0] = '{'{name: "Jax", len: 3}, 37};
    people[1] = '{'{name: "TJ", len: 2}, 25};
    people[2] = '{'{name: "Alex", len: 4}, 72};

    // Sort people by age
    sort_people_by_age(people);
    $display("Sorted people: %s (%0d), %s (%0d), %s (%0d)",
             people[0].name.chars, people[0].age,
             people[1].name.chars, people[1].age,
             people[2].name.chars, people[2].age);
  end

endmodule

In this Verilog implementation, we’ve had to make several adjustments due to the language differences:

  1. Verilog doesn’t have built-in string types, so we’ve defined a custom string_t struct to represent strings.

  2. There’s no direct equivalent to Go’s slices in Verilog, so we’re using fixed-size arrays.

  3. Verilog doesn’t have built-in sorting functions, so we’ve implemented a simple bubble sort algorithm for both string length sorting and age sorting.

  4. The compare_lengths and compare_ages functions return -1, 0, or 1 to indicate less than, equal to, or greater than, similar to Go’s cmp.Compare.

  5. We’ve used Verilog’s initial block to set up and run our sorting operations, which is somewhat analogous to Go’s main function in this context.

  6. The $display function is used to output results, similar to Go’s fmt.Println.

Note that this Verilog code is more of a simulation and wouldn’t be synthesizable as-is. In real hardware design, sorting would typically be implemented differently, often using dedicated sorting networks or other hardware-friendly algorithms.