Void Star
Void Star

Reputation: 2521

Pipelined design issues with Verilog

I just started learning Verilog because I bought an FPGA. Since I don't have my FPGA yet, I started off with a somewhat big project, just to see where I get. I may have bitten off more than I can chew on this one, but I am trying to make a simple pipelined CORDIC module. The problem I am having in simulation here is that values will propagate from the testbench's input to uut, the unit under test, an instance of cordic rotator, those signals propagate to the first stage in the pipeline, xpipe[0], ypipe[0], zpipe[0], then to a cordic_stage instance, but the outputs of this cordic_stage instance do not seem to be changing any values in the xpipe[1], ypipe[1], or zpipe[1] registers, they remain at zzzz. Now I'm sure there's a million and one things wrong with my modules here, but I want to figure them out on my own. What I do want to know is why the values aren't making it out of the cordic_stage into the next element in the pipelines' arrays, and how I can fix it. Here is my code below:

module cordic_stage #(
    parameter ANGLE_WIDTH = 16,
    parameter VALUE_WIDTH = 8,
    parameter STAGE_I = 0
    )(
    input clk,
    input [VALUE_WIDTH-1:0] xin,
    input [VALUE_WIDTH-1:0] yin,
    input [ANGLE_WIDTH-1:0] zin,
    output reg [VALUE_WIDTH-1:0] xout,
    output reg [VALUE_WIDTH-1:0] yout,
    output reg [ANGLE_WIDTH-1:0] zout
    );
    parameter DELTA = 1 << (ANGLE_WIDTH - 2);
    always @(posedge clk) begin
        if (zin[ANGLE_WIDTH-1]) begin
            xout <= xin + (yin >> STAGE_I); // These assignments to outputs are WORKING
            yout <= yout - (xin >> STAGE_I);
            zout <= zin + (DELTA >> STAGE_I);
        end else begin
            xout <= xin - (yin >> STAGE_I);
            yout <= yout + (xin >> STAGE_I);
            zout <= zin - (DELTA >> STAGE_I);
        end
    end
endmodule

module cordic_rotator #(
    parameter ANGLE_WIDTH = 16,
    parameter VALUE_WIDTH = 8
    )(
    input clk,
    input [ANGLE_WIDTH-1:0] angle,
    input [VALUE_WIDTH-1:0] xin,
    input [VALUE_WIDTH-1:0] yin,
    output [VALUE_WIDTH-1:0] xout,
    output [VALUE_WIDTH-1:0] yout
    );
    reg [VALUE_WIDTH-1:0] xpipe [ANGLE_WIDTH:0]; // The second element in these pipelines arrays at index 1 never gets changed, so that it NOT WORKING
    reg [VALUE_WIDTH-1:0] ypipe [ANGLE_WIDTH:0];
    reg [ANGLE_WIDTH-2:0] zpipe [ANGLE_WIDTH:0];
    always @(*) begin
        xpipe[0] <= angle[ANGLE_WIDTH-1] ? -xin : xin; // These assignments to the first element in the pipeline are WORKING
        ypipe[0] <= angle[ANGLE_WIDTH-1] ? -yin : yin;
        zpipe[0] <= angle[ANGLE_WIDTH-2:0];
    end
    genvar i;
    generate
        for (i = 0; i < ANGLE_WIDTH; i = i + 1) begin: stages
            cordic_stage #(ANGLE_WIDTH-1, VALUE_WIDTH, i) stage(clk, xpipe[i], ypipe[i], zpipe[i], xpipe[i+1], ypipe[i+1], zpipe[i+1]); // Values are being passed from the first stage in the pipeline at index zero to the first cordic_stage module, so that is WORKING
        end
    endgenerate 
endmodule

module cordic_rotator_testbench;

    // Inputs
    reg clk;
    reg [3:0] angle;
    reg [3:0] xin;
    reg [3:0] yin;

    // Outputs
    wire [3:0] xout;
    wire [3:0] yout;

    // Instantiate the Unit Under Test (UUT)
    cordic_rotator #(4,4) uut (
        .clk(clk), 
        .angle(angle), 
        .xin(xin), 
        .yin(yin), 
        .xout(xout), 
        .yout(yout)
    );

    initial begin
        // Initialize Inputs
        clk = 0;
        angle = 0;
        xin = 0;
        yin = 0;

        // Wait 100 ns for global reset to finish
        #100;

        // Add stimulus here

        assign angle = 2; // These lines are also WORKING
        assign xin = 8;
        assign yin = 0;

    end

    always #5 clk = !clk; 

endmodule

Upvotes: 1

Views: 1108

Answers (1)

Tim
Tim

Reputation: 35933

You are driving a register xpipe, directly from an output wire of a module, I would have thought that would be a syntax error, as register types are only supposed to be driven in procedural blocks.

You might try changing the xyzpipe types from reg to wire, since wire types are what are supposed to be driven by module outputs.

Addendum by OP: Code in cordic_rotator is changed for wire types, this fixes the problem.

wire [VALUE_WIDTH-1:0] xpipe [ANGLE_WIDTH:0];
wire [VALUE_WIDTH-1:0] ypipe [ANGLE_WIDTH:0];
wire [ANGLE_WIDTH-2:0] zpipe [ANGLE_WIDTH:0];
assign xpipe[0] = angle[ANGLE_WIDTH-1] ? -xin : xin;
assign ypipe[0] = angle[ANGLE_WIDTH-1] ? -yin : yin;
assign zpipe[0] = angle[ANGLE_WIDTH-2:0];

Upvotes: 1

Related Questions