赞
踩
UART:通用异步收发器
接收和发送串行数据,发送和接收单元不同步
设计实例:以ASIC码传输
“协议约定”:
1.起始位为0表示传输开始
2.停止位为1表示传输结束
3.数据传输从LSB开始
输入端口:
data_in[7:0]:主机输入UART_XMTR的数据,位宽为8=7bit data+1bit 奇偶校验
byte_ready:主机向发送器声明数据已经准备好
t_ready:主机向发送器声明可以开始传递数据,即起始位变低
输出端口:
serial_out:串行输出数据
`timescale 1ns/1ns module uart_xmt_controller( input wire sclk, input wire rst_n, input wire byte_ready, input wire t_ready, input wire bc_lt_bcmax, output reg load_shiftreg, output reg start, output reg send, output reg inc_bc_counter, output reg clc_bc_counter ); parameter S_idle=3'b001, S_wait=3'b010, S_send=3'b100; reg [2:0] state,next_state; always @(posedge sclk or negedge rst_n)begin if(rst_n==1'b0) next_state<=3'd0; else next_state<=state; end always @(*)begin load_shiftreg=0;start=0;send=0; inc_bc_counter=0;clc_bc_counter=0; next_state=S_idle; case(state) S_idle:begin if(byte_ready==1'b1) begin next_state=S_wait; load_shiftreg=1; end else next_state=S_idle; end S_wait:begin if(t_ready==1'b1) begin next_state=S_send; start=1; end else next_state=S_wait; end S_send:begin send=1; if(bc_lt_bcmax==1'b1)begin next_state=S_send; inc_bc_counter=1; end else begin next_state=S_idle; clc_bc_counter=1; end end default:next_state=S_idle; endcase end endmodule
`timescale 1ns/1ns module uart_xmt_datapath #( parameter WORD_SIZE=8, parameter BC_SIZE=4, parameter BC_MAX=9 )( input wire sclk, input wire rst_n, input wire load_shiftreg, input wire start, input wire send, input wire inc_bc_counter, input wire clc_bc_counter, input wire [WORD_SIZE-1:0] data_in, output wire bc_lt_bcmax, output wire serial_out ); reg [WORD_SIZE:0] data_shift; reg [BC_SIZE-1:0] bit_counter; assign serial_out=data_shift[0]; assign bc_lt_bcmax=(bit_counter<9)? 1'b1:1'b0; always @(posedge sclk or negedge rst_n)begin if(rst_n==1'b0) data_shift<=9'b1_1111_1111; else if(load_shiftreg==1'b1) data_shift<={data_in,1'b1}; else if(start==1'b1) data_shift<={data_shift[WORD_SIZE:1],1'b0}; else if(send==1'b1) data_shift<={1'b1,data_shift[WORD_SIZE:1]}; else data_shift<=data_shift; end always @(posedge sclk or negedge rst_n)begin if(rst_n==1'b0) bit_counter<=0; else if(inc_bc_counter==1'b1) bit_counter<=bit_counter+1'b1; else if(clc_bc_counter==1'b1) bit_counter<=0; else bit_counter<=bit_counter; end endmodule
`timescale 1ns/1ns module uart_xmt #( parameter WORD_SIZE=8, parameter BC_SIZE=4, parameter BC_MAX=9 )( input wire sclk, input wire rst_n, input wire byte_ready, input wire t_ready, input wire [WORD_SIZE-1:0] data_in, output wire serial_out ); wire bc_lt_bcmax; wire load_shiftreg; wire start; wire send; wire inc_bc_counter; wire clc_bc_counter; uart_xmt_controller uart_xmt_controller_inst( . sclk (sclk ), . rst_n (rst_n ), . byte_ready (byte_ready ), . t_ready (t_ready ), . bc_lt_bcmax (bc_lt_bcmax ), . load_shiftreg (load_shiftreg ), . start (start ), . send (send ), . inc_bc_counter (inc_bc_counter ), . clc_bc_counter (clc_bc_counter ) ); uart_xmt_datapath uart_xmt_datapath_inst( .sclk ( sclk ) , .rst_n ( rst_n ) , .load_shiftreg ( load_shiftreg ) , .start ( start ) , .send ( send ) , .inc_bc_counter ( inc_bc_counter ) , .clc_bc_counter ( clc_bc_counter ) , .data_in ( data_in ) , .bc_lt_bcmax ( bc_lt_bcmax ) , .serial_out ( serial_out ) ); endmodule
tb文件中
1.forever使用
2.task调用
`timescale 1ns/1ns module tb_uart_xmt #(parameter WORD_SIZE=8)(); reg sclk; reg rst_n; reg byte_ready; reg t_ready; reg [WORD_SIZE-1:0] data_in; wire serial_out; reg [WORD_SIZE+1:0] serial_test; wire[WORD_SIZE-1:0] test_word; initial begin sclk=0; forever #10 sclk=~sclk; end initial begin rst_n=0; #200 rst_n=1; end initial begin byte_ready=0;t_ready=0; data_in=0;serial_test=0; #210 gen_test_data();//调用task rec_test_data(); end initial begin serial_test=0; rec_test_data(); end uart_xmt uart_xmt_inst( . sclk (sclk ), . rst_n (rst_n ), . byte_ready (byte_ready ), . t_ready (t_ready ), . data_in (data_in ), . serial_out (serial_out ) ); //产生测试数据 task gen_test_data(); integer i; begin for(i=0;i<10;i=i+1)begin data_in=8'ha7+i; #10 byte_ready=1; #20 byte_ready=0; #60 t_ready=1; #20 t_ready=0; #350; end end endtask //测试数据回收是否正确 assign test_word=serial_test[WORD_SIZE:1]; task rec_test_data(); integer i,j; begin for(i=0;i<350;i=i+1)begin for(j=0;j<10;j=j+1)begin @(posedge sclk) serial_test={serial_out,serial_test[WORD_SIZE+1:1]};//向LSB移动 end end end endtask endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。