⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ac51_serial.v

📁 Verilog 8051 IP Core for Cyclone II
💻 V
字号:
//// ac51_serial.v//// ac51 microcontroller core//// Version 0.6//// Copyright 2008, Hideyuki Abe. All rights reserved.// Distributed under the terms of the MIT License.//module ac51_serial(	clk,	rst,	ioaddr,	iowdata,	iordata,	iowen,	sck1,	sck2,	rclk,	tclk,	smod,	rxd_i,	rxd_o,	txd,	sint_req);input	clk;input	rst;input [6:0]	ioaddr;input [7:0]	iowdata;output [7:0]	iordata;input	iowen;input	sck1;input	sck2;input	rclk;input	tclk;input	smod;input	rxd_i;output	rxd_o;output	txd;output	sint_req;reg [6:0]	ioaddr_d;wire	scon_enb;wire	sbuf_enb;wire	scon_wen;wire	sbuf_wen;wire [7:0]	scon;reg [7:0]	sbuf;// smode[0] : SM2, smode[1] : SM1, smode[2] : SM0reg [2:0]	smode;reg	ren;reg	tb8;reg	rb8;reg	ti;reg	ri;reg	ri_set;reg [8:0]	tbuf;reg [8:0]	rbuf;reg	half_clk;reg	sck1_i;reg	sck1_en;reg	spresc_upd;reg	rpresc_upd;reg [5:0]	snd_presc;reg [5:0]	rcv_presc;reg [5:0]	presc_rld;reg	sending;reg	receiving;reg	snd_start;reg	snd_stop;reg [7:0]	rxd_seq;reg	rcv_start;reg	rcv_stop;reg [3:0]	snd_cnt;reg [3:0]	rcv_cnt;wire	snd_cnt_upd;wire	rcv_cnt_upd;reg	snd_shift;reg	rcv_shift;reg [1:0]	rxd_one_cnt;reg	rxd_f;wire	rxd_rdy;reg	rxd_o;reg	txd;always @(posedge clk or negedge rst) begin	if(~rst)		ioaddr_d <= 7'h00;	else		ioaddr_d <= ioaddr;end	// alwaysassign	scon_enb = (ioaddr_d == 7'h18);	// SCON @8'h98assign	sbuf_enb = (ioaddr_d == 7'h19);	// SBUF @8'h99assign	scon = {smode, ren, tb8, rb8, ti, ri};always @(posedge clk or negedge rst) begin	if(~rst)		sbuf = 8'h00;	else if(ri_set)		sbuf = rbuf[7:0];end	// alwaysassign	iordata = ({8{scon_enb}} & scon)					| ({8{sbuf_enb}} & sbuf);assign	scon_wen = ((ioaddr == 7'h18) & iowen);	// SCON @8'h98assign	sbuf_wen = ((ioaddr == 7'h19) & iowen);	// SBUF @8'h99always @(posedge clk or negedge rst) begin	if(~rst) begin		smode <= 3'b000;		ren <= 1'b0;		tb8 <= 1'b0;	end	else if(scon_wen) begin		smode <= iowdata[7:5];		ren <= iowdata[4];		tb8 <= iowdata[3];	endend	// alwaysalways @(posedge clk or negedge rst) begin	if(~rst)		rb8 <= 1'b0;	else if(ri_set)		rb8 <= rbuf[8];/* controlled by hardware *///	else if(scon_wen)//		rb8 <= iowdata[2];end	// alwaysalways @(posedge clk or negedge rst) begin	if(~rst)		ti <= 1'b0;	else if(snd_stop)		ti <= 1'b1;	else if(scon_wen)//		ti <= ti & iowdata[1];	// clear		ti <= iowdata[1];		// set & clearend	// alwaysalways @(posedge clk or negedge rst) begin	if(~rst)		ri <= 1'b0;	else if(ri_set)		ri <= 1'b1;	else if(scon_wen)//		ri <= ri & iowdata[0];	// clear		ri <= iowdata[0];		// set & clearend	// alwaysalways @(smode or rcv_stop or rbuf) begin	case(smode[2:1])	2'b00:	// mode0		ri_set = rcv_stop;	2'b01,	// mode1	2'b10,	// mode2	2'b11:	// mode3		if(smode[0])	// if SM2 = 1			ri_set = rcv_stop & rbuf[8];		else			ri_set = rcv_stop;	endcaseend	// always combassign	sint_req = ti | ri;// prescaleralways @(posedge clk or negedge rst) begin	if(~rst)		snd_presc <= 6'h00;	else if(sending) begin		if(spresc_upd) begin			if(snd_presc == 6'h00)				snd_presc <= presc_rld;			else				snd_presc <= snd_presc - 6'h01;		end	end	else		snd_presc <= presc_rld;end	// alwaysalways @(posedge clk or negedge rst) begin	if(~rst)		rcv_presc <= 6'h00;	else if(receiving) begin		if(rpresc_upd) begin			if(rcv_presc == 6'h00)				rcv_presc <= presc_rld;			else				rcv_presc <= rcv_presc - 6'h01;		end	end	else		rcv_presc <= presc_rld;end	// alwaysalways @(	smode or smod or sck1_i or sck1_en	or sck2 or tclk) begin	case(smode[2:1])	2'b00:	// mode0		spresc_upd = sck1_i;	2'b10:	// mode2		if(smod) spresc_upd = sck1_i;		else spresc_upd = sck1_i & sck1_en;	2'b01,	// mode1	2'b11:	// mode3		if(tclk) spresc_upd = sck2;		else if(smod) spresc_upd = sck1_i;		else spresc_upd = sck1_i & sck1_en;	endcaseend	// always combalways @(	smode or smod or sck1_i or sck1_en	or sck2 or rclk) begin	case(smode[2:1])	2'b00:	// mode0		rpresc_upd = sck1_i;	2'b10:	// mode2		if(smod) rpresc_upd = sck1_i;		else rpresc_upd = sck1_i & sck1_en;	2'b01,	// mode1	2'b11:	// mode3		if(rclk) rpresc_upd = sck2;		else if(smod) rpresc_upd = sck1_i;		else rpresc_upd = sck1_i & sck1_en;	endcaseend	// always combalways @(posedge clk or negedge rst) begin	if(~rst)		half_clk <= 1'b0;	else		half_clk <= ~half_clk;end	// alwaysalways @(smode or sck1 or half_clk or smod) begin	case(smode[2:1])	2'b00:	// mode0		sck1_i = 1'b1;		// count every cycle	2'b01:	// mode1		sck1_i = sck1;		// count when tmr1 overflow	2'b10:	// mode2		sck1_i = half_clk;	// count every other cycle	2'b11:	// mode3		sck1_i = sck1;		// count when tmr1 overflow	endcaseend	// always combalways @(posedge clk or negedge rst) begin	if(~rst)		sck1_en <= 1'b0;	else if(sck1_i)		sck1_en <= ~sck1_en;end	// alwaysalways @(smode or smod) begin	presc_rld = 6'h00;	case(smode[2:1])	2'b00:	// mode0		presc_rld = 6'd11;	2'b01,	// mode1	2'b10,	// mode2	2'b11:	// mode3		presc_rld = 6'd15;	endcaseend	// always combalways @(posedge clk or negedge rst) begin	if(~rst)		sending <= 1'b0;	else if(snd_start)		sending <= 1'b1;	else if(snd_stop)		sending <= 1'b0;end	// alwaysalways @(sbuf_wen) begin	snd_start = sbuf_wen;end	// always combalways @(smode or snd_cnt or snd_cnt_upd) begin	snd_stop = 1'b0;	case(smode[2:1])	2'b00:	// mode0		snd_stop = ((snd_cnt == 4'h8) & snd_cnt_upd);	2'b01:	// mode1		snd_stop = ((snd_cnt == 4'h9) & snd_cnt_upd);	2'b10,	// mode2	2'b11:	// mode3		snd_stop = ((snd_cnt == 4'ha) & snd_cnt_upd);	endcaseend	// always combalways @(posedge clk or negedge rst) begin	if(~rst)		receiving <= 1'b0;	else if(rcv_start)		receiving <= 1'b1;	else if(rcv_stop)		receiving <= 1'b0;end	// always// detect falling edge of rxdalways @(posedge clk or negedge rst) begin	if(~rst)		rxd_seq <= 8'hff;	else		rxd_seq <= {rxd_seq[6:0], rxd_i};end	// always//always @(smode or ren or ri or receiving or rxd_seq) beginalways @(smode or ren or ri or receiving or rcv_stop or rxd_seq) begin	rcv_start = 1'b0;	case(smode[2:1])	2'b00:	// mode0		rcv_start = ren & ~ri & ~receiving;	2'b01,	// mode1	2'b10,	// mode2	2'b11:	// mode3		rcv_start = ren & (rxd_seq == 8'h80) & (~receiving | rcv_stop);	endcaseend	// always combalways @(smode or rcv_cnt or rcv_cnt_upd or rxd_rdy or rxd_f) begin	rcv_stop = 1'b0;	case(smode[2:1])	2'b00:	// mode0		rcv_stop = ((rcv_cnt == 4'h8) & rcv_cnt_upd);	2'b01:	// mode1		rcv_stop = ((rcv_cnt == 4'h0) & rxd_rdy & rxd_f)	// spurious start bit				| ((rcv_cnt == 4'h9) & rcv_cnt_upd);	2'b10,	// mode2	2'b11:	// mode3		rcv_stop = ((rcv_cnt == 4'h0) & rxd_rdy & rxd_f)	// spurious start bit				| ((rcv_cnt == 4'ha) & rcv_cnt_upd);	endcaseend	// always combalways @(posedge clk or negedge rst) begin	if(~rst)		snd_cnt <= 4'h0;	else if(snd_stop)		snd_cnt <= 4'h0;	else if(snd_cnt_upd)		snd_cnt <= snd_cnt + 4'h1;end	// alwaysassign	snd_cnt_upd = sending & (snd_presc == 6'd0) & spresc_upd;always @(smode or snd_cnt_upd or snd_cnt) begin	snd_shift = 1'b0;	case(smode[2:1])	2'b00:	// mode0		snd_shift = snd_cnt_upd;	2'b01:	// mode1		snd_shift = snd_cnt_upd & ((snd_cnt >= 4'h1) & (snd_cnt < 4'h8));	2'b10,	// mode2	2'b11:	// mode3		snd_shift = snd_cnt_upd & ((snd_cnt >= 4'h1) & (snd_cnt < 4'h9));	endcaseend	// always combalways @(posedge clk or negedge rst) begin	if(~rst)		rcv_cnt <= 4'h0;	else if(rcv_stop)		rcv_cnt <= 4'h0;	else if(rcv_cnt_upd)		rcv_cnt <= rcv_cnt + 4'h1;end	// alwaysassign	rcv_cnt_upd = receiving & (rcv_presc == 6'd0) & rpresc_upd;always @(smode or rxd_rdy or rcv_cnt) begin	rcv_shift = 1'b0;	case(smode[2:1])	2'b00:	// mode0		rcv_shift = rxd_rdy;	2'b01,	// mode1	2'b10,	// mode2	2'b11:	// mode3		rcv_shift = rxd_rdy & ((rcv_cnt >= 4'h1) & (rcv_cnt < 4'ha));	endcaseend	// always combalways @(posedge clk or negedge rst) begin	if(~rst)		tbuf <= 9'h000;	else if(sbuf_wen)		tbuf <= {tb8, iowdata};	else if(snd_shift)		tbuf <= {1'b0, tbuf[8:1]};end	// alwaysalways @(posedge clk or negedge rst) begin	if(~rst)		rbuf <= 9'h000;	else if(rcv_shift) begin		if(smode[2:1] == 2'b00)	// mode0			rbuf <= {rxd_i, rbuf[8:1]};		else			rbuf <= {rxd_f, rbuf[8:1]};	endend	// always// rxd noise rejectionalways @(posedge clk or negedge rst) begin	if(~rst) begin		rxd_one_cnt <= 2'b00;	end	else if(receiving & rpresc_upd) begin		if(rcv_presc == 6'd10) begin			rxd_one_cnt <= 2'b00;		end		else if(rcv_presc == 6'd9 | rcv_presc == 6'd8			| rcv_presc == 6'd7) begin			if(rxd_i) rxd_one_cnt <= rxd_one_cnt + 2'b01;		end	endend	// alwaysalways @(posedge clk or negedge rst) begin	if(~rst) begin		rxd_f <= 1'b1;	end	else if(receiving & rpresc_upd) begin		if(rcv_presc == 6'd6)			rxd_f <= rxd_one_cnt[1];	endend	// alwaysassign	rxd_rdy = receiving & (rcv_presc == 6'd2) & rpresc_upd;always @(smode or sending or tbuf) begin	rxd_o = 1'b1;	case(smode[2:1])	2'b00:	// mode0		if(sending) rxd_o = tbuf[0];	endcaseend	// always combalways @(	smode or sending or snd_presc or receiving or rcv_presc	or snd_cnt or sending or tbuf) begin	txd = 1'b1;	case(smode[2:1])	2'b00:	// mode0		if(sending) begin			if((snd_presc < 6'd8) & (snd_presc >= 6'd2))				txd = 1'b0;		end		else if(receiving) begin			if((rcv_presc < 6'd8) & (rcv_presc >= 6'd2))				txd = 1'b0;		end	2'b01:	// mode1		if(sending) begin			if(snd_cnt == 4'h0) txd = 1'b0;	// start bit			else if(snd_cnt == 4'h9) txd = 1'b1;	// stop bit			else txd = tbuf[0];		end	2'b10,	// mode2	2'b11:	// mode3		if(sending) begin			if(snd_cnt == 4'h0) txd = 1'b0;	// start bit			else if(snd_cnt == 4'ha) txd = 1'b1;	// stop bit			else txd = tbuf[0];		end	endcaseend	// always combendmodule// End of ac51_serial.v

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -