对RAM(随机存储器)进行读和写操作。 使用tool工具生成IP核RAM,8位读地址8位写地址。
当读地址为零时,两个周期后q信号输出数据。延迟两个周期。
将按键异步信号消抖处理,产生Key_flag和Key_state信号,处理按键按下事件。
module Key_shake(Clk,Rst_n,Key_in,Key_flag,Key_data); input Clk; input Rst_n; input Key_in; output reg Key_flag; //当按键按下20ms消除抖动成功后产生一个脉冲flag信号,检测到产生flag信号后产生按键按下低电平。 output reg Key_data; reg [3:0]state; reg [19:0]count; //寄存器计数 reg count_start;//时能计时 reg count_full;//计满脉冲信号 reg reg0,reg1; reg key_in_now0,key_in_now1; wire rise,fall; localparam High_pulse = 4'b0001, //高电平稳定状态 Low_eliminate = 4'b0010, //键下降沿稳定状态 Low_pulse = 4'b0100, //低电平稳定状态 High_eliminate = 4'b1000; //键上升沿稳定状态 always @(posedge Clk or negedge Rst_n) //对输入按键信号做同步处理,消除异步信号亚稳态的影响。 if(!Rst_n) begin key_in_now0 <= 1'b0; key_in_now1 <=1'b0; end else begin key_in_now0 <= Key_in; key_in_now1 <= key_in_now0; end always @(posedge Clk or negedge Rst_n) //脉冲边沿检测 两个寄存器 if(!Rst_n) begin reg0 <= 1'b0; reg1 <=1'b0; end else begin reg0 <= key_in_now1; reg1 <= reg0; end assign fall = !reg0 & reg1; //检测到下降沿 assign rise = reg0 & !reg1; //检测到上升沿 always @(posedge Clk or negedge Rst_n) //20ms计数器 if(!Rst_n) count <= 20'b0; else if(count_start) count <= count + 20'b1; else count <= 20'b0; always @(posedge Clk or negedge Rst_n) //20ms计数器计数满标志脉冲信号 if(!Rst_n) count_full <= 1'b0; else if(count == 99_9999) count_full <= 1'b1; else count_full <= 1'b0; always @(posedge Clk or negedge Rst_n) if(!Rst_n) begin Key_data <= 1'b1; state <= High_pulse; Key_flag <= 1'b0; count_start <= 1'b0; end else case(state) High_pulse : begin Key_flag <= 0; Key_data <= 1'b1; if(fall) begin state <= Low_eliminate; count_start <= 1'b1; //使能开始20ms计数 end else state <= High_pulse; end Low_eliminate : if(count_full) begin state <= Low_pulse; Key_flag <= 1'b1; Key_data <= 1'b0; count_start <= 1'b0; //关闭使能20ms计数 end else begin if(rise) begin state <= High_pulse; count_start <= 1'b0; //关闭使能20ms计数 end else state <= Low_eliminate; end Low_pulse: begin Key_flag <= 1'b0; if(rise) begin state <= High_eliminate; count_start <= 1'b1; //开始计时 end else state <= Low_pulse; end High_eliminate : if(count_full) begin Key_data <= 1'b1; Key_flag <= 1'b1; state <= High_pulse; end else begin if(fall) begin state <= Low_pulse; count_start <= 1'b0; end else state <= High_eliminate; end default : begin state <= High_pulse; //默认状态 count_start <= 1'b0; Key_data <= 1'b1; Key_flag <= 1'b0; end endcase endmodule接收外来信号并传输到dpram中。
module uart_data_rx( //串口接收模块 Clk, Rst_n, Rs232_rx, Bps_set, Data_out, Done_rx ); input Clk; input Rst_n; input Rs232_rx; input [2:0]Bps_set; output reg [7:0]Data_out; output reg Done_rx; reg [8:0]bps_max;//计数值 reg now_reg0,rs232_rx_now; //同步寄存器 消除亚稳态 reg data_reg0,data_reg1; //数据寄存器 判断高低电平 wire low; reg en_data; reg [8:0]bps_con; //bps_clk时钟计数器 reg bps_clk; reg [7:0]bps_count; reg [2:0]Data[7:0]; //共有8个Data数据每一个Data数据有3位 例如110 reg [2:0]start_bite; reg [2:0]stop_bite; //查找表选择计数值 always @(posedge Clk or negedge Rst_n) if(!Rst_n) bps_max <= 9'b0; else begin case(Bps_set) 0: bps_max <= 9'd324; 1: bps_max <= 9'd162; 2: bps_max <= 9'd80; 3: bps_max <= 9'd53; 4: bps_max <= 9'd26; default : bps_max <= 9'd324; endcase end //消除亚稳态 always @(posedge Clk or negedge Rst_n) if(!Rst_n) begin now_reg0 <= 0; rs232_rx_now <= 0; end else begin now_reg0 <= Rs232_rx; rs232_rx_now <= now_reg0; end //判断低电平 always @(posedge Clk or negedge Rst_n) if(!Rst_n) begin data_reg0 <= 0; data_reg1 <= 0; end else begin data_reg0 <= rs232_rx_now; data_reg1 <= data_reg0; end assign low = !data_reg0 & data_reg1; //使能开始计数 always @(posedge Clk or negedge Rst_n) if(!Rst_n) bps_con <= 9'b0; else if(en_data) begin if(bps_con == bps_max) bps_con <= 9'b0; else bps_con <= bps_con + 1'b1; end else bps_con <= 9'b0; //产生波特率时钟 always @(posedge Clk or negedge Rst_n) if(!Rst_n) bps_clk <= 0; else if(bps_con ==9'b1) bps_clk <= 1'b1; else bps_clk <= 1'b0; //计数波特率时钟 always @(posedge Clk or negedge Rst_n) if(!Rst_n) bps_count <= 8'b0; else if(Done_rx || ((bps_count == 8'd12) && (start_bite >2))) bps_count <= 8'b0; else if(bps_clk) bps_count <= bps_count + 1'b1; //产生Done_rx计数满信号 always @(posedge Clk or negedge Rst_n) if(!Rst_n) Done_rx <= 1'b0; else if(bps_count == 8'd159) Done_rx <= 1'b1; else Done_rx <= 1'b0; //将Data的值给Data_out输出查看 always @(posedge Clk or negedge Rst_n) if(!Rst_n) Data_out <= 8'b0; else if(bps_count == 8'd159) begin Data_out[0] <= Data[0][2]; //如果中间6位数值和加起来大于3(100.101.110)第3位数值将大于1,由此可以将第3位的值直接传给Data_out数据 Data_out[1] <= Data[1][2]; Data_out[2] <= Data[2][2]; Data_out[3] <= Data[3][2]; Data_out[4] <= Data[4][2]; Data_out[5] <= Data[5][2]; Data_out[6] <= Data[6][2]; Data_out[7] <= Data[7][2]; end //将Data的中间6位数据累加 always @(posedge Clk or negedge Rst_n) if(!Rst_n)begin start_bite <= 3'b0; Data[0] <= 3'b0; Data[1] <= 3'b0; Data[2] <= 3'b0; Data[3] <= 3'b0; Data[4] <= 3'b0; Data[5] <= 3'b0; Data[6] <= 3'b0; Data[7] <= 3'b0; stop_bite <= 3'b0; end else if(bps_clk) begin case(bps_count) 0:begin start_bite <= 3'b0; Data[0] <= 3'b0; Data[1] <= 3'b0; Data[2] <= 3'b0; Data[3] <= 3'b0; Data[4] <= 3'b0; Data[5] <= 3'b0; Data[6] <= 3'b0; Data[7] <= 3'b0; stop_bite <= 3'b0; end 6,7,8,9,10,11: start_bite <= start_bite + rs232_rx_now; 22,23,24,25,26,27: Data[0] <= Data[0] + rs232_rx_now; 38,39,40,41,42,43: Data[1] <= Data[1] + rs232_rx_now; 54,55,56,57,58,59: Data[2] <= Data[2] + rs232_rx_now; 70,71,72,73,74,75: Data[3] <= Data[3] + rs232_rx_now; 86,87,88,89,90,91: Data[4] <= Data[4] + rs232_rx_now; 102,103,104,105,106,107: Data[5] <= Data[5] + rs232_rx_now; 118,119,120,121,122,123: Data[6] <= Data[6] + rs232_rx_now; 134,135,136,137,138,139: Data[7] <= Data[7] + rs232_rx_now; 150,151,152,153,154,155: stop_bite <= stop_bite + rs232_rx_now; default : begin start_bite <= start_bite; Data[0] <= Data[0]; Data[1] <= Data[1]; Data[2] <= Data[2]; Data[3] <= Data[3]; Data[4] <= Data[4]; Data[5] <= Data[5]; Data[6] <= Data[6]; Data[7] <= Data[7]; stop_bite <= stop_bite; end endcase end //判断是否完成接收或无开始错误,产生使能信号 always @(posedge Clk or negedge Rst_n) if(!Rst_n) en_data <= 1'b0; else if(low) en_data <= 1'b1; else if(Done_rx ||((bps_count == 8'd12) && (start_bite >2))) en_data <= 1'b0; else en_data <= en_data; endmodule使用quartus2软件工具生成存储器IP核。
读取dpram中的值,con_en使能为高电平输出dapram中的值。
module UART_TX( Clk, Rst_n, Bps_set, Con_en, Data_in, Rs232_tx, Done_tx, Uart_state ); input Clk; input Rst_n; input [2:0]Bps_set; input Con_en; input [7:0]Data_in; output reg Rs232_tx; output reg Done_tx; output reg Uart_state; reg [15:0]count; //计数器定值 reg [15:0]high_count; //计数值 reg [7:0]Data_in_r; reg bps_clk; reg [3:0]bps_count; localparam start_bite = 1'b0; localparam stop_bite = 1'b1; //查找表输出计数值 always @(posedge Clk or negedge Rst_n) if(!Rst_n) count <= 16'd5207; else begin case(Bps_set) 0: count <= 16'd5207; 1: count <= 16'd2603; 2: count <= 16'd1301; 3: count <= 16'd865; 4: count <= 16'd433; default : count <= 16'd5207; endcase end //产生Uart_state使能信号 always @(posedge Clk or negedge Rst_n) if(!Rst_n) Uart_state <= 1'b0; else if(Con_en) Uart_state <= 1'b1; else if(bps_count == 4'd11) Uart_state <= 1'b0; else Uart_state <= Uart_state; //计数满产生bps_clk信号 always @(posedge Clk or negedge Rst_n) if(!Rst_n) high_count <= 0; else if(Uart_state) begin if(high_count == count) high_count <= 0; else high_count <= high_count + 1'b1; end else high_count <= 0; always @(posedge Clk or negedge Rst_n) if(!Rst_n) bps_clk <= 1'b0; else if(high_count == 16'b1) bps_clk <= 1'b1; else bps_clk <= 1'b0; //计数bps_clk的高电平到11计数满为0 产生Done_tx高点平信号 always @(posedge Clk or negedge Rst_n) if(!Rst_n) bps_count <= 4'b0; else if(bps_count == 4'd11) bps_count <= 4'b0; else if(bps_clk ) bps_count <= bps_count + 4'b1; else bps_count <= bps_count; always @(posedge Clk or negedge Rst_n) if(!Rst_n) Done_tx <= 1'b0; else if(bps_count == 4'd11) Done_tx <= 1; else Done_tx <= 0; always @(posedge Clk or negedge Rst_n ) if(!Rst_n) Data_in_r <= 0; else if(Con_en) Data_in_r <= Data_in ; else Data_in_r <= Data_in_r; //十选一多路选择器 always @(posedge Clk or negedge Rst_n) if(!Rst_n) Rs232_tx <= 1'b1; else begin case(bps_count) 0: Rs232_tx <= 1'b1; 1: Rs232_tx <= start_bite; 2: Rs232_tx <= Data_in_r[0]; 3: Rs232_tx <= Data_in_r[1]; 4: Rs232_tx <= Data_in_r[2]; 5: Rs232_tx <= Data_in_r[3]; 6: Rs232_tx <= Data_in_r[4]; 7: Rs232_tx <= Data_in_r[5]; 8: Rs232_tx <= Data_in_r[6]; 9: Rs232_tx <= Data_in_r[7]; 10: Rs232_tx <= stop_bite; default : Rs232_tx <= 1'b1; endcase end endmodule控制其他模块的输入输出。
module control( Key_state, Key_flag, Clk, Rst_n, Done_rx, Done_tx, Rdaddress, Wraddress, Wren, En_send ); input Key_flag; input Key_state; input Clk, Rst_n; input Done_rx,Done_tx; output reg [7:0]Rdaddress; output reg [7:0]Wraddress; output Wren; output reg En_send; reg put_button; reg delay_t0,delay_t1; assign Wren = Done_rx; always @(posedge Clk or negedge Rst_n) //写入地址 if(!Rst_n) Wraddress <= 8'd0; else if(Done_rx) Wraddress <= Wraddress + 1'b1; else Wraddress <= Wraddress ; always @(posedge Clk or negedge Rst_n) //乒乓操作 if(!Rst_n) put_button <= 1'b0; else if(Key_flag && !Key_state) put_button <= ~ put_button; always @(posedge Clk or negedge Rst_n) //读操作 if(!Rst_n) Rdaddress <= 8'b0; else if(put_button && Done_tx) Rdaddress <= Rdaddress + 1'b1; else Rdaddress <= Rdaddress; //将信号延迟两个周期 always @(posedge Clk or negedge Rst_n) if(!Rst_n) begin delay_t0 <= 1'b0; delay_t1 <= 1'b0; end else begin delay_t0 <= (put_button && Done_tx); delay_t1 <= delay_t0; end //控制产生发送使能信号 always @(posedge Clk or negedge Rst_n) if(!Rst_n) En_send <= 1'b0; else if(delay_t1) En_send <= 1'b1; else if(Key_flag && !Key_state) En_send <= 1'b1; else En_send <= 1'b0; endmodule //控制产生发送使能信号 always @(posedge Clk or negedge Rst_n) if(!Rst_n) En_send <= 1'b0; else if(delay_t1) En_send <= 1'b1; else if(Key_flag && !Key_state) En_send <= 1'b1; else En_send <= 1'b0;if(Key_flag && !Key_state)条件为第一次按下按键后的产生En_send使能信号发送地址为0的数据,if(delay_t1) 为按下按键后每当tx模块输出一次地址数据完成产生Done_tx信号自动输出下一个地址数据。
Key_model模块为按键事件模型,模拟实际中产生的按键抖动信号。 当读地址rdaddress变化后,dpram寄存器输出Data_bite_tx信号。
