led跑马灯多种方法(移位法,位拼接法,调用模块法,位移及位拼接语法,testbench的理解,源文件的存储路径,计数器的个数,调用模块的方式)
阅读原文时间:2023年07月09日阅读:1

  跟着教程写了几种方法,才发现自己写的虽然能实现,但比较繁琐。教程有三种方法:

1.移位法,每次左移一位,相比我自己写的,优点是不用把每一种情况都写出来。但是需要考虑左移到最后一位时需要自己再写个赋值语句重新回到第一位。

2.位拼接法,循环左移,每一次都把最后一位放到第一位,其他六位左移一位,克服了移位法的问题,简化了代码。

3.调用已有模块法,调用4-16译码器刚好可以实现流水灯,需要额外的counter作为译码器的输入。

  • 移位法

module led_run1( //移位法
clk,
reset,
led
);
input clk;
input reset;
output reg [7:0]led;

reg \[5:0\]counter1;  
always@( posedge clk or negedge reset )begin  
    if( reset == 1'd0)  
    counter1 <= 1'd0;  
    else if(counter1 == 4 )    这两个虽然赋值语句一样,但是不能把判断语句合并。  
    counter1 <=1'd0;  
    else  
    counter1 <= counter1 + 1'd1;  
end

always@(posedge clk or negedge reset) begin  
    if( reset == 1'd0)  
    led <= 8'b0000\_0001;  
    else if(counter1 == 4 )begin  
        if(led == 8'b1000\_0000)  
        led <= 8'b0000\_0001;      //最后一位的处理  
        else  
        led <= led << 1'd1 ;      //注意左移几位的语法,应该怎么写  
    end  
end  

endmodule

  • 位拼接法

module led_run2( //位拼接法
clk,
reset,
led
);
input clk;
input reset;
output reg [7:0]led;

reg \[5:0\]counter1;  
always@( posedge clk or negedge reset )begin  
    if( reset == 1'd0)  
    counter1 <= 1'd0;  
    else if(counter1 == 4 )  
    counter1 <=1'd0;  
    else  
    counter1 <= counter1 + 1'd1;  
end

always@(posedge clk or negedge reset) begin  
    if( reset == 1'd0)  
    led <= 8'b0000\_0001;  
    else if(counter1 == 4 )begin  
        led <= {led\[6:0\],led\[7\]};    //位拼接的语法,十分注意  

end
end
endmodule

  • 调用模块法

module led_run4( //调用模块4-16译码器法
clk,
reset,
led
);
input clk;
input reset;
output wire [15:0]led;

reg \[2:0\]counter1;  
reg \[3:0\]counter4;    一个用来计数,一个用来译码  
always@( posedge clk or negedge reset )begin  
    if( reset == 1'd0)  
    counter1 <= 1'd0;  
    else if(counter1 == 4 )  
    counter1 <=1'd0;  
    else  
    counter1 <= counter1 + 1'd1;  
end

always@(posedge clk or negedge reset) begin  
    if( reset == 1'd0)  
    counter4 <= 8'd1;  
    else if(counter1 == 4 )begin  
    counter4 <= counter4 + 1'b1;  
    end  
end

decoder\_4\_16 decoder\_4\_16\_run(        //调用的方法类似于仿真时的例化,存储电路与组合逻辑电路相结合。  
           .a(counter4\[3\]),  
           .b(counter4\[2\]),  
           .c(counter4\[1\]),  
           .d(counter4\[0\]),  
           .out(led)  
    );

endmodule

注意:

1.左移/右移的语法:led=led << n   /   led=led >> n

2.位拼接的语法:led={led[6:0],led[7]} 注意花括号,中括号,数组表达方式。定义时中括号放名字前,引用时放名字后。逗号隔开位。

3.一个testbench可以用来测试验证多个模块,需要修改的是tb里面例化的模块名,激励如果一样可以不修改。(testbench差不多就是个激励产生器用来验证性能)

4.在工程中创建的design sources的源文件的路径为:.srcs->sources->new->xx.v

5.时序电路自少需要一个计数器来控制开发板时钟信号和我们实际需要的周期信号的关系。但是不是说只能有一个,可以根据需求增加。

6.报错:ordered port connections cannot be mixed with named port connections  目标端口连接不能与命名端口连接混合

  

  原因:最后一个变量后面加了逗号,删掉即可。

7.调用子模块的方式:

  7.1把子模块的文件复制到当前工程的design源文件目录下,路径上面有写。

  7.2在vivado中添加该文件进design sources,作为子模块。

  7.3在顶层文件(即要调用该子文件的文件)调用子模块,方式是类似于testbench的例化。注意,在子模块(底层)中定义了输出为reg型,在顶层应该定义输出为wire型。

    效果

   

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章