基于FPGA使用串口发送B码时间信息-强化篇

基于FPGA使用串口发送B码时间信息-强化篇

绘制模块框图及状态图

彩色模块是ip核,灰色模块的b_code和uart_tx直接调用之前的模块代码即可。

编写模块代码

uart_send_IRIG_data_top

module uart_send_IRIG_data_top( input wire clk , input wire rst_n , output wire tx ); wire clk_125Mhz ; wire locked ; wire ex_b_code ; wire [3:0] miao_gewei ; wire [2:0] miao_shiwei ; wire [3:0] fen_gewei ; wire [2:0] fen_shiwei ; wire [3:0] shi_gewei ; wire [1:0] shi_shiwei ; wire [3:0] day_gewei ; wire [3:0] day_shiwei ; wire [1:0] day_baiwei ; wire [3:0] year_gewei ; wire [3:0] year_shiwei ; wire send_done ; wire pi_flag ; wire [7:0] pi_data ; pll_125Mhz pll_125Mhz_inst ( .areset ( ~rst_n ), .inclk0 ( clk ), .c0 ( clk_125Mhz), .locked ( locked ) ); b_code_gen #( .TIME_1S ( 32'd124_999_999),//32'd124_999_999 .TIME_10MS ( 32'd1_249_999 ),//32'd1_249_999 .TIME_8MS ( 32'd999_999 ),//32'd999_999 .TIME_5MS ( 32'd624_999 ),//32'd624_999 .TIME_2MS ( 32'd249_999 )//32'd249_999 ) b_code_gen_inst ( .clk (clk_125Mhz),//125Mhz .rst_n (locked ), .ex_b_code (ex_b_code ) ); b_code #( .TIME_10MS ( 32'd1_249_999),//32'd1_249_999 .TIME_8MS ( 32'd999_999 ),//32'd999_999 .TIME_2MS ( 32'd249_999 ),//32'd249_999 .TIME_5MS ( 32'd624_999 ),//32'd624_999 .WUCHA_8US ( 32'd1000 ) //32'd1000 ) b_code_inst ( .clk_125Mhz (clk_125Mhz ), .rst_n (locked ), .ex_b_code (ex_b_code ), .miao_gewei (miao_gewei ), .miao_shiwei (miao_shiwei), .fen_gewei (fen_gewei ), .fen_shiwei (fen_shiwei ), .shi_gewei (shi_gewei ), .shi_shiwei (shi_shiwei ), .day_gewei (day_gewei ), .day_shiwei (day_shiwei ), .day_baiwei (day_baiwei ), .year_gewei (year_gewei ), .year_shiwei (year_shiwei) ); fsm #( .TIME_1S (32'd124_999_999)//32'd124_999_999 ) fsm_inst ( .clk (clk_125Mhz ), .rst_n (locked ), .send_done (send_done ),//控制串口发送信号线 .miao_gewei (miao_gewei ), .miao_shiwei (miao_shiwei), .fen_gewei (fen_gewei ), .fen_shiwei (fen_shiwei ), .shi_gewei (shi_gewei ), .shi_shiwei (shi_shiwei ), .day_gewei (day_gewei ), .day_shiwei (day_shiwei ), .day_baiwei (day_baiwei ), .year_gewei (year_gewei ), .year_shiwei (year_shiwei), .pi_flag (pi_flag ), .pi_data (pi_data ) ); uart_tx #( .CLK_FREQ ('d124_999_999), .BPS ('d9600 ) ) uart_tx_inst ( .clk (clk_125Mhz ) , .rst_n (locked ) , .pi_flag (pi_flag ) , .pi_data (pi_data ) , .send_done (send_done ) , .tx (tx ) ); endmodule

b_code_gen

module b_code_gen #( parameter TIME_1S = 32'd124_999_999, parameter TIME_10MS = 32'd1_249_999 , parameter TIME_8MS = 32'd999_999 , parameter TIME_5MS = 32'd624_999 , parameter TIME_2MS = 32'd249_999 ) ( input wire clk ,//125Mhz input wire rst_n , output reg ex_b_code ); parameter idle = 8'd0; parameter s0 = 8'd1; parameter s1 = 8'd2; parameter s2 = 8'd3; parameter s3 = 8'd4; parameter s4 = 8'd5; parameter s5 = 8'd6; //给3个基本码元类型编码 parameter MAYUAN_P = 8'h50; parameter MAYUAN_0 = 8'h30; parameter MAYUAN_1 = 8'h31; parameter MAYUAN_NUM = 'd100; //定义B码的一帧数据的数组,B码一帧数据有100个码元 wire [7:0] mem [99:0]; //26年154天12时59分48秒 assign mem[0] = MAYUAN_P;//位置分隔符 assign mem[1] = MAYUAN_P; assign mem[2] = MAYUAN_0;//秒个位 assign mem[3] = MAYUAN_0; assign mem[4] = MAYUAN_0; assign mem[5] = MAYUAN_1; assign mem[6] = MAYUAN_0;//索引标志,置0 assign mem[7] = MAYUAN_0;//秒十位 assign mem[8] = MAYUAN_0; assign mem[9] = MAYUAN_1; assign mem[10] = MAYUAN_P;//位置分隔符 assign mem[11] = MAYUAN_1;//分个位 assign mem[12] = MAYUAN_0; assign mem[13] = MAYUAN_0; assign mem[14] = MAYUAN_1; assign mem[15] = MAYUAN_0;//索引标志,置0 assign mem[16] = MAYUAN_1;//分十位 assign mem[17] = MAYUAN_0; assign mem[18] = MAYUAN_1; assign mem[19] = MAYUAN_0;//保留,置0 assign mem[20] = MAYUAN_P;//位置分隔符 assign mem[21] = MAYUAN_0;//时个位 assign mem[22] = MAYUAN_1; assign mem[23] = MAYUAN_0; assign mem[24] = MAYUAN_0; assign mem[25] = MAYUAN_0;//索引标志,置0 assign mem[26] = MAYUAN_1;//时十位 assign mem[27] = MAYUAN_0; assign mem[28] = MAYUAN_0;//保留,置0 assign mem[29] = MAYUAN_0;//保留,置0 assign mem[30] = MAYUAN_P;//位置分隔符 assign mem[31] = MAYUAN_0;//日个位 assign mem[32] = MAYUAN_0; assign mem[33] = MAYUAN_1; assign mem[34] = MAYUAN_0; assign mem[35] = MAYUAN_0;//索引标志,置0 assign mem[36] = MAYUAN_1;//日十位 assign mem[37] = MAYUAN_0; assign mem[38] = MAYUAN_1; assign mem[39] = MAYUAN_0; assign mem[40] = MAYUAN_P;//位置分隔符 assign mem[41] = MAYUAN_1;//日百位 assign mem[42] = MAYUAN_0; assign mem[43] = MAYUAN_0;//保留,置0 assign mem[44] = MAYUAN_0;//保留,置0 assign mem[45] = MAYUAN_0;//保留,置0 assign mem[46] = MAYUAN_0;//保留,置0 assign mem[47] = MAYUAN_0;//保留,置0 assign mem[48] = MAYUAN_0;//保留,置0 assign mem[49] = MAYUAN_0;//保留,置0 assign mem[50] = MAYUAN_P;//位置分隔符 assign mem[51] = MAYUAN_0;//年个位 assign mem[52] = MAYUAN_1; assign mem[53] = MAYUAN_1; assign mem[54] = MAYUAN_0; assign mem[55] = MAYUAN_0;//索引标志,置0 assign mem[56] = MAYUAN_0;//年十位 assign mem[57] = MAYUAN_1; assign mem[58] = MAYUAN_0; assign mem[59] = MAYUAN_0; assign mem[60] = MAYUAN_P;//p//位置分隔符 assign mem[61] = MAYUAN_0;//0//闰秒预告LSP assign mem[62] = MAYUAN_0;//0//闰秒标志LS assign mem[63] = MAYUAN_0;//0//夏制时预告DSP assign mem[64] = MAYUAN_0;//0//夏制时标志DST assign mem[65] = MAYUAN_0;//0//时间偏移符号位 assign mem[66] = MAYUAN_0;//0 assign mem[67] = MAYUAN_0;//0 assign mem[68] = MAYUAN_0;//0 assign mem[69] = MAYUAN_0;//0 assign mem[70] = MAYUAN_P;//p位置分隔符 assign mem[71] = MAYUAN_0;//0不增加时间偏移量 assign mem[72] = MAYUAN_0;//0正常工作状态 assign mem[73] = MAYUAN_0;//0正常工作状态 assign mem[74] = MAYUAN_0;//0正常工作状态 assign mem[75] = MAYUAN_0;//0正常工作状态 assign mem[76] = MAYUAN_1;//1(校验位) assign mem[77] = MAYUAN_0;//0//保留,置0 assign mem[78] = MAYUAN_0;//0//保留,置0 assign mem[79] = MAYUAN_0;//0//保留,置0 assign mem[80] = MAYUAN_P;//位置分隔符 assign mem[81] = MAYUAN_0;//0 //一天中的秒数(二进制低9位) assign mem[82] = MAYUAN_0;//0 //一天中的秒数86400 assign mem[83] = MAYUAN_0;//0 assign mem[84] = MAYUAN_0;//0 assign mem[85] = MAYUAN_0;//0 assign mem[86] = MAYUAN_0;//0 assign mem[87] = MAYUAN_0;//0 assign mem[88] = MAYUAN_1;//1 assign mem[89] = MAYUAN_1;//1 assign mem[90] = MAYUAN_P;//位置分隔符 assign mem[91] = MAYUAN_0;//0 //一天中的秒数(二进制高9位) assign mem[92] = MAYUAN_0;//0 assign mem[93] = MAYUAN_0;//0 assign mem[94] = MAYUAN_1;//1 assign mem[95] = MAYUAN_0;//0 assign mem[96] = MAYUAN_1;//1 assign mem[97] = MAYUAN_0;//0 assign mem[98] = MAYUAN_1;//1 assign mem[99] = MAYUAN_0;//0 reg [7:0] state ; reg [31:0] cnt_10ms ; reg [7:0] index ; reg [7:0] cnt_mayuan ; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin state <= idle; cnt_10ms <= 32'd0; index <= 8'd0; cnt_mayuan <= 8'd0; ex_b_code <= 1'b0; end else case(state) idle: begin state <= s0; cnt_10ms <= 32'd0; index <= 8'd0; cnt_mayuan <= 8'd0; ex_b_code <= 1'b0; end s0 : begin if(mem[index] == MAYUAN_P) state <= s1; else if(mem[index] == MAYUAN_0) state <= s2; else// if(mem[index] == MAYUAN_1) state <= s3; end s1 : begin if(cnt_10ms == TIME_10MS) begin state <= s4; cnt_10ms <= 32'd0; end else if(cnt_10ms <= TIME_8MS) begin ex_b_code <= 1'b1; cnt_10ms <= cnt_10ms + 1'b1; end else begin ex_b_code <= 1'b0; cnt_10ms <= cnt_10ms + 1'b1; end end s2 : begin if(cnt_10ms == TIME_10MS) begin state <= s4; cnt_10ms <= 32'd0; end else if(cnt_10ms <= TIME_2MS) begin ex_b_code <= 1'b1; cnt_10ms <= cnt_10ms + 1'b1; end else begin ex_b_code <= 1'b0; cnt_10ms <= cnt_10ms + 1'b1; end end s3 : begin if(cnt_10ms == TIME_10MS) begin state <= s4; cnt_10ms <= 32'd0; end else if(cnt_10ms <= TIME_5MS) begin ex_b_code <= 1'b1; cnt_10ms <= cnt_10ms + 1'b1; end else begin ex_b_code <= 1'b0; cnt_10ms <= cnt_10ms + 1'b1; end end s4 : begin index <= index + 1'b1; cnt_mayuan <= cnt_mayuan + 1'b1; state <= s5; end s5 : begin if(cnt_mayuan == MAYUAN_NUM) state <= idle; else state <= s0; end default: begin state <= idle; cnt_10ms <= 32'd0; index <= 8'd0; cnt_mayuan <= 8'd0; ex_b_code <= 1'b0; end endcase end endmodule

b_code

module b_code #( parameter TIME_10MS = 32'd1_249_999, parameter TIME_8MS = 32'd999_999 , parameter TIME_2MS = 32'd249_999 , parameter TIME_5MS = 32'd629_999 , parameter WUCHA_8US = 32'd1000 ) ( input wire clk_125Mhz , input wire rst_n , input wire ex_b_code , output reg [3:0] miao_gewei , output reg [2:0] miao_shiwei , output reg [3:0] fen_gewei , output reg [2:0] fen_shiwei , output reg [3:0] shi_gewei , output reg [1:0] shi_shiwei , output reg [3:0] day_gewei , output reg [3:0] day_shiwei , output reg [1:0] day_baiwei , output reg [3:0] year_gewei , output reg [3:0] year_shiwei ); // 消除ex_b_code亚稳态,提高信号质量 reg ex_b_code_0; reg ex_b_code_1; reg ex_b_code_2; reg fall_0 ;//用于确定当前码元类型(now_type) reg fall_1 ;//同时有锁定的码元类型(latch_type)和当前码元类型(now_type),用于开始信号双p检测 reg fall_2 ;//更新锁定的上一个码元信息(latch_type) reg fall_3 ;//用于定位一帧数据中当前码元对应的序号 reg fall_4 ;//用于完成当前码元的时间信息解析 reg fall_5 ;//用于全部解析完成的整体输出 reg fall_6 ;//预留 reg fall_7 ;//用于高电平计数器计数值的清零(高电平计数器:计数高电平保持时常确定码元) reg [31:0] cnt_b ; reg [1:0] now_type ; reg work_state ; reg [1:0] latch_type ; reg [7:0] cnt_mem ; // 多级打拍处理,消除ex_b_code亚稳态,提高信号质量,下降沿检测 always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) begin ex_b_code_0 <= 1'b0; ex_b_code_1 <= 1'b0; ex_b_code_2 <= 1'b0; fall_0 <= 1'b0; fall_1 <= 1'b0; fall_2 <= 1'b0; fall_3 <= 1'b0; fall_4 <= 1'b0; fall_5 <= 1'b0; fall_6 <= 1'b0; fall_7 <= 1'b0; end else begin ex_b_code_0 <= ex_b_code ; ex_b_code_1 <= ex_b_code_0 ; ex_b_code_2 <= ex_b_code_1 ; fall_0 <= ~ex_b_code_1 && ex_b_code_2; fall_1 <= fall_0 ; fall_2 <= fall_1 ; fall_3 <= fall_2 ; fall_4 <= fall_3 ; fall_5 <= fall_4 ; fall_6 <= fall_5 ; fall_7 <= fall_6 ; end end // cnt_b:高电平计数器,低电平保持,fall_7清零 always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) cnt_b <= 32'd0; else if(fall_7)//注意优先级 cnt_b <= 32'd0; else if(ex_b_code_2) cnt_b <= cnt_b + 1'b1; else cnt_b <= cnt_b; end // now_type:当前码元类型 0码:00;1码:01;p码:10 always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) now_type <= 2'b11 ; else if(fall_0 && TIME_8MS - WUCHA_8US <= cnt_b && cnt_b <= TIME_8MS + WUCHA_8US) now_type <= 2'b10 ;//p else if(fall_0 && TIME_5MS - WUCHA_8US <= cnt_b && cnt_b <= TIME_5MS + WUCHA_8US) now_type <= 2'b01 ;//1 else if(fall_0 && TIME_2MS - WUCHA_8US <= cnt_b && cnt_b <= TIME_2MS + WUCHA_8US) now_type <= 2'b00 ;//0 else if(fall_0) now_type <= 2'b11 ;//出现错码 else now_type <= now_type; end // latch_type:锁定上一个码元 always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) latch_type <= 2'b11 ; else if(fall_2) latch_type <= now_type ; else latch_type <= latch_type; end // work_state:工作状态(双p检测) always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) work_state <= 1'b0; else if(fall_1 && now_type == 2'b10 && latch_type == 2'b10) work_state <= 1'b1; else if(cnt_mem == 8'd61) work_state <= 1'b0; else work_state <= work_state; end // cnt_mem:码元序号 always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) cnt_mem <= 8'd0; else if(~work_state) cnt_mem <= 8'd0; else if(fall_3) cnt_mem <= cnt_mem + 1'b1; else cnt_mem <= cnt_mem; end // 时间输出寄存器(为了统一输出时间) reg [3:0] miao_gewei_r ; reg [2:0] miao_shiwei_r; reg [3:0] fen_gewei_r ; reg [2:0] fen_shiwei_r ; reg [3:0] shi_gewei_r ; reg [1:0] shi_shiwei_r ; reg [3:0] day_gewei_r ; reg [3:0] day_shiwei_r ; reg [1:0] day_baiwei_r ; reg [3:0] year_gewei_r ; reg [3:0] year_shiwei_r; /////////////秒个位时间信息 序号2~5 miao_gewei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) miao_gewei_r <= 4'd0; else if(fall_4 && 8'd2 <= cnt_mem && cnt_mem <= 8'd5) miao_gewei_r <= {now_type[0],miao_gewei_r[3:1]}; else miao_gewei_r <= miao_gewei_r; end /////////////秒十位时间信息 序号7~9 miao_shiwei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) miao_shiwei_r <= 3'd0; else if(fall_4 && 8'd7 <= cnt_mem && cnt_mem <= 8'd9) miao_shiwei_r <= {now_type[0],miao_shiwei_r[2:1]}; else miao_shiwei_r <= miao_shiwei_r; end /////////////分个位时间信息 序号11~14 fen_gewei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) fen_gewei_r <= 4'd0; else if(fall_4 && 8'd11 <= cnt_mem && cnt_mem <= 8'd14) fen_gewei_r <= {now_type[0],fen_gewei_r[3:1]}; else fen_gewei_r <= fen_gewei_r; end /////////////分十位时间信息 序号16~18 fen_shiwei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) fen_shiwei_r <= 3'd0; else if(fall_4 && 8'd16 <= cnt_mem && cnt_mem <= 8'd18) fen_shiwei_r <= {now_type[0],fen_shiwei_r[2:1]}; else fen_shiwei_r <= fen_shiwei_r; end /////////////时个位时间信息 序号21~24 shi_gewei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) shi_gewei_r <= 4'd0; else if(fall_4 && 8'd21 <= cnt_mem && cnt_mem <= 8'd24) shi_gewei_r <= {now_type[0],shi_gewei_r[3:1]}; else shi_gewei_r <= shi_gewei_r; end /////////////时十位时间信息 序号26~27 shi_shiwei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) shi_shiwei_r <= 2'd0; else if(fall_4 && 8'd26 <= cnt_mem && cnt_mem <= 8'd27) shi_shiwei_r <= {now_type[0],shi_shiwei_r[1]}; else shi_shiwei_r <= shi_shiwei_r; end /////////////日个位时间信息 序号31~34 day_gewei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) day_gewei_r <= 4'd0; else if(fall_4 && 8'd31 <= cnt_mem && cnt_mem <= 8'd34) day_gewei_r <= {now_type[0],day_gewei_r[3:1]}; else day_gewei_r <= day_gewei_r; end /////////////日十位时间信息 序号36~39 day_shiwei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) day_shiwei_r <= 4'd0; else if(fall_4 && 8'd36 <= cnt_mem && cnt_mem <= 8'd39) day_shiwei_r <= {now_type[0],day_shiwei_r[3:1]}; else day_shiwei_r <= day_shiwei_r; end /////////////日百位时间信息 序号41~42 day_baiwei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) day_baiwei_r <= 2'd0; else if(fall_4 && 8'd41 <= cnt_mem && cnt_mem <= 8'd42) day_baiwei_r <= {now_type[0],day_baiwei_r[1]}; else day_baiwei_r <= day_baiwei_r; end /////////////年个位时间信息 序号51~54 year_gewei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) year_gewei_r <= 4'd0; else if(fall_4 && 8'd51 <= cnt_mem && cnt_mem <= 8'd54) year_gewei_r <= {now_type[0],year_gewei_r[3:1]}; else year_gewei_r <= year_gewei_r; end /////////////年十位时间信息 序号56~59 year_shiwei_r always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) year_shiwei_r <= 4'd0; else if(fall_4 && 8'd56 <= cnt_mem && cnt_mem <= 8'd59) year_shiwei_r <= {now_type[0],year_shiwei_r[3:1]}; else year_shiwei_r <= year_shiwei_r; end ///////////////////////////////////////////////////////////// // 统一输出 always@(posedge clk_125Mhz or negedge rst_n) begin if(!rst_n) begin miao_gewei <= 4'd0; miao_shiwei <= 3'd0; fen_gewei <= 4'd0; fen_shiwei <= 3'd0; shi_gewei <= 4'd0; shi_shiwei <= 2'd0; day_gewei <= 4'd0; day_shiwei <= 4'd0; day_baiwei <= 2'd0; year_gewei <= 4'd0; year_shiwei <= 4'd0; end else if(fall_5 && cnt_mem == 8'd60) begin miao_gewei <= miao_gewei_r ; miao_shiwei <= miao_shiwei_r; fen_gewei <= fen_gewei_r ; fen_shiwei <= fen_shiwei_r ; shi_gewei <= shi_gewei_r ; shi_shiwei <= shi_shiwei_r ; day_gewei <= day_gewei_r ; day_shiwei <= day_shiwei_r ; day_baiwei <= day_baiwei_r ; year_gewei <= year_gewei_r ; year_shiwei <= year_shiwei_r; end else begin miao_gewei <= miao_gewei ; miao_shiwei <= miao_shiwei ; fen_gewei <= fen_gewei ; fen_shiwei <= fen_shiwei ; shi_gewei <= shi_gewei ; shi_shiwei <= shi_shiwei ; day_gewei <= day_gewei ; day_shiwei <= day_shiwei ; day_baiwei <= day_baiwei ; year_gewei <= year_gewei ; year_shiwei <= year_shiwei ; end end endmodule

fsm

module fsm #( parameter TIME_1S = 32'd50_000_000 ) ( input wire clk , input wire rst_n , input wire send_done ,//控制串口发送信号线 input wire [3:0] miao_gewei , input wire [2:0] miao_shiwei , input wire [3:0] fen_gewei , input wire [2:0] fen_shiwei , input wire [3:0] shi_gewei , input wire [1:0] shi_shiwei , input wire [3:0] day_gewei , input wire [3:0] day_shiwei , input wire [1:0] day_baiwei , input wire [3:0] year_gewei , input wire [3:0] year_shiwei , output reg pi_flag , output reg [7:0] pi_data ); //parameter TIME_1S = 32'd50_000;//用于仿真测试,缩短仿真时间 parameter BYTE_NUM = 32'd14 ;//发送的字节数 parameter idle = 8'd0; parameter s0 = 8'd1; parameter s1 = 8'd2; parameter s2 = 8'd3; parameter s3 = 8'd4; //定义一个数组,存放8个字节需要发送的数据 wire [7:0] mem [0:13]; assign mem[0] = 8'h55;//帧头 assign mem[1] = 8'h55; assign mem[2] = 8'h55; assign mem[3] = {4'd0,miao_gewei [3:0] };//秒个位,1个字节 assign mem[4] = {5'd0,miao_shiwei [2:0] };//秒十位,1个字节 assign mem[5] = {4'd0,fen_gewei [3:0]};//分个位,1个字节 assign mem[6] = {5'd0,fen_shiwei [2:0]};//分十位,1个字节 assign mem[7] = {4'd0,shi_gewei [3:0]};//时个位,1个字节 assign mem[8] = {6'd0,shi_shiwei [1:0]};//时十位,1个字节 assign mem[9] = {4'd0,day_gewei [3:0]};//天个位,1个字节 assign mem[10] = {4'd0,day_shiwei [3:0]};//天十位,1个字节 assign mem[11] = {6'd0,day_baiwei [1:0]};//天百位,1个字节 assign mem[12] = {4'd0,year_gewei [3:0]};//年个位,1个字节 assign mem[13] = {4'd0,year_shiwei [3:0]};//年十位,1个字节 reg [7:0] state; //内部变量的定义 reg [31:0] delay_cnt; reg [7:0] send_done_cnt; reg [7:0] index; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin delay_cnt <= 32'd0; send_done_cnt <= 8'd0; index <= 8'd0; state <= idle; pi_flag <= 1'b0; pi_data <= 8'd0; end else begin case(state) idle: begin if(delay_cnt == TIME_1S) begin delay_cnt <= 32'd0; send_done_cnt <= 8'd0; pi_flag <= 1'b0; pi_data <= 8'd0; index <= 8'd0; state <= s0 ; end else begin state <= state; delay_cnt <= delay_cnt + 1'b1; end end s0 : begin pi_flag <= 1'b1; pi_data <= mem[index]; state <= s1; end s1 : begin pi_flag <= 1'b0; if(send_done) begin state <= s2; send_done_cnt <= send_done_cnt + 1'b1; index <= index + 1'b1; end else begin state <= state; send_done_cnt <= send_done_cnt; index <= index; end end s2 : begin if(send_done_cnt == BYTE_NUM) state <= s3; else state <= s0; end s3 : begin delay_cnt <= 32'd0; send_done_cnt <= 8'd0; index <= 8'd0; state <= idle; pi_flag <= 1'b0; pi_data <= 8'd0; end default: begin delay_cnt <= 32'd0; send_done_cnt <= 8'd0; index <= 8'd0; state <= idle; pi_flag <= 1'b0; pi_data <= 8'd0; end endcase end end endmodule

uart_tx

module uart_tx #( parameter CLK_FREQ = 'd124_999_999 , parameter BPS = 'd9600 ) ( input wire clk , input wire rst_n , input wire pi_flag , input wire [7:0] pi_data , output reg send_done , output reg tx ); localparam BAUD_TIME= CLK_FREQ / BPS ; parameter idle = 8'd0 ; parameter s0 = 8'd1 ; parameter s1 = 8'd2 ; parameter s2 = 8'd3 ; parameter s3 = 8'd4 ; parameter s4 = 8'd5 ; parameter s5 = 8'd6 ; parameter s6 = 8'd7 ; parameter s7 = 8'd8 ; parameter s8 = 8'd9 ; parameter s9 = 8'd10; parameter s10 = 8'd11; parameter done = 8'd12; reg [7:0] state ; reg [15:0] delay_cnt ; reg [9:0] send_data ; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin state <= idle; delay_cnt <= 16'd0; send_done <= 1'b0; tx <= 1'b1; send_data <= 10'd0; end else case(state) idle: begin if(pi_flag) state <= s0; else state <= state; delay_cnt <= 16'd0; tx <= 1'b1; send_done <= 1'b0; end s0 : begin send_data <= {1'b1,pi_data[7:0],1'b0}; state <= s1; end s1 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s2; delay_cnt <= 16'd0; end else begin tx <= send_data[0]; delay_cnt <= delay_cnt + 1'b1; end end s2 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s3; delay_cnt <= 16'd0; end else begin tx <= send_data[1]; delay_cnt <= delay_cnt + 1'b1; end end s3 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s4; delay_cnt <= 16'd0; end else begin tx <= send_data[2]; delay_cnt <= delay_cnt + 1'b1; end end s4 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s5; delay_cnt <= 16'd0; end else begin tx <= send_data[3]; delay_cnt <= delay_cnt + 1'b1; end end s5 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s6; delay_cnt <= 16'd0; end else begin tx <= send_data[4]; delay_cnt <= delay_cnt + 1'b1; end end s6 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s7; delay_cnt <= 16'd0; end else begin tx <= send_data[5]; delay_cnt <= delay_cnt + 1'b1; end end s7 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s8; delay_cnt <= 16'd0; end else begin tx <= send_data[6]; delay_cnt <= delay_cnt + 1'b1; end end s8 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s9; delay_cnt <= 16'd0; end else begin tx <= send_data[7]; delay_cnt <= delay_cnt + 1'b1; end end s9 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= s10; delay_cnt <= 16'd0; end else begin tx <= send_data[8]; delay_cnt <= delay_cnt + 1'b1; end end s10 : begin if(delay_cnt == BAUD_TIME - 1'b1) begin state <= done; delay_cnt <= 16'd0; end else begin tx <= send_data[9]; delay_cnt <= delay_cnt + 1'b1; end end done: begin state <= idle; send_done <= 1'b1; end default: begin state <= idle; delay_cnt <= 16'd0; send_done <= 1'b0; tx <= 1'b1; end endcase end endmodule

编写仿真代码

`timescale 1ns/1ps module uart_send_IRIG_data_top_tb(); reg clk ; reg rst_n ; initial begin clk = 1'b0; rst_n = 1'b0; #123 rst_n = 1'b1; end always #10 clk = ~clk; defparam uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_1S = 32'd124_999; defparam uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_10MS = 32'd1_249 ; defparam uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_8MS = 32'd999 ; defparam uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_5MS = 32'd624 ; defparam uart_send_IRIG_data_top_inst.b_code_gen_inst.TIME_2MS = 32'd249 ; defparam uart_send_IRIG_data_top_inst.b_code_inst.TIME_10MS = 32'd1_249; defparam uart_send_IRIG_data_top_inst.b_code_inst.TIME_8MS = 32'd999 ; defparam uart_send_IRIG_data_top_inst.b_code_inst.TIME_2MS = 32'd249 ; defparam uart_send_IRIG_data_top_inst.b_code_inst.TIME_5MS = 32'd624 ; defparam uart_send_IRIG_data_top_inst.b_code_inst.WUCHA_8US = 32'd10 ; defparam uart_send_IRIG_data_top_inst.fsm_inst.TIME_1S = 32'd124_999; defparam uart_send_IRIG_data_top_inst.uart_tx_inst.CLK_FREQ = 'd124_999_999; defparam uart_send_IRIG_data_top_inst.uart_tx_inst.BPS = 'd9600 ; uart_send_IRIG_data_top uart_send_IRIG_data_top_inst( .clk (clk ), .rst_n (rst_n ), .tx () ); endmodule

仿真验证

可以看出顶层没问题。

上板验证