创建一个4步时钟

时间:2017-10-18 00:32:56

标签: verilog

我试图实现在Verilog中一个接一个地激活的4个时钟信号。我写了一个模块,但我不知道如何为它制作一个测试平台,因为我得到了错误:

error: clk_pc Unable to assign to unresolved wires.

我期待这样的结果:

1000
0100
0010
0001
1000
0100
...

这是模块:

module clock_divisor(input clk0,
                    input clk1,
                    input clk2,
                    input clk3, 
                    output clk0_out,
                    output clk1_out,
                    output clk2_out,
                    output clk3_out);

    reg clk0_out,clk1_out,clk2_out,clk3_out;
    always @(posedge clk0 or posedge clk1 or posedge clk2 or posedge clk3) begin
        if(clk0 == 1)begin
            assign clk0_out = 0;
            assign clk1_out = 1;
            assign clk2_out = 0;
            assign clk3_out = 0;
        end
        else if(clk1 == 1)begin
            assign clk0_out = 0;
            assign clk1_out = 0;
            assign clk2_out = 1;
            assign clk3_out = 0;
        end
        else if(clk2 == 1)begin
            assign clk0_out = 0;
            assign clk1_out = 0;
            assign clk2_out = 0;
            assign clk3_out = 1;
        end
        else if(clk3 == 1)begin
            assign clk0_out = 1;
            assign clk1_out = 0;
            assign clk2_out = 0;
            assign clk3_out = 0;
        end
    end

endmodule

我的测试台:

module testbench();
    reg clk_pc, clk_instruction_memory, clk_alu, clk_registers, reset;
    // Clock Management
    clock_divisor clock_divisor (clk_pc,
                                 clk_instruction_memory, 
                                 clk_alu, 
                                 clk_registers,
                                 clk_pc,
                                 clk_instruction_memory, 
                                 clk_alu, 
                                 clk_registers);
    initial begin
      clk_pc = 1;
    end

    initial
     #500 $finish;


  initial begin
    //$display ("   Pc\tCLK\treset\tCurrent-inst");
    //$monitor("   %d\t%b\t%b\t%h", pc, clk_pc, reset, current_instruction);

    //Monitor Clocks
    $display ("   CLK0\tCLK1\tCLK2\tCLK3");
    $monitor("   %b\t%b\t%b\t%b", clk_pc, clk_instruction_memory, clk_alu, clk_registers);
  end

endmodule 

任何人都可以告诉我为什么我会收到此错误,如何让我的模块按预期工作?

1 个答案:

答案 0 :(得分:1)

(抱歉,我的声誉太低而无法发表评论)

像其他人说的那样,不要在always块中使用过程赋值。顺序元素必须仅具有非阻塞赋值(< =),而组合元素仅阻止赋值(=)。不要在代码块中混合它们。此外,由于始终阻止灵敏度列表中的多个信号,您的设计将不会合成

如果您想同步时钟信号,只需使用其中一个并同步其他信号即可。如果使用4位旋转移位寄存器并将时钟输出分配给移位寄存器中的相应位,这很简单。

移位注册:

module clock_divisor(input clk0,
                input rst_i,
                output clk0_out,
                output clk1_out,
                output clk2_out,
                output clk3_out);

reg [3:0] shift_reg;

always @ (posedge clk0 or negedge rst_i) begin
    if(rst_i) begin
        shift_reg <= 4'd1;
    end
    else begin
        shift_reg <= {shift_reg[2:0], shift_reg[3]};
    end
end

assign clk0_out = shift_reg[0];
assign clk1_out = shift_reg[1];
assign clk2_out = shift_reg[2];
assign clk3_out = shift_reg[3];

endmodule

enter image description here

所有时钟输出的频率与clk0相同!它们只有180°相移。

但如果你真的想制作一个时钟分频器,只需使用一个简单的计数器:

module clock_divisor(input clk0,
                input rst_i,
                output clk0_out,
                output clk1_out,
                output clk2_out,
                output clk3_out);

reg [3:0] counter;

always @ (posedge clk0 or negedge rst_i) begin
    if(rst_i) begin
        counter <= 4'd0;
    end
    else begin
        counter <= counter + 1'd1;
    end
end

assign clk0_out = counter[0];
assign clk1_out = counter[1];
assign clk2_out = counter[2];
assign clk3_out = counter[3];

endmodule

enter image description here

现在,clk_out的频率为:

  • clk0_out = 2 * clk0
  • clk1_out = 4 * clk0
  • clk2_out = 8 * clk0
  • clk3_out = 16 * clk0

希望这能帮到你!

P.S。不要忘记为寄存器添加复位信号!这是至关重要的,因此您的设计可以从已知状态开始。