当前位置: 首页 > 工具软件 > 积木云 > 使用案例 >

《搭建你的数字积木 数字电路与逻辑设计》(2)

东郭凯捷
2023-12-01

串行通信接口控制器

UART 异步收发传输器(Universal Asynchronous Receiver/Transmitter)

主要功能分为三个模块,老生常谈的时钟模块,还有一个rx_uart和一个tx_uart模块,rx_uart负责接收来自外界的消息,并将其传给tx_uart模块,而tx_uart负责接收rx_uart的消息并将其解码后根据内部转换机制顺序回复相应的消息。

`timescale 1ns / 1ps
//
// Company: NUAA
// Engineer: Jason Wang
// 
// Create Date: 2021/07/05 09:17:07
// Design Name: uart
// Module Name: rs232_uart_clk_rst
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module rs232_uart_clk_rst(
	input I_sys_clk_50M,
	input I_sys_rst_50M,
	output O_clk_96M,
	output O_rst_96M
    );
wire rst_50M_n;
wire clk;
wire rst;
wire pll_locked;

reg rst_d1;
reg rst_d2;
assign rst_50M_n=~I_sys_rst_50M; // 按下为高电平
assign rst=rst_50M_n | ~pll_locked;

//==============================input register=================================
always@(posedge clk,posedge rst)begin
	if(rst)
	begin
		rst_d1<=1'b1;
		rst_d2<=1'b1;
	end
	else
		rst_d1<=rst;
		rst_d2<=rst_d1;
end
//==================================assign output=================================
assign O_clk_96M = clk;
assign O_rst_96M = rst_d2;

clk_wiz_0 clk_wiz_0_inst(
	.clk_in1(I_sys_clk_50M),
	.reset(rst_50M_n),
	.locked(pll_locked),
	.clk_out1(clk)
);

endmodule
`timescale 1ns / 1ps
//
// Company: NUAA
// Engineer: Jason Wang
// 
// Create Date: 2021/07/05 09:17:07
// Design Name: uart
// Module Name: rx_rs232_uart
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module rx_rs232_uart(
	input        I_clk,
	input        I_rst,
	input        I_rx_data,
	output [7:0] O_dout,
	output       O_valid,
	output       O_rx_clk
    );

reg rx_data_d1;
reg rx_data_d2;
reg rx_data_d3;
reg rx_data_d4;

reg[13:0]   rx_cnt;             //2^14=16384  96MHz /9600bps =10000 
reg         rx_cnt_en;
reg         rx_cnt_cl;

reg[3:0] state;
reg[3:0] n_state;
parameter		idle =4'h0,
				start=4'h1,
				bit0 =4'h2,
				bit1 =4'h3,
				bit2 =4'h4,
				bit3 =4'h5,
				bit4 =4'h6,
				bit5 =4'h7,
				bit6 =4'h8,
				bit7 =4'h9,
				check=4'ha,
				stop =4'hb;
reg [7:0]  rx_dout;
reg        rx_vld;
reg        rx_bsp_flg;            //按我的理解这个是开始赋值的标志,在计数到一半的时候开始将值付给dout
  

//======================input register=================
always@(posedge I_clk)begin
	rx_data_d1<=I_rx_data;
	rx_data_d2<=rx_data_d1;
	rx_data_d3<=rx_data_d2;
	rx_data_d4<=rx_data_d3;
	
end

//======================rx_cnt_cl=======================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		rx_cnt_cl<=1'b0;
	else if(rx_cnt==14'd9998)
		rx_cnt_cl<=1'b1;
	else
		rx_cnt_cl<=1'b0;
end
//======================rx_cnt_en======================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		rx_cnt_en<=1'b0;
	else if(state!=idle)
		rx_cnt_en<=1'b1;
	else
		rx_cnt_en<=1'b0;
end

//======================rx_cnt==========================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		rx_cnt<=14'd0;
	else if(rx_cnt_en==1'b1)
		rx_cnt<=rx_cnt+1'b1;
	else if(rx_cnt_cl==1'b1)
		rx_cnt<=14'd0;
	else
		rx_cnt<=rx_cnt;
end
//======================rx_bsp_flg====================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		rx_bsp_flg<=1'b0;
	else if(rx_cnt==14'd5000)
		rx_bsp_flg<=1'b1;
	else
		rx_bsp_flg<=1'b0;
end
		
//======================fsm===========================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		state<=4'h0;
	else
		state<=n_state;
end
always@(*) begin
	case(state)
		idle:
			begin
				if(rx_data_d3==1'b0)
					n_state=start;
				else
					n_state=idle;
			end
		start:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=bit0;
				else
					n_state=start;
			end
		bit0:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=bit1;
				else
					n_state=bit0;
			end
		bit1:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=bit2;
				else
					n_state=bit1;
			end
		bit2:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=bit3;
				else
					n_state=bit2;
			end
		bit3:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=bit4;
				else
					n_state=bit3;
			end
		bit4:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=bit5;
				else
					n_state=bit4;
			end
		bit5:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=bit6;
				else
					n_state=bit5;
			end
		bit6:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=bit7;
				else
					n_state=bit6;
			end
		bit7:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=check;
				else
					n_state=bit7;
			end
		check:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=stop;
				else
					n_state=check;
			end
		stop:
			begin
				if(rx_cnt_cl==1'b1)
					n_state=idle;
				else
					n_state=stop;
			end
		default:
			n_state=idle;
		endcase
end
//==========================assignment=====================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		rx_dout<=8'd0;
	else if(rx_bsp_flg==1'b1)
		case(state)
			bit0:	rx_dout[0]<=rx_data_d4;
			bit1:	rx_dout[1]<=rx_data_d4;	
			bit2:	rx_dout[2]<=rx_data_d4;
			bit3:	rx_dout[3]<=rx_data_d4;
			bit4:	rx_dout[4]<=rx_data_d4;		
			bit5:	rx_dout[5]<=rx_data_d4;
			bit6:	rx_dout[6]<=rx_data_d4;
			bit7:	rx_dout[7]<=rx_data_d4;
			default:
					rx_dout<=rx_dout;
		endcase
	else
				rx_dout<=rx_dout;
end

//========================assign output==================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		rx_vld<=1'b0;
	else if(rx_cnt_cl==1'b1 && state==bit7)
		rx_vld<=1'b1;
	else
		rx_vld<=1'b0;
end

assign O_dout = rx_dout;
assign O_vld  = rx_vld;
assign O_clk  = ~I_clk;
	
endmodule
`timescale 1ns / 1ps
//
// Company: NUAA
// Engineer: Jason Wang
// 
// Create Date: 2021/07/05 09:17:07
// Design Name: uart
// Module Name: tx_rs232_uart
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tx_rs232_uart(
	input   	I_clk,
	input   	I_rst,
	input[7:0]  I_data,
	input 		I_valid,
	output 		O_data
    );
	
reg[7:0] I_data_d1;
reg[7:0] I_data_d2;
reg[7:0] I_data_d3;
reg[7:0] I_data_d4;
reg I_valid_d1;
reg I_valid_d2;
reg I_valid_d3;
reg I_valid_d4;

reg[13:0] tx_cnt;
reg       tx_cnt_en;
reg       tx_cnt_cl;

reg[3:0] state;
reg[3:0] n_state;
parameter		idle =4'h0,
				start=4'h1,
				bit0 =4'h2,
				bit1 =4'h3,
				bit2 =4'h4,
				bit3 =4'h5,
				bit4 =4'h6,
				bit5 =4'h7,
				bit6 =4'h8,
				bit7 =4'h9,
				check=4'ha,
				stop =4'hb;
reg [7:0]	data_tem;
reg         tx_data;


//===========================input regester==================
always@(posedge I_clk)begin
	I_data_d1<=I_data;
	I_data_d2<=I_data_d1;
	I_data_d3<=I_data_d2;
	I_data_d4<=I_data_d3;
end
always@(posedge I_clk)begin
	I_valid_d1<=I_valid;
	I_valid_d2<=I_valid_d1;
	I_valid_d3<=I_valid_d2;
	I_valid_d3<=I_valid_d3;
end
//======================tx_cnt_en============================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		tx_cnt_en<=1'b0;
	else if(state!==idle)
		tx_cnt_en<=1'b1;
	else
		tx_cnt_en<=1'b0;
end
//========================tx_cnt_cl=======================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		tx_cnt_cl<=1'b0;
	else if(tx_cnt==14'd9998)
		tx_cnt_cl<=1'b1;
	else
		tx_cnt_cl<=1'b0;
end
//===========================tx_cnt==========================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		tx_cnt<=14'd0;
	else if(tx_cnt_cl==1'b1)
		tx_cnt<=14'd0;
	else if(tx_cnt_en==1'b1)
		tx_cnt<=tx_cnt+1'b1;
	else
		tx_cnt<=tx_cnt;
end
//============================fsm==============================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		state<=idle;
	else
		state<=n_state;
end
always@(*) begin
	case(state)
		idle:
			begin
				if(I_data_d3==1'b0)
					n_state=start;
				else
					n_state=idle;
			end
		start:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=bit0;
				else
					n_state=start;
			end
		bit0:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=bit1;
				else
					n_state=bit0;
			end
		bit1:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=bit2;
				else
					n_state=bit1;
			end
		bit2:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=bit3;
				else
					n_state=bit2;
			end
		bit3:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=bit4;
				else
					n_state=bit3;
			end
		bit4:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=bit5;
				else
					n_state=bit4;
			end
		bit5:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=bit6;
				else
					n_state=bit5;
			end
		bit6:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=bit7;
				else
					n_state=bit6;
			end
		bit7:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=check;
				else
					n_state=bit7;
			end
		check:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=stop;
				else
					n_state=check;
			end
		stop:
			begin
				if(tx_cnt_cl==1'b1)
					n_state=idle;
				else
					n_state=stop;
			end
		default:
			n_state=idle;
		endcase
end
//=====================assignment==============================
always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		data_tem<=8'd0;
	else if(I_valid_d2==1'b1)
		data_tem<=I_data_d2;
	else
		data_tem<=data_tem;
end

always@(posedge I_clk,posedge I_rst)begin
	if(I_rst)
		tx_data<=1'b1;
	else 
		case(state)
			idle:	tx_data<=1'b1;
		    start:  tx_data<=1'b0;
			bit0:	tx_data<=data_tem[0];
			bit1:	tx_data<=data_tem[1];	
			bit2:	tx_data<=data_tem[2];
			bit3:	tx_data<=data_tem[3];
			bit4:	tx_data<=data_tem[4];	
			bit5:	tx_data<=data_tem[5];
			bit6:	tx_data<=data_tem[6];
			bit7:	tx_data<=data_tem[7];
			check:  tx_data <= 1'b1;
			stop:   tx_data <= 1'b1;
			default:tx_data <= 1'b1;
		endcase
	end
	
assign O_data=tx_data;

endmodule
`timescale 1ns / 1ps
//
// Company: NUAA
// Engineer: Jason Wang
// 
// Create Date: 2021/07/05 09:17:07
// Design Name: uart
// Module Name: rs232_uart_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module rs232_uart_top(
	input I_sys_clk_50M,
	input I_sys_rst_50M,
	input I_rx_data,
	output O_tx_data
    );
wire        clk;
wire        rst;
wire [7:0]  data;
wire        valid;
wire        rx_clk;

rs232_uart_clk_rst rs232_uart_clk_rst_inst(
	.I_sys_clk_50M (I_sys_clk_50M),
	.I_sys_rst_50M (I_sys_rst_50M),
	.O_clk_96M     (clk),
	.O_rst_96M     (rst)
    );

rx_rs232_uart rx_rs232_uart_inst(
	.I_clk         (clk),
	.I_rst         (rst),
	.I_rx_data     (I_rx_data),
	.O_dout        (data),
	.O_valid       (valid),
	.O_rx_clk      (rx_clk)
    );
tx_rs232_uart tx_rs232_uart_inst(
	.I_clk         (rx_clk),
	.I_rst         (rst),
	.I_data		   (data),
	.I_valid       (valid),
	.O_data        (O_tx_data)
    );

endmodule

主要还是状态机的转换。

PS/2协议

PS/2这种协议几乎已经不用了,现在的键盘通用的都是USB的接口协议。PS/2通信协议是一种双向同步串行通信协议。通信的两端通过Clock(时钟脚)同步,并通过Data(数据脚)交换数据。任何一方如果想抑制另外一方通信时,只需要把时钟脚拉到低电平。如果是PC和PS/2键盘间的通信,则PC必须做主机,也就是说,PC可以抑制PS/2键盘发送数据,而PS/2键盘则不会抑制PC发送数据。大多数PS/2设备工作在10~20kHz。

SPI协议

I2C协议

由于对于这两个通信协议不是很熟悉,暂时跳过。

RAM接口控制器

 类似资料: