|
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 21:50:13 10/02/07
// Design Name:
// Module Name: rs232
// Project Name:
// Target Device:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module rs232(clk50,rst,rxd,txd,led,led2,led3,led4);
input clk50,rst;
input rxd;
output txd;
output led,led2;
output led3,led4;
reg txd;
reg rxd_reg;
reg led; //对应开发板上第8个LED灯
reg led2; //对应开发板上第七个LED灯
reg led3;
reg led4;
wire clk50;
reg [6:0] waddr;
reg [6:0] raddr;
reg [7:0] wdata;
wire [7:0] rdata;
reg wea;
reg [2:0] DRI_state; //驱动状态,输出状态
reg [2:0] REV_state; //输入状态
reg [13:0] REV_counter,DRI_counter;
// reg [2:0] REV_counter,DRI_counter; //for test
reg received_char; //接收到一个字节后为1,否则为0
reg [7:0] rev_char; //接收到的字符
reg rev_check; //接收到字符的校验位
reg [7:0] send_char; //要发送的字符
reg send_check; //发送字符的校验位,偶校验
reg [7:0] send_char_tmp;
reg start_send_char; //为1时表示要发送一个字符,字符为send_char
reg send_char_over; //发送一个字符结束后变为1
reg [3:0] rev_bits_count; //记录接收一个字符8位里的多少位
reg [3:0] send_bits_count;//记录发送一个字符8位里的多少位
reg response; //为1时表示收到读取数据的命令,响应开始
reg [2:0] CHAR_REV_state;// 字符接收状态机
reg [3:0] CHAR_DRI_state;//字符发送状态机
// parameter DELAYCOUNT=10'b01_0100_0100; //324+1+1=326
parameter DELAYCOUNT= 14'b01_0100_0101_0110; //5206+1+1=5208
// parameter DELAYCOUNT=2'b10; //for test
parameter BITS_PER_CHAR=3'b110; //6+1+1=8
parameter REV_IDLE=3'b000,REV_START=3'b001,REV_BIT=3'b010,REV_CHECK=3'b101,REV_STOP=3'b100; //CHECK为校验位状态
parameter DRI_IDLE=3'b000,DRI_START=3'b001,DRI_BIT=3'b010,DRI_CHECK=3'b101,DRI_STOP=3'b100;
parameter CHAR_REV_IDLE=3'b000,CHAR_REV_CHAR2=3'b001,CHAR_REV_CHAR3=3'b010,CHAR_REV_CHAR4=3'b100;
parameter CHAR_DRI_IDLE=4'b0000,CHAR_DRI_ADDR=4'b0001,CHAR_DRI_CHAR2=4'b0010,CHAR_DRI_CHAR3=4'b0011,
CHAR_DRI_CHAR4=4'b0100,CHAR_DRI_DATA1=4'b0101,CHAR_DRI_DATA2=4'b0110,CHAR_DRI_DATA3=4'b1000,
CHAR_DRI_DATA4=4'b1001,CHAR_DRI_SUM=4'b0111;
parameter REV_ADDR=8'hE4,REV_CHAR2=8'h00,REV_CHAR3=8'h01,REV_CHAR4=8'h04;
parameter DRI_ADDR=8'hE4,DRI_CHAR2=8'hE1,DRI_CHAR3=8'h01,DRI_CHAR4=8'h04;
always @ (posedge clk50)
begin
if(~rst)
begin
rxd_reg<=1;
led2<=0;
led3<=0;
led4<=0;
end
else
begin
rxd_reg<=rxd;
if(~rxd_reg)
begin
led2<=1; //PC机向串口发送数据时,该灯点亮
led3<=1;
led4<=1;
end
end
end
//串口字符接收状态机,根据最开始从串口接收到的四个字符来判断是不是建立了连接
always @ (posedge clk50)
if(~rst)
begin
response<=0;
CHAR_REV_state<=CHAR_REV_IDLE; //b'000
led<=1;
end
else if(~wea)
begin
case(CHAR_REV_state)
CHAR_REV_IDLE:
begin
CHAR_REV_state<=CHAR_REV_IDLE;
response<=0;
led<=1;
//led4<=1;
if(received_char) //收到一个字符
begin
if(rev_char==REV_ADDR)
begin
CHAR_REV_state<=CHAR_REV_CHAR2;
end
end
end
CHAR_REV_CHAR2:
begin
if(received_char)
begin
if(rev_char==REV_CHAR2)
begin
CHAR_REV_state<=CHAR_REV_IDLE;
response<=1;
led<=0;
//led4<=0;
end
else
CHAR_REV_state<=CHAR_REV_IDLE;
end
end
default:
CHAR_REV_state<=CHAR_REV_IDLE;
endcase
end
//串口字符发送状态机
always @ (posedge clk50)
if(~rst)
begin
start_send_char<=0;
CHAR_DRI_state<=CHAR_DRI_IDLE;
raddr<=0;
end
else if(~wea)
begin
case(CHAR_DRI_state)
CHAR_DRI_IDLE:
begin
CHAR_DRI_state<=CHAR_DRI_IDLE;
start_send_char<=0;
raddr<=0;
if(response) //为1时表示收到PC机的命令,开始输出数据
begin
CHAR_DRI_state<=CHAR_DRI_ADDR;
send_char_tmp<=DRI_ADDR;
start_send_char<=1;
end
end
CHAR_DRI_ADDR:
begin
start_send_char<=0;
if(send_char_over)
begin
CHAR_DRI_state<=CHAR_DRI_CHAR2;
send_char_tmp<=DRI_CHAR2;
start_send_char<=1;
end
end
CHAR_DRI_CHAR2:
begin
start_send_char<=0;
if(send_char_over)
begin
CHAR_DRI_state<=CHAR_DRI_DATA1;
send_char_tmp<=rdata;
// send_char_tmp<=raddr;
start_send_char<=1;
raddr<=raddr+1;
end
end
CHAR_DRI_DATA1:
begin
start_send_char<=0;
if(raddr==7'd20)
CHAR_DRI_state<=CHAR_DRI_IDLE;
else if(send_char_over)
begin
CHAR_DRI_state<=CHAR_DRI_DATA1;
send_char_tmp<=rdata;
start_send_char<=1;
raddr<=raddr+1;
end
end
default:
CHAR_DRI_state<=CHAR_DRI_IDLE;
endcase
end
/*******************************************************************/
//单个字符接收状态机
always @ (posedge clk50)
if(~rst)
begin
rev_char<=8'b0;
REV_counter<=DELAYCOUNT;
REV_state<=REV_IDLE;
rev_bits_count<=BITS_PER_CHAR;
received_char<=0;
end
else if(~wea)
case(REV_state)
REV_IDLE:
begin
REV_counter<=DELAYCOUNT;
rev_bits_count<=BITS_PER_CHAR;
received_char<=0;
rev_check<=0;
rev_char<=8'b0;
if(~rxd_reg)//为低,起始位
begin
REV_state<=REV_START;
end
end
REV_START:
begin
if(REV_counter[13])//计数完成
begin
REV_state<=REV_BIT;
REV_counter<=DELAYCOUNT;
end
else
REV_counter<=REV_counter-1;
end
REV_BIT:
begin
if(REV_counter[13])//计数完成
begin
REV_state<=REV_BIT;
REV_counter<=DELAYCOUNT;
if(rev_bits_count[3])
begin
REV_state<=REV_CHECK;
REV_counter<=DELAYCOUNT;
end
else
rev_bits_count<=rev_bits_count-1;
end
else
REV_counter<=REV_counter-1;
if(REV_counter==2500) //在延时中间取值
// if(REV_counter==1)
begin
rev_char[7:0]<={rxd_reg,rev_char[7:1]}; //rev_char右移一位,低位在前
end
end
REV_CHECK:
begin
if(REV_counter[13])//计数完成
begin
REV_state<=REV_STOP;
REV_counter<=DELAYCOUNT; //对校验位没有做处理!!!!!!!!!!!!!!!!!!!!!!!!
received_char<=1; //接受到一个字符,指示总状态机接收到一个字符
end
else
REV_counter<=REV_counter-1;
if(REV_counter==2500)
// if(REV_counter==1)
begin
rev_check<=rxd_reg; //接收到校验位
end
end REV_STOP: //一个停止位
begin
received_char<=0;
if(REV_counter[13])//计数完成
begin
REV_state<=REV_IDLE;
REV_counter<=DELAYCOUNT;
end
else
REV_counter<=REV_counter-1;
end
default:
REV_state<=REV_IDLE;
endcase
//单个字符发送状态机
always @ (posedge clk50)
if(~rst)
begin
DRI_counter<=DELAYCOUNT;
DRI_state<=DRI_IDLE;
send_bits_count<=BITS_PER_CHAR;
send_char_over<=0;
txd<=1; //高表示空闲
end
else if(~wea)
case(DRI_state)
DRI_IDLE:
begin
DRI_counter<=DELAYCOUNT;
send_char_over<=0;
txd<=1;
send_check<=0;
send_bits_count<=BITS_PER_CHAR;
if(start_send_char)//要发送一个字符
begin
txd<=0; //起始位
DRI_state<=DRI_START;
send_char<=send_char_tmp;
send_check<=^send_char_tmp; //偶校验位为send_char_tmp的8数据位按位异或的结果
end
end
DRI_START:
begin
if(DRI_counter[13])//计数完成
begin
DRI_state<=DRI_BIT;
txd<=send_char[0];
send_char[7:0]<={send_char[0],send_char[7:1]}; //右移一位
DRI_counter<=DELAYCOUNT;
end
else
DRI_counter<=DRI_counter-1;
end
DRI_BIT:
begin
if(DRI_counter[13])//计数完成
begin
if(send_bits_count[3])
begin
DRI_state<=DRI_CHECK;
txd<=send_check;
DRI_counter<=DELAYCOUNT;
end
else
begin
DRI_state<=DRI_BIT;
txd<=send_char[0];
send_char[7:0]<={send_char[0],send_char[7:1]}; //右移一位
DRI_counter<=DELAYCOUNT;
send_bits_count<=send_bits_count-1;
end
end
else
DRI_counter<=DRI_counter-1;
end
DRI_CHECK:
begin
if(DRI_counter[13])//计数完成
begin
DRI_state<=DRI_STOP;
txd<=1; //停止位
DRI_counter<=DELAYCOUNT;
end
else
DRI_counter<=DRI_counter-1;
end
DRI_STOP: //一个停止位
begin
if(DRI_counter[13])//计数完成
begin
DRI_state<=DRI_IDLE;
DRI_counter<=DELAYCOUNT;
send_char_over<=1; //发送完一个字符
end
else
DRI_counter<=DRI_counter-1;
end
default:
DRI_state<=DRI_IDLE;
endcase
//上电复位后,写将20个数写入BlockRam
always @ (posedge clk50)
begin
if(~rst)
begin
waddr<=0;
wdata<=0;
wea<=1;
end
else
begin
if(waddr==7'd20)
begin
wea<=0;
waddr<=0;
wdata<=0;
end
else
begin
waddr<=waddr+1;
wdata<=wdata+1;
end
end
end
//调用BlockRam块
ram_dataout ram(
.addra(waddr),
.addrb(raddr),
.clka(clk50),
.clkb(clk50),
.dina(wdata),
.doutb(rdata),
.wea(wea));
endmodule
这个是开发板自带的程序,功能就是 ,通过串口发送 E4 00 ,然后FPGA 返回 E4 41 + 20个事先写入RAM里的数据
PC 发 FPGA时, 串口要设置校验位,,偶校验,
现在想把校验的功能去掉
是不是把 代码中红色部分去掉就可以了?
谢谢
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|