FPGA project : example_ram

发布时间:2023年12月20日

?

?

?

module ram_ctrl
#(
    parameter CNT_MAX = 24'd9_999_999
)(
    input           wire            sys_clk     ,
    input           wire            sys_rst_n   ,
    input           wire            wr_flag     ,
    input           wire            rd_flag     ,

    output          reg             wr_en       , // write enable
    output          reg    [7:0]    addr        , // 单端口 ram 读写 共用一个地址线
    output          reg    [7:0]    wr_data     , // write data
    output          reg             rd_en         // read enable
);

    // reg signal define
    reg     [23:00]     cnt_200ms ;

    // cnt_200ms
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_200ms <= 24'd0 ;
        end else begin
            if(rd_flag == 1'b1) begin
                cnt_200ms <= 24'd0 ;
            end else begin
                if(rd_en == 1'b1 && cnt_200ms == CNT_MAX || wr_flag == 1'b1) begin
                    cnt_200ms <= 24'd0 ;
                end else begin
                    if(rd_en == 1'b1) begin
                        cnt_200ms <= cnt_200ms + 1'b1 ; 
                    end else begin
                        cnt_200ms <= 24'd0 ;
                    end
                end
            end
        end
    end
    // wr_en    
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            wr_en <= 1'b0 ;
        end else begin
            if(wr_flag == 1'b1) begin
                wr_en <= 1'b1 ;
            end else begin
                if(addr == 8'd255) begin
                    wr_en <= 1'b0 ;
                end else begin
                    wr_en <= wr_en ;
                end
            end
        end
    end
    // rd_en  
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            rd_en <= 1'b0 ;
        end else begin
            if(rd_flag == 1'b1 && wr_en <= 1'b0) begin
                rd_en <= 1'b1 ;
            end else begin
                if(rd_en == 1'b1 && wr_flag == 1'b1) begin
                    rd_en <= 1'b0 ;
                end else begin
                    rd_en <= rd_en ;
                end
            end
        end
    end
    // addr     
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            addr <= 8'd0 ;
        end else begin
            if(wr_flag == 1'b1) begin
                addr <= 8'd0 ;
            end else begin
                if(wr_en == 1'b1) begin
                    if(addr == 8'd255) begin
                        addr <= 8'd0 ;
                    end else begin
                        addr <= addr + 1'b1 ;
                    end
                end else begin
                    if(rd_flag == 1'b1) begin
                        addr <= 8'd0 ;
                    end else begin
                        if(rd_en == 1'b1 && cnt_200ms == CNT_MAX) begin
                            if(addr == 8'd255) begin
                                addr <= 8'd0 ;
                            end else begin
                                addr <= addr + 1'b1 ;
                            end
                        end else begin
                            if(rd_en == 1'b1) begin
                                addr <= addr ;
                            end else begin
                                addr <= 8'd0 ;
                            end
                        end
                    end
                end
            end
        end
    end
    // wr_data  不存在 在一次写操作期间内 按下第二次写按键与读按键的可能
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            wr_data <= 8'd0 ;
        end else begin
            if(wr_flag == 1'b1) begin
                wr_data <= 8'd0 ;
            end else begin
                if(wr_en == 1'b1) begin
                    if(wr_data == 8'd255) begin
                        wr_data <= 8'd0 ;
                    end else begin
                        wr_data <= wr_data + 1'b1 ;
                    end
                end 
            end
        end
    end
  
endmodule
module top(
    input           wire                sys_clk     ,
    input           wire                sys_rst_n   ,
    input           wire                wr_key      ,
    input           wire                rd_key      ,

    output          wire                ds          ,
    output          wire                oe          ,
    output          wire                shcp        ,
    output          wire                stcp    
);

    //
    wire    [1:0]       key_out_w   ;

    wire                wr_en_w     ;   
    wire    [7:0]       addr_w      ;    
    wire    [7:0]       wr_data_w   ; 
    wire                rd_en_w     ; 
    
    wire    [7:0]       q_w         ;  

    wire    [19:00]q_w_20 ;
    assign  q_w_20 = { 12'd0 , q_w} ;
        
    wire    [05:00]     point_w     ; 
    wire                sign_w      ;  
    wire                seg_en_w    ;
    assign              point_w  = 5'd0 ;
    assign              sign_w   = 1'b0 ;
    assign              seg_en_w = 1'b1 ;

key_filter
#(
    .MAX_CNT_20MS (20'd999_999),//50
    .SIZE         (2 )
)
key_filter_insert(
    .sys_clk                        ( sys_clk         ) ,
    .sys_rst_n                      ( sys_rst_n       ) ,
    .key_in                         ( {rd_key,wr_key} ) ,

    .key_out                        ( key_out_w       )  
);

ram_ctrl
#(
    .CNT_MAX                        (24'd9_999_999)        //20
)
ram_ctrl_insert(
    .sys_clk                        ( sys_clk         ) ,
    .sys_rst_n                      ( sys_rst_n       ) ,
    .wr_flag                        ( key_out_w[0]    ) ,
    .rd_flag                        ( key_out_w[1]    ) ,

    .wr_en                          ( wr_en_w         ) ,
    .addr                           ( addr_w          ) ,
    .wr_data                        ( wr_data_w       ) ,
    .rd_en                          ( rd_en_w         )  
);

ram_8x256	ram_8x256_inst (
	.aclr                           ( ~sys_rst_n ),
	.address                        ( addr_w     ),
	.clock                          ( sys_clk    ),
	.data                           ( wr_data_w  ),
	.rden                           ( rd_en_w    ),
	.wren                           ( wr_en_w    ),

	.q                              ( q_w        )
);

seg_595_dynamic seg_595_dynamic_insert(
    .sys_clk                        ( sys_clk    ) ,
    .sys_rst_n                      ( sys_rst_n  ) ,
    .data                           ( q_w_20     ) ,
    .point                          ( point_w    ) ,
    .sign                           ( sign_w     ) ,
    .seg_en                         ( seg_en_w   ) ,

    .ds                             ( ds         ) ,
    .oe                             ( oe         ) ,
    .shcp                           ( shcp       ) ,
    .stcp                           ( stcp       )    
);

endmodule
module key_filter
#(
    parameter MAX_CNT_20MS = 20'd999_999 ,
              SIZE         = 2
)(
    input           wire            sys_clk     ,
    input           wire            sys_rst_n   ,
    input           wire    [SIZE - 1:0]   key_in      ,

    output          reg     [SIZE - 1:0]   key_out  
);
    // reg signal define
    reg     [SIZE - 1:0]       key_r0  ;
    reg     [SIZE - 1:0]       key_r1  ;
    reg                        nege    ;
    reg                        pose    ;

    reg     [19:00]     cnt_20ms     ;
    reg                 add_cnt_flag ;
    reg                 flag_20ms    ;

    // key_r0 key_r1 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            key_r0 <= 1 ;
        end else begin
            key_r0 <= key_in ;
        end
    end
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            key_r1 <= 1 ;
        end else begin
            key_r1 <= key_r0 ;
        end
    end

    // nege
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            nege <= 1'b0 ;
        end else begin
            if(| (~key_r0 &  key_r1)) begin
                nege <= 1'b1 ;
            end else begin
                nege <= 1'b0 ;
            end
        end
    end
    // pose
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            pose <= 1'b0 ;
        end else begin
            if(| ( key_r0 & ~key_r1)) begin
                pose <= 1'b1 ;
            end else begin
                pose <= 1'b0 ;
            end
        end
    end

    // add_cnt_flag
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            add_cnt_flag <= 1'b0 ;
        end else begin
            if(nege) begin
                add_cnt_flag <= 1'b1 ;
            end else begin
                if(pose || cnt_20ms == MAX_CNT_20MS) begin
                    add_cnt_flag <= 1'b0 ;
                end else begin
                    add_cnt_flag <= add_cnt_flag ;
                end
            end
        end
    end

    // cnt_20ms 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_20ms <= 20'd0 ;
        end else begin
            if(add_cnt_flag) begin
                if(cnt_20ms == MAX_CNT_20MS) begin
                    cnt_20ms <= 20'd0 ;
                end else begin
                    cnt_20ms <= cnt_20ms + 20'd1 ;
                end
            end else begin
                cnt_20ms <= 20'd0 ;
            end
        end
    end
    // falg_20ms
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            flag_20ms <= 1'b0 ;
        end else begin
            if(cnt_20ms == MAX_CNT_20MS - 1'b1) begin
                flag_20ms <= 1'b1 ;
            end else begin
                flag_20ms <= 1'b0 ;
            end
        end
    end

    // [3:0]key_out
    always @(posedge sys_clk or negedge sys_rst_n) begin
    // always @(*) begin // 这样的话 会综合成 数据选择器
        if(~sys_rst_n) begin
            key_out <= 0 ;
        end else begin
            if(flag_20ms) begin
                key_out <= ~key_r1 ;
            end else begin
                key_out <= 0 ;
            end
        end
    end
endmodule

?其他模块代码同example_rom

?

?

文章来源:https://blog.csdn.net/Meng_long2022/article/details/132770124
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。