3
\$\begingroup\$

There are both a simple byte endian (little and big) order swapper and its testbench. A data stream inputs to the module and is converted to the other endianness by computational logic.

byte_order_swap.v

`timescale 1ns / 1ps

module byte_order_swap #
(
    parameter integer DATA_WIDTH = 32
)
(
    input wire [DATA_WIDTH - 1 : 0] data_i,
    input wire [DATA_WIDTH - 1 : 0] data_o
);
    localparam integer DATA_BYTE_NUMBER = DATA_WIDTH / 8;
    localparam integer DEC_DATA_WIDTH   = DATA_WIDTH - 1;

    generate
        genvar i;
        if (0 == (DATA_WIDTH % 4)) begin
            for(i = 0; i < DATA_BYTE_NUMBER; i = i + 1) begin
                assign data_o[(i * 8) +: 8] = data_i[(DEC_DATA_WIDTH - i * 8)  -: 8];
            end
        end
        else begin
            assign data_o = {DATA_WIDTH{1'h0}};
        end
    endgenerate

endmodule

byte_order_swap_tb.v

`timescale 1ns / 1ps

module byte_order_swap_tb;

    localparam integer              DATA_WIDTH          = 32;
    localparam integer              CLOCK_PERIOD        = 100;
    localparam integer              ITERATION_NUMBER    = 1000;
    localparam [DATA_WIDTH - 1 : 0] COUNTER_START_VALUE = 32'hAABB1122;
    
    wire [DATA_WIDTH - 1 : 0] counter_swap_value;
    
    reg                      clk;
    reg [DATA_WIDTH - 1 : 0] counter_dir_value;

    byte_order_swap #
    (
        .DATA_WIDTH (DATA_WIDTH)
    )
    byte_order_swap_dut
    (
        .data_i (counter_dir_value),
        .data_o (counter_swap_value)
    );
    
    initial begin
        clk = 1'h0;
 
        forever begin
            #( CLOCK_PERIOD / 2 ) clk = !clk;
        end 
    end
    
    initial begin
        counter_dir_value <= COUNTER_START_VALUE;
    
        repeat(ITERATION_NUMBER) begin
            @(posedge clk);
            counter_dir_value <= counter_dir_value + 1'h1;
        end
    end
    
    task check_swap;
    begin
        repeat(ITERATION_NUMBER) begin
            @(posedge clk);
            $display("A direction value:  %h -> the swap value: %h",counter_dir_value, counter_swap_value, $time);
        end
    end
    endtask
    
    initial begin
    
        check_swap;
        
        $stop();
    end

endmodule
\$\endgroup\$
0
1
\$\begingroup\$

The code makes good use of parameters. However, I see a potential problem.

    if (0 == (DATA_WIDTH % 4)) begin

That code seems to imply that any multiple of 4 is supported. But, if I try DATA_WIDTH = 20, then I see z values in the output. Perhaps you should restrict values to be a multiple of 8 instead:

    if (0 == (DATA_WIDTH % 8)) begin

Conventionally, the word "check" means that you will compare an actual value to an expected value and report an error if the two do not match. The check_swap task simply displays the values. If that is all you are looking to do, then I suggest renaming the task as display_swap or monitor_swap.

However, you could add code to the testbench to do a comparison. If your tool suite supports SystemVerilog features, then the following additions/modifications would provide automatic checking:

wire [DATA_WIDTH - 1 : 0] data_o;
generate
    if (0 == (DATA_WIDTH % 8)) begin
        assign data_o = {<< 8{counter_dir_value}};
    end else begin
        assign data_o = '0;
    end
endgenerate

task check_swap;
    repeat(ITERATION_NUMBER) begin
        @(posedge clk);
        $display("A direction value:  %h -> the swap value: %h", counter_dir_value, counter_swap_value, $time);
        if (data_o !== counter_swap_value) begin
            $display("ERROR: data miscompare", $time);
        end
    end
endtask

To create the expected data (data_o), I copied the generate code from the design and made some simplifications. The {<< 8{counter_dir_value}} syntax is another way to perform the byte swap. Refer to IEEE Std 1800-2017, section 11.4.14 Streaming operators (pack/unpack). The '0 syntax is a simplified way of assigning all bits to 0, equivalent to what you have already. If you plan to synthesize the design, and your tool chain supports this syntax, you could even use this code in your design module.

A minor note: with that type of task body, the begin/end keywords are now optional.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Thank you for the reply. Your criticism and rectification of my code are very important for me. Sorry for the late answer. \$\endgroup\$
    – Drakonof
    Mar 18 at 7:15
  • \$\begingroup\$ @drakonof I'm glad to help. \$\endgroup\$
    – toolic
    Mar 18 at 14:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.