热度 6
2015-4-9 11:36
953 次阅读|
0 个评论
主要记录自己在利用 verilog 实现串口的时候一些简单的介绍和遇到问题和思考。备忘 1、串口传输格式,可以百度,有很多也很简单。串口分为两部分,一个收,一个发。所以在 verilog 实现时可以把这两部分分开。也就是两个 fifo 配套收和发的 .v 文件,可以实现一个串口。一般人实现串口的都是这么想的吧。下面是文件的层级结构: 2、当然是 coding 了。写串口的代码。主要贴一下收和发的状态机(用一段来实现的): (1)这是收的部分: case(state_rxd) state_rxd_idle : //0 begin finished_rxd = 1'b0; rxd_error = 1'b0; if((!rxd_write_full) ({port_rxd_d3,port_rxd_d2,port_rxd_d1}==3'b100)) begin state_rxd = state_rxd_head; time_rxd = 1'd0; end else state_rxd = state_rxd_idle; end state_rxd_head : //1 begin if((time_rxd == rxd_half_band_rate) ({port_rxd_d3,port_rxd_d2,port_rxd_d1}==3'b000)) begin time_rxd = 15'd0; state_rxd = state_rxd_rxd; data_rxd_d1 = 8'd0; end else if((time_rxd == rxd_half_band_rate) ({port_rxd_d3,port_rxd_d2,port_rxd_d1}!=3'b000)) begin time_rxd = 15'd0; state_rxd = state_rxd_idle; end else time_rxd = time_rxd + 1; end state_rxd_rxd : //2 begin if((time_rxd == rxd_band_rate)) begin time_rxd = 15'd0; if(count_rxd_bit == 3'd7) begin count_rxd_bit = 3'd0; state_rxd = state_rxd_tail; data_rxd_d1 = {port_rxd_d1,data_rxd_d1 }; end else begin count_rxd_bit = count_rxd_bit + 1; data_rxd_d1 = {port_rxd_d1,data_rxd_d1 }; end end else begin time_rxd = time_rxd + 1; end end state_rxd_tail : //3 begin if((time_rxd == rxd_band_rate) ({port_rxd_d3,port_rxd_d2,port_rxd_d1}==3'b111)) begin rxd_error = 1'd0; finished_rxd = 1'b1; state_rxd = state_rxd_idle; end else if((time_rxd == rxd_band_rate) ({port_rxd_d3,port_rxd_d2,port_rxd_d1}!=3'b111)) begin rxd_error = 1'd1; finished_rxd = 1'b0; state_rxd = state_rxd_idle; end else begin finished_rxd = 1'b0; rxd_error = 1'b0; time_rxd = time_rxd + 1; end end default : state_rxd = state_rxd_idle; Endcase (2)这是发的部分: case(state_txd) state_txd_idle : //0 begin time_txd = 15'd0; finished_send = 1'b0; if(load_data_tag_d1 == 1'b1) begin state_txd = state_txd_head; data_txd_reg1 = data_txd_reg; end else state_txd = state_txd; end state_txd_head : //1 begin port_txd_reg = 1'b0; if(time_txd == txd_band_rate) begin time_txd = 15'd0; state_txd = state_txd_txd; end else time_txd = time_txd + 1; end state_txd_txd : //2 begin port_txd_reg = data_txd_reg1 ; if(time_txd == txd_band_rate) begin time_txd = 15'd0; if(count_bit_send == 3'd7) begin count_bit_send = 3'd0; state_txd = state_txd_tail; end else begin count_bit_send = count_bit_send + 1; data_txd_reg1 = {1'b0,data_txd_reg1 }; end end else time_txd = time_txd + 1; end state_txd_tail : //3 begin port_txd_reg = 1'b1; if(time_txd == txd_band_rate) begin state_txd = state_txd_idle; finished_send = 1'b1; end else begin finished_send = 1'b0; time_txd = time_txd + 1; end end default: begin port_txd_reg = 1'b1; finished_send = 1'b0; time_txd = 15'd0; data_txd_reg1 = 8'd0; end Endcase 3、测试串口: 测试方法主要是通过自己把 fifo 写成回路来测试,相当于上位机发数据给 fpga ,然后 fpga 自己把数据通过串口传给上位机,对比传入和传出的数据是否一样来验证。这样测试对于一般串口的应用是应该够了。 4 ,调试过程中遇到问题: (1)fifo 里面的 wrfull 和 rdempty 信号,并不是延迟一个时钟出来的,而是延迟两个; (2)fifo 里面的 wrusedw 或者 rdusedw ,要等它反映过来,貌似是延迟 4 个时钟。而且这两个信号是可以用最高位来看 fifo 是否满半来做一些其它的操作的。 (3)Fifo 的 aclr 是高有效而产生复位 暂时就想到这么多,先写这么多,其实实现起来也很简单,主要写这个主要是为了以后多阅读英文文献,先从 fifo user guide 来入手研究一下容易点。