天天看点

关于组合逻辑和时序逻辑自己的一点理解

module r_g_b(    //颜色控制模块
//端口信号:模块的输入输出接口
    input           clk,   //连接至分频时钟,为40MHz
    input       rst_n, //低电平复位
    input       en_zx,  //红色使能信号

    output [:]  vga_r, //红色(3位:根据数值的变化,控制颜色的深浅)
    output [:]  vga_g, //绿色(3位:根据数值的变化,控制颜色的深浅)
    output [:]  vga_b  //蓝色(2位:根据数值的变化,控制颜色的深浅)
    );

wire [:]  data;  //rom取出的值寄存器
reg  [:]  cnt_ad;//rom地址控制信号
reg  [:]  cnt_zx;//对应一个数据的8位相应的计数信号

//例化调用rom       
rom rom(
    .address(cnt_ad),
    .clock(clk),
    .q(data)
    );

//通过计数器取地址0-63
wire  en_ad;  //地址变化的使能信号:每取完一个8位数据后,地址加1,从而取下一个8位数据
always@(posedge clk or negedge rst_n)
    if(!rst_n)
            cnt_zx <= ;
    else if(en_zx)
                begin
                    if(cnt_zx == )
                        cnt_zx <= ;
                    else
                        cnt_zx <= cnt_zx + 'b1;    
                end
    else
            cnt_zx <= ;

assign  en_ad = (cnt_zx == )?'b1:'b0;    //当计数到5时,将信号拉高一个时钟,那么en_ad作为地址计数的使能信号,驱支cnt_ad在下一个时钟,(即cnt_zx==6)时地址加1,
                                                        //地址控制信号cnt_ad又在下一个时钟(cnt_zx==7)时传入rom (这是常见的时序问题,值得思考一下)

//在使能信号en_ad为高电平时地址加1
always@(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt_ad <= ;
    else if(cnt_ad <= )
             begin
                if(en_ad)
                    cnt_ad <= cnt_ad + 'b1;    
             end
    else
        cnt_ad <= ;


//在使能区域内,通过查找表的方式,把数据的8位依次从低到高取出                    
reg vga_r_r;
always@(*)
    if(en_zx)
    case(cnt_zx)
        : vga_r_r <= data[];  //取第0位
        : vga_r_r <= data[];  //取第1位
        : vga_r_r <= data[];  //取第2位
        : vga_r_r <= data[];  //取第3位
        : vga_r_r <= data[];  //取第4位
        : vga_r_r <= data[];  //取第5位
        : vga_r_r <= data[];  //取第6位
        : vga_r_r <= data[];  //取第7位
        default:;
    endcase 

//将1位数据通过拼接符号组合成3位数据:增加颜色的深度
assign vga_r = (en_zx)?{{vga_r_r}}:'b000;//在32*16的有效区域内字符用红色表示
assign vga_g = 'b000;
assign vga_b = 'b00; 
endmodule
           

其中“//当计数到5时,将信号拉高一个时钟,那么en_ad作为地址计数的使能信号,驱支cnt_ad在下一个时钟,(即cnt_zx==6)时地址加1,

//地址控制信号cnt_ad又在下一个时钟(cnt_zx==7)时传入rom (这是常见的时序问题,值得思考一下)”这里原来的作者写的有问题 assign的组合逻辑可以完全换成

always@(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt_ad <= ;
    else if(cnt_ad <= )
             begin
                if(cnt_zx == )
                    cnt_ad <= cnt_ad + 'b1;    
             end
    else
        cnt_ad <= ;
           

这和原来的完全等同,但是cnt_ad加一是发生在cnt_zx==5时,在cnt_zx==6时,cnt_ad已经加一了。已经将加一后的cnt_ad传给rom,在cnt_zx==7时将最新的数据从rom中传递出来,同时在这个时刻vga_r_r 读取data[7]的数据。

附上RTL视图

关于组合逻辑和时序逻辑自己的一点理解

从RTL视图中可以看出,在zx_cnt==5时完成cnt_ad加一操作采用组合逻辑直接完成,在zx_cnt==6时传递cnt_ad加一后的数值通过一个d触发器将数据传递给rom。在zx_cnt==7时rom将数据传递出来,更新data[7:0]。

继续阅读