0

以下是我的顶级模块:

module spwm(clk, p1, sine_a, tri_out);

input clk;      //16MHz
reg tick = 0;

reg  [7:0] theta_a = 8'd0;
reg  [7:0] theta_tri = 8'd0;
output [8:0] sine_a;
output [9:0] tri_out;

integer div = 42;
integer r = 0;

output p1;
reg p1;


always@(posedge clk) begin
    if(r == div) begin
        tick = ~tick;
        r = 1;
    end
    else begin
        r = r + 1;
    end
end

always@(tick) begin
    theta_a = (theta_a + 8'b1) % 8'd255;
end


always@(posedge clk) begin
    theta_tri = (theta_tri + 8'b1) % 8'd255;
end

//generate spwm
always@(clk) begin
    if ($signed(sine_a) > $signed(tri_out))
        p1 = 1'b1;
    else if ($signed(sine_a) < $signed(tri_out))
        p1 = 1'b0;
                
end

SINE_LUT lut_a(theta_a, sine_a);
TRI_LUT lut_tri(theta_tri, tri_out);
endmodule

我的正弦波查找表:

module SINE_LUT (THETA, SINE_OUT);

input  [7:0] THETA;         //Input THETA
output [8:0] SINE_OUT;      //Output SINE_OUT

reg [5:0] THETA_TMP;        //Lower bits of THETA (counting up or counting down)
reg [6:0] THETA_HLP;        //Helper for reversing lower bits of counting direction for theta
reg [8:0] SINE_TMP;         //Temporary holder for output (two's compliment)
reg [8:0] SINE_OUT;         //Output Sine in two's compliment

always @ (THETA) begin                      //Combinatorial Logic Look Up Table

    if (THETA[6:0] == 7'd64) begin          //At 90 degrees and 270 degrees
        SINE_TMP = 9'd255;
    end
    else begin
        if (THETA[6]) begin                 //If counting down should begin reverse counting order
            THETA_HLP = 7'd64 - {1'd0, THETA[5:0]};
            THETA_TMP = {THETA_HLP[5:0]};
        end
        else begin                          //Continue counting up by default
            THETA_TMP = {THETA[5:0]};
        end
        case (THETA_TMP)                    //Look Up Table (quarter wave)
        6'd0: SINE_TMP = 9'd0;
        6'd1: SINE_TMP = 9'd6;
        6'd2: SINE_TMP = 9'd13;
        6'd3: SINE_TMP = 9'd19;
        6'd4: SINE_TMP = 9'd25;
        6'd5: SINE_TMP = 9'd31;
        6'd6: SINE_TMP = 9'd37;
        6'd7: SINE_TMP = 9'd44;
        6'd8: SINE_TMP = 9'd50;
        6'd9: SINE_TMP = 9'd56;
        6'd10: SINE_TMP = 9'd62;
        6'd11: SINE_TMP = 9'd68;
        6'd12: SINE_TMP = 9'd74;
        6'd13: SINE_TMP = 9'd80;
        6'd14: SINE_TMP = 9'd86;
        6'd15: SINE_TMP = 9'd92;
        6'd16: SINE_TMP = 9'd98;
        6'd17: SINE_TMP = 9'd103;
        6'd18: SINE_TMP = 9'd109;
        6'd19: SINE_TMP = 9'd115;
        6'd20: SINE_TMP = 9'd120;
        6'd21: SINE_TMP = 9'd126;
        6'd22: SINE_TMP = 9'd131;
        6'd23: SINE_TMP = 9'd136;
        6'd24: SINE_TMP = 9'd142;
        6'd25: SINE_TMP = 9'd147;
        6'd26: SINE_TMP = 9'd152;
        6'd27: SINE_TMP = 9'd157;
        6'd28: SINE_TMP = 9'd162;
        6'd29: SINE_TMP = 9'd167;
        6'd30: SINE_TMP = 9'd171;
        6'd31: SINE_TMP = 9'd176;
        6'd32: SINE_TMP = 9'd180;
        6'd33: SINE_TMP = 9'd185;
        6'd34: SINE_TMP = 9'd189;
        6'd35: SINE_TMP = 9'd193;
        6'd36: SINE_TMP = 9'd197;
        6'd37: SINE_TMP = 9'd201;
        6'd38: SINE_TMP = 9'd205;
        6'd39: SINE_TMP = 9'd208;
        6'd40: SINE_TMP = 9'd212;
        6'd41: SINE_TMP = 9'd215;
        6'd42: SINE_TMP = 9'd219;
        6'd43: SINE_TMP = 9'd222;
        6'd44: SINE_TMP = 9'd225;
        6'd45: SINE_TMP = 9'd228;
        6'd46: SINE_TMP = 9'd231;
        6'd47: SINE_TMP = 9'd233;
        6'd48: SINE_TMP = 9'd236;
        6'd49: SINE_TMP = 9'd238;
        6'd50: SINE_TMP = 9'd240;
        6'd51: SINE_TMP = 9'd242;
        6'd52: SINE_TMP = 9'd244;
        6'd53: SINE_TMP = 9'd246;
        6'd54: SINE_TMP = 9'd247;
        6'd55: SINE_TMP = 9'd249;
        6'd56: SINE_TMP = 9'd250;
        6'd57: SINE_TMP = 9'd251;
        6'd58: SINE_TMP = 9'd252;
        6'd59: SINE_TMP = 9'd253;
        6'd60: SINE_TMP = 9'd254;
        6'd61: SINE_TMP = 9'd254;
        6'd62: SINE_TMP = 9'd255;
        6'd63: SINE_TMP = 9'd255;

        endcase
    end

    if (THETA > 8'd128) begin               //Any theta between 180 and 360 degrees should be negative
        SINE_OUT = (~SINE_TMP) + 1'd1;      //Create negative value in two's compliment
    end
    else begin                              //Any theta between 0 and 180 degrees should be positive
        SINE_OUT = SINE_TMP;
    end

end

endmodule

我还使用三角波查找表:

module TRI_LUT (THETA, TRI_OUT);

input  [7:0] THETA;         
output [9:0] TRI_OUT;       

reg [5:0] THETA_TMP;        
reg [6:0] THETA_HLP;        
reg [9:0] TRI_TMP;          
reg [9:0] TRI_OUT;          

always @ (THETA) begin          

    if (THETA[6:0] == 7'd64) begin  
        TRI_TMP = 10'd364;
    end
    else begin
        if (THETA[6]) begin             
            THETA_HLP = 7'd64 - {1'd0, THETA[5:0]};
            THETA_TMP = {THETA_HLP[5:0]};
        end
        else begin                  
            THETA_TMP = {THETA[5:0]};
        end
        case (THETA_TMP)            
            6'd0: TRI_TMP = 10'd0;
            6'd1: TRI_TMP = 10'd6;
            6'd2: TRI_TMP = 10'd12;
            6'd3: TRI_TMP = 10'd17;
            6'd4: TRI_TMP = 10'd23;
            6'd5: TRI_TMP = 10'd29;
            6'd6: TRI_TMP = 10'd35;
            6'd7: TRI_TMP = 10'd40;
            6'd8: TRI_TMP = 10'd46;
            6'd9: TRI_TMP = 10'd52;
            6'd10: TRI_TMP = 10'd58;
            6'd11: TRI_TMP = 10'd64;
            6'd12: TRI_TMP = 10'd69;
            6'd13: TRI_TMP = 10'd75;
            6'd14: TRI_TMP = 10'd81;
            6'd15: TRI_TMP = 10'd87;
            6'd16: TRI_TMP = 10'd92;
            6'd17: TRI_TMP = 10'd98;
            6'd18: TRI_TMP = 10'd104;
            6'd19: TRI_TMP = 10'd110;
            6'd20: TRI_TMP = 10'd116;
            6'd21: TRI_TMP = 10'd121;
            6'd22: TRI_TMP = 10'd127;
            6'd23: TRI_TMP = 10'd133;
            6'd24: TRI_TMP = 10'd139;
            6'd25: TRI_TMP = 10'd144;
            6'd26: TRI_TMP = 10'd150;
            6'd27: TRI_TMP = 10'd156;
            6'd28: TRI_TMP = 10'd162;
            6'd29: TRI_TMP = 10'd168;
            6'd30: TRI_TMP = 10'd173;
            6'd31: TRI_TMP = 10'd179;
            6'd32: TRI_TMP = 10'd185;
            6'd33: TRI_TMP = 10'd191;
            6'd34: TRI_TMP = 10'd196;
            6'd35: TRI_TMP = 10'd202;
            6'd36: TRI_TMP = 10'd208;
            6'd37: TRI_TMP = 10'd214;
            6'd38: TRI_TMP = 10'd220;
            6'd39: TRI_TMP = 10'd225;
            6'd40: TRI_TMP = 10'd231;
            6'd41: TRI_TMP = 10'd237;
            6'd42: TRI_TMP = 10'd243;
            6'd43: TRI_TMP = 10'd248;
            6'd44: TRI_TMP = 10'd254;
            6'd45: TRI_TMP = 10'd260;
            6'd46: TRI_TMP = 10'd266;
            6'd47: TRI_TMP = 10'd272;
            6'd48: TRI_TMP = 10'd277;
            6'd49: TRI_TMP = 10'd283;
            6'd50: TRI_TMP = 10'd289;
            6'd51: TRI_TMP = 10'd295;
            6'd52: TRI_TMP = 10'd300;
            6'd53: TRI_TMP = 10'd306;
            6'd54: TRI_TMP = 10'd312;
            6'd55: TRI_TMP = 10'd318;
            6'd56: TRI_TMP = 10'd324;
            6'd57: TRI_TMP = 10'd329;
            6'd58: TRI_TMP = 10'd335;
            6'd59: TRI_TMP = 10'd341;
            6'd60: TRI_TMP = 10'd347;
            6'd61: TRI_TMP = 10'd352;
            6'd62: TRI_TMP = 10'd358;
            6'd63: TRI_TMP = 10'd364;

        endcase
    end

    if (THETA > 8'd128) begin
        TRI_OUT = (~TRI_TMP) + 1'd1;
    end
    else begin                      
        TRI_OUT = TRI_TMP;
    end

end

endmodule

上述 SPWM 在 ModelSim PE Student Edition 10.3 中有效。 在此处输入图像描述

当加载到 GFEC Max II 入门套件中时,信号 p1 未被调制。任何帮助。谢谢...

4

1 回答 1

1

theta_a并且p1正在推断锁存逻辑。这通常综合为大、复杂、脆弱的逻辑。制作人字拖应该可以解决您的问题。

always@(posedge clk) begin
    if(r == div) begin
        //tick <= ~tick; // tick can be optimized out
        theta_a <= (theta_a + 8'b1) % 8'd255; // theta_a is flopped
        r <= 1;
    end
    else begin
        r <= r + 1;
    end
end

always@(posedge clk) begin
    theta_tri <= (theta_tri + 8'b1) % 8'd255;
end

//generate spwm
always@(posedge clk) begin // latch to flip-flop
    if ($signed(sine_a) > $signed(tri_out))
        p1 <= 1'b1;
    else if ($signed(sine_a) < $signed(tri_out))
        p1 <= 1'b0;
end

仅供参考:您可能还想检查您的SINE_LUTand中是否有闩锁TRI_LUT。如果您的合成器有一个不错的优化阶段,那么THETA_HLP并且THETA_TMP将是组合逻辑。蛮力合成器可以创建闩锁。为了保证组合逻辑,请确保THETA_HLPTHETA_TMP始终分配一个值。

兑换:

if (THETA[6:0] == 7'd64) begin
    ...
end
else begin
    if (THETA[6]) begin
        THETA_HLP = 7'd64 - {1'd0, THETA[5:0]};
        THETA_TMP = {THETA_HLP[5:0]};
    end
    else begin
        THETA_TMP = {THETA[5:0]};
    end
    case (THETA_TMP)
    ...
    endcase
end

至:

THETA_HLP = 7'd64 - {1'd0, THETA[5:0]};
THETA_TMP = THETA[6] ? THETA_HLP[5:0] : THETA[6];
if (THETA[6:0] == 7'd64) begin
    ... 
end
else begin
    case (THETA_TMP)
    ...
    endcase
end

THETA_HLP并且THETA_TMP被连续分配组合逻辑并且在功能上等同于您的原始。

于 2014-04-03T22:23:25.990 回答