如何在SV中使用结构体struct语法

前言
测试下可综合的struct,
struct和interface的区别:两者都可以是信号的组合,但interface可以定义信号的不同方向,而struct中的所有信号都是同向的。
struct可对像以太网帧格式进行建模(暂未用到)。

流程
(1)为了对struct进行建模,需要三个模块,顶层,信号输出模块,信号输入模块。
(2)对于结构体的定义可放在模块外部的包里面,单独成一个文件。同时为了避免$unit的问题,使用类似C语法规则的条件编译。
(3)条件编译文件中的内容:文件放在src同级目录即可。
`ifndef DFFS_DONE
    `define DFFS_DONE
    package p_demo;
        typedef struct {
            logic l_clk_50M;
            logic l_clk_100M;
            logic l_rst_50M;
            logic l_rst_100M;
        } t_clk_rst;
    endpackage 
    import p_demo::*;
`endif
(4)顶层:注意需包含定义文件。同时定义结构体变量。实例化genafic和test模块。
`include "definitions.sv"
module demo_sv (
    input     i_clk       ,
    input     i_rst_n     ,
    input     i_a         ,
    output    o_b           
);
t_clk_rst t_gene_top;
genafic  inst_genafic (
    .i_clk             (i_clk),
    .i_rst_n           (i_rst_n),        
    .t_gene            (t_gene_top)
);

test  inst_test (
    .i_a                  (i_a),
    .o_b                  (o_b),
    .t_gene_in            (t_gene_top)
);

endmodule:demo_sv
(5)genafic文件内容:产生了两个时钟和复位。结构体的方向是输出。
`include "definitions.sv"
module genafic (
    input logic i_clk,
    input logic i_rst_n,
    output t_clk_rst t_gene          
);
logic l_locked;
clk_wiz_0  inst_clk_wiz_0 (       
    .clk_out1          (t_gene.l_clk_50M),
    .clk_out2          (t_gene.l_clk_100M),
    .reset             (~i_rst_n),   
    .locked            (l_locked),  
    .clk_in1           (i_clk)  
);

logic l_rst_50M = 1'b1;
logic [9:0] l_cnt_50M = '0;
always_ff @(posedge t_gene.l_clk_50M)
begin
    if (!i_rst_n)
        l_cnt_50M <= '0;
    else if (l_cnt_50M == 'd200)
        l_cnt_50M <= l_cnt_50M;
    else 
        l_cnt_50M <= l_cnt_50M + 'd1;
end
always_ff @(posedge t_gene.l_clk_50M)
begin
    if (!l_locked)
        l_rst_50M <= 1'b1;
    else if (l_cnt_50M == 'd200)
        l_rst_50M <= 1'b0;
end
logic l_rst_100M = 1'b1;
logic [9:0] l_cnt_100M = '0;
always_ff @(posedge t_gene.l_clk_100M)
begin
    if (!i_rst_n)
        l_cnt_100M <= '0;
    else if (l_cnt_100M == 'd200)
        l_cnt_100M <= l_cnt_100M;
    else 
        l_cnt_100M <= l_cnt_100M + 'd1;
end
always_ff @(posedge t_gene.l_clk_100M)
begin
    if (!l_locked)
        l_rst_100M <= 1'b1;
    else if (l_cnt_100M == 'd200)
        l_rst_100M <= 1'b0;
end
assign t_gene.l_rst_50M = l_rst_50M;
assign t_gene.l_rst_100M = l_rst_100M;

endmodule:genafic
(6)test文件内容:使用了50M的时钟,结构体为输入。
`include "definitions.sv"
module test (
    input logic i_a,
    output logic o_b,
    input t_clk_rst t_gene_in
);
logic [9:0] l_cnt_b = '0;
always_ff @(posedge t_gene_in.l_clk_50M)
begin
    if (!t_gene_in.l_rst_50M)
        l_cnt_b <= '0;
    else if (i_a)
        l_cnt_b <= l_cnt_b + 'd1;
end
assign o_b = l_cnt_b[9];

endmodule:test

(7)使用vivado2018.3综合看看结果:
采用结构体对信号进行分组,可实现偷懒以及更佳维护性效果。

以上。

posted @ 2020-08-12 18:56  小翁同学  阅读(1522)  评论(0编辑  收藏  举报