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