当前位置: 首页 > news >正文

zynq串口的例子

vio_uart

功能

vio_uart 是一个内存映射接口,

o_acq_gram_x(地址范围 0~16) 是采集寄存器

i_ctrl_gram_x (地址范围 17~29) 是控制寄存器

帧格式

读写标志: 0读 1写(1字节)地址 (1字节)数据 (4字节)

uart_tx.v

module uart_tx(// from systeminput                   i_sys_clk       ,input                   i_sys_reset_n   ,input                   i_uart_tx_en    ,input           [7 : 0] i_uart_tx_data  ,output  reg             or_uart_tx_busy , // 发送中标志// outputoutput  reg             or_uart_txd
);// parameter define
parameter   CLK_FREQ     = 50000000;
parameter   UART_BPS     = 115200;
localparam  BAUD_CNT_MAX = CLK_FREQ / UART_BPS;// reg define
reg [3:0]   r_tx_cnt;
reg [15:0]  r_baud_cnt;
reg [7 :0]  r_tx_data_t;
reg         r_uart_tx_en_d;//i_uart_tx_en的上升沿
wire        w_uart_tx_en_posedge;// detect i_uart_tx_en rising edge
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n)r_uart_tx_en_d <= 1'b0;elser_uart_tx_en_d <= i_uart_tx_en;
endassign w_uart_tx_en_posedge = i_uart_tx_en && !r_uart_tx_en_d;// baud rate counter
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n)r_baud_cnt <= 16'd0;else if (or_uart_tx_busy) beginif (r_baud_cnt == BAUD_CNT_MAX - 1)r_baud_cnt <= 16'd0;elser_baud_cnt <= r_baud_cnt + 1'b1;end else beginr_baud_cnt <= 16'd0;end
end// tx bit counter
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n)r_tx_cnt <= 4'd0;else if (or_uart_tx_busy && (r_baud_cnt == BAUD_CNT_MAX - 1))r_tx_cnt <= r_tx_cnt + 1'b1;else if (!or_uart_tx_busy)r_tx_cnt <= 4'd0;
end// control busy and latch data
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n) beginr_tx_data_t     <= 8'd0;or_uart_tx_busy <= 1'b0;endelse if (w_uart_tx_en_posedge && !or_uart_tx_busy) beginr_tx_data_t     <= i_uart_tx_data;or_uart_tx_busy <= 1'b1;endelse if (or_uart_tx_busy && r_tx_cnt == 4'd9 && r_baud_cnt == BAUD_CNT_MAX - 1) beginor_uart_tx_busy <= 1'b0;end
end// generate txd signal
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n)or_uart_txd <= 1'b1;else if (or_uart_tx_busy) begincase(r_tx_cnt)4'd0 : or_uart_txd <= 1'b0;               // start bit4'd1 : or_uart_txd <= r_tx_data_t[0];4'd2 : or_uart_txd <= r_tx_data_t[1];4'd3 : or_uart_txd <= r_tx_data_t[2];4'd4 : or_uart_txd <= r_tx_data_t[3];4'd5 : or_uart_txd <= r_tx_data_t[4];4'd6 : or_uart_txd <= r_tx_data_t[5];4'd7 : or_uart_txd <= r_tx_data_t[6];4'd8 : or_uart_txd <= r_tx_data_t[7];4'd9 : or_uart_txd <= 1'b1;               // stop bitdefault : or_uart_txd <= 1'b1;endcaseendelseor_uart_txd <= 1'b1;
endendmodule

uart_rx.v

module uart_rx(input           i_sys_clk       ,input           i_sys_reset_n   ,input           i_uart_rxd      ,output  reg     or_uart_rx_done ,output  reg [7:0] or_uart_rx_data
);//parameter define
parameter   CLK_FREQ    =   50000000   ;
parameter   UART_BPS    =   115200     ;
localparam   BAUD_CNT_MAX=   CLK_FREQ/UART_BPS   ;//reg define
reg             r_uart_rxd0  ;
reg             r_uart_rxd1  ;
reg             r_uart_rxd2  ;
reg             r_rx_flag    ; //正在接收中的标志
reg     [3:0]   r_rx_cnt     ;
reg     [15:0]  r_baud_cnt   ;
reg     [7:0]   r_rx_data_t  ;//wire define
wire            w_start_en;
////////////////////////////////////////////////////////////////////
//*************************main code******************************
//////////////////////////////////////////////////////////////////////i_uart_rxd negedge
assign w_start_en = r_uart_rxd2 & (~r_uart_rxd1) & (~r_rx_flag);//async signal input delay
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif(!i_sys_reset_n) beginr_uart_rxd0 <= 1'b0 ;r_uart_rxd1 <= 1'b0 ;r_uart_rxd2 <= 1'b0 ;endelse beginr_uart_rxd0 <= i_uart_rxd ;r_uart_rxd1 <= r_uart_rxd0 ;r_uart_rxd2 <= r_uart_rxd1 ;end
end//generate r_baud_cnt
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif(!i_sys_reset_n)r_baud_cnt <= 16'd0;else if(r_rx_flag) beginif(r_baud_cnt == BAUD_CNT_MAX - 1'b1)r_baud_cnt <= 16'd0;elser_baud_cnt <= r_baud_cnt + 16'b1;endelser_baud_cnt <= 16'd0;
end//generate r_rx_cnt
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif(!i_sys_reset_n) beginr_rx_cnt <= 4'd0;endelse if(r_rx_flag) beginif(r_baud_cnt == BAUD_CNT_MAX - 1'b1)r_rx_cnt <= r_rx_cnt + 1'b1;elser_rx_cnt <= r_rx_cnt;endelser_rx_cnt <= 4'd0;
end//generate r_rx_flag
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif(!i_sys_reset_n)r_rx_flag <= 1'b0;else if(w_start_en)r_rx_flag <= 1'b1;else if((r_rx_cnt == 4'd9) && (r_baud_cnt == BAUD_CNT_MAX/2 - 1'b1))r_rx_flag <= 1'b0;elser_rx_flag <= r_rx_flag;
endalways @(posedge i_sys_clk or negedge i_sys_reset_n) beginif(!i_sys_reset_n)r_rx_data_t <= 8'b0;else if(r_rx_flag) beginif(r_baud_cnt == BAUD_CNT_MAX/2 - 1'b1) begincase(r_rx_cnt)4'd1 : r_rx_data_t[0] <= r_uart_rxd2;4'd2 : r_rx_data_t[1] <= r_uart_rxd2;4'd3 : r_rx_data_t[2] <= r_uart_rxd2;4'd4 : r_rx_data_t[3] <= r_uart_rxd2;4'd5 : r_rx_data_t[4] <= r_uart_rxd2;4'd6 : r_rx_data_t[5] <= r_uart_rxd2;4'd7 : r_rx_data_t[6] <= r_uart_rxd2;4'd8 : r_rx_data_t[7] <= r_uart_rxd2;default : ;endcaseendelser_rx_data_t <= r_rx_data_t;endelser_rx_data_t <= 8'b0;
endalways @(posedge i_sys_clk or negedge i_sys_reset_n) beginif(!i_sys_reset_n) beginor_uart_rx_done <= 1'b0;or_uart_rx_data <= 8'b0;endelse if(r_rx_cnt == 4'd9 && r_baud_cnt == BAUD_CNT_MAX/2 - 1'b1) beginor_uart_rx_done <= 1'b1;or_uart_rx_data <= r_rx_data_t;endelse beginor_uart_rx_done <= 1'b0;or_uart_rx_data <= or_uart_rx_data;end
endendmodule

vio_uart.v

/**
读地址0x00:00 00 [00 00 00 00]
写地址0x00:01 00 [01 00 00 02]
**/
module vio_uart #(parameter P_DATA_LEN = 6, //一 帧字节数parameter CLK_FREQ = 50_000_000
)(input               i_sys_clk       ,input               i_sys_reset_n   ,input               i_uart_rxd      ,output              o_uart_txd,output reg          o_recv_acq_done,  //采集完成output reg          o_recv_ctrl_done, //控制完成//0:禁用采集  1:启用采集input        i_acq_en,//采集完成的中断脉冲output  reg     o_acq_done_irq_pulse,/***  采集  ***/output [31:0] o_acq_gram_0,output [31:0] o_acq_gram_1,output [31:0] o_acq_gram_2,output [31:0] o_acq_gram_3,output [31:0] o_acq_gram_4,output [31:0] o_acq_gram_5,output [31:0] o_acq_gram_6,output [31:0] o_acq_gram_7,output [31:0] o_acq_gram_8,output [31:0] o_acq_gram_9,output [31:0] o_acq_gram_10,output [31:0] o_acq_gram_11,output [31:0] o_acq_gram_12,output [31:0] o_acq_gram_13,output [31:0] o_acq_gram_14,output [31:0] o_acq_gram_15,output [31:0] o_acq_gram_16,/***  控制  ***/input [31:0]  i_ctrl_gram_0,//17input [31:0]  i_ctrl_gram_1,//18input [31:0]  i_ctrl_gram_2,//19input [31:0]  i_ctrl_gram_3,//20input [31:0]  i_ctrl_gram_4,//21input [31:0]  i_ctrl_gram_5,//22input [31:0]  i_ctrl_gram_6,//23input [31:0]  i_ctrl_gram_7,//24input [31:0]  i_ctrl_gram_8,//25input [31:0]  i_ctrl_gram_9,//26input [31:0]  i_ctrl_gram_10,//27input [31:0]  i_ctrl_gram_11,//28input [31:0]  i_ctrl_gram_12//29);// ========== RX / TX 接口 ==========
wire        w_rx_done;
wire [7:0]  w_rx_data;reg         r_tx_en;
reg [7:0]   r_tx_data;
wire        w_tx_busy;uart_rx uart_rx_inst (.i_sys_clk       (i_sys_clk),.i_sys_reset_n   (i_sys_reset_n),.i_uart_rxd      (i_uart_rxd),.or_uart_rx_done (w_rx_done),.or_uart_rx_data (w_rx_data)
);uart_tx uart_tx_inst (.i_sys_clk        (i_sys_clk),.i_sys_reset_n    (i_sys_reset_n),.i_uart_tx_en     (r_tx_en),.i_uart_tx_data   (r_tx_data),.or_uart_tx_busy  (w_tx_busy),.or_uart_txd      (o_uart_txd)
);// ========== 内部信号 ==========
reg [7:0]   r_recv_buffer  [0:P_DATA_LEN-1];
reg [7:0]   r_tx_buffer   [0:P_DATA_LEN-1];
reg [3:0]   r_rx_cnt;
reg [3:0]   r_tx_cnt;
reg [2:0]   r_state;
reg         r_wait_busy;localparam  S_IDLE = 3'd0,S_RECV = 3'd1,S_CMD  = 3'd2,S_RESP = 3'd3,S_SEND = 3'd4;
//0:16是采集,17:29是控制
reg [31:0]  r_gram [0:29];
reg [31:0]  r_resp_data;
reg [7:0]   r_cmd_type;
reg [7:0]   r_cmd_addr;
reg [31:0]  r_cmd_data;reg [31:0] r_acq_gram_seq;assign o_acq_gram_0  = r_gram[0];
assign o_acq_gram_1  = r_gram[1];
assign o_acq_gram_2  = r_gram[2];
assign o_acq_gram_3  = r_acq_gram_seq;
assign o_acq_gram_4  = r_gram[4];
assign o_acq_gram_5  = r_gram[5];
assign o_acq_gram_6  = r_gram[6];
assign o_acq_gram_7  = r_gram[7];
assign o_acq_gram_8  = r_gram[8];
assign o_acq_gram_9  = r_gram[9];
assign o_acq_gram_10 = r_gram[10];
assign o_acq_gram_11 = r_gram[11];
assign o_acq_gram_12 = r_gram[12];
assign o_acq_gram_13 = r_gram[13];
assign o_acq_gram_14 = r_gram[14];
assign o_acq_gram_15 = r_gram[15];
assign o_acq_gram_16 = r_gram[16];integer     idx;
integer      i;
always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n) beginr_rx_cnt    <= 0;r_tx_cnt    <= 0;r_state     <= S_IDLE;r_tx_en     <= 1'b0;r_tx_data   <= 8'd0;r_wait_busy <= 1'b0;o_recv_acq_done <= 1'b0;o_recv_ctrl_done <= 1'b0;r_gram[0]<=32'h00000002;r_gram[1]<=32'h08800040;r_gram[2]<=32'h02400007;for (i = 4; i <= 17; i = i + 1) beginr_gram[i] <= i>9?i-9:i;endend else beginr_tx_en <= 1'b0;o_recv_acq_done <=  1'b0;o_recv_ctrl_done<=  1'b0;case (r_state)S_IDLE: beginr_rx_cnt    <= 0;r_tx_cnt    <= 0;r_wait_busy <= 0;r_state     <= S_RECV;r_gram[3] <=r_acq_gram_seq;r_gram[17]<=i_ctrl_gram_0;r_gram[18]<=i_ctrl_gram_1;r_gram[19]<=i_ctrl_gram_2;r_gram[20]<=i_ctrl_gram_3;r_gram[21]<=i_ctrl_gram_4;r_gram[22]<=i_ctrl_gram_5;r_gram[23]<=i_ctrl_gram_6;r_gram[24]<=i_ctrl_gram_7;r_gram[25]<=i_ctrl_gram_8;r_gram[26]<=i_ctrl_gram_9;r_gram[27]<=i_ctrl_gram_10;r_gram[28]<=i_ctrl_gram_11;r_gram[29]<=i_ctrl_gram_12;endS_RECV: beginif (w_rx_done) beginr_recv_buffer[r_rx_cnt] <= w_rx_data;if (r_rx_cnt == P_DATA_LEN - 1) beginr_state <= S_CMD;endr_rx_cnt <= r_rx_cnt + 1;endendS_CMD: beginr_cmd_type <= r_recv_buffer[0];r_cmd_addr <= r_recv_buffer[1];r_cmd_data <= {r_recv_buffer[5], r_recv_buffer[4], r_recv_buffer[3], r_recv_buffer[2]};if (r_recv_buffer[1]< 30) beginidx = r_recv_buffer[1];if(idx<30) beginif (r_recv_buffer[0] == 8'h01) beginr_gram[idx] <= {r_recv_buffer[5], r_recv_buffer[4], r_recv_buffer[3], r_recv_buffer[2]};o_recv_acq_done<= 1'b1;r_state <= S_RESP;end else beginr_resp_data <= r_gram[idx];o_recv_ctrl_done<= 1'b1;r_state <= S_SEND;endendelse beginr_state <= S_IDLE;endend else beginr_state <= S_IDLE;endendS_RESP: beginr_resp_data <= r_gram[idx];r_state <= S_SEND;endS_SEND: beginr_tx_buffer[0] <= r_cmd_type;r_tx_buffer[1] <= r_cmd_addr;r_tx_buffer[2] <= r_resp_data[7:0];r_tx_buffer[3] <= r_resp_data[15:8];r_tx_buffer[4] <= r_resp_data[23:16];r_tx_buffer[5] <= r_resp_data[31:24];if (!w_tx_busy && !r_wait_busy) beginr_tx_data   <= r_tx_buffer[r_tx_cnt];r_tx_en     <= 1'b1;r_tx_cnt    <= r_tx_cnt + 1;r_wait_busy <= 1'b1;end else if (w_tx_busy) beginr_wait_busy <= 1'b0;if (r_tx_cnt == 6)r_state <= S_IDLE;endendendcaseend
end// 每毫秒需要的周期数localparam integer CNT_1MS_MAX = CLK_FREQ / 1000;// 1ms 计数器reg [$clog2(CNT_1MS_MAX):0] r_cnt_1ms;reg                         r_1ms_pulse;always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n) beginr_cnt_1ms    <= 0;r_1ms_pulse  <= 0;end else if (r_cnt_1ms == CNT_1MS_MAX - 1) beginr_cnt_1ms    <= 0;r_1ms_pulse  <= 1;end else beginr_cnt_1ms    <= r_cnt_1ms + 1;r_1ms_pulse  <= 0;endend//采集序号always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n)r_acq_gram_seq <= 0;else if (r_1ms_pulse)r_acq_gram_seq <= r_acq_gram_seq + 1;end//产生采集完成的中断脉冲:20us宽的脉冲always @(posedge i_sys_clk or negedge i_sys_reset_n) beginif (!i_sys_reset_n) begino_acq_done_irq_pulse  <= 0;end else if (r_cnt_1ms > CNT_1MS_MAX - 1000 &&  r_cnt_1ms <= CNT_1MS_MAX - 1) begino_acq_done_irq_pulse  <=i_acq_en ? 1:0;end else begino_acq_done_irq_pulse  <= 0;endendendmodule

HC_FPGA_Demo_Top.v

module HC_FPGA_Demo_Top
(input   CLOCK_XTAL_50MHz,input   RESET,input   KEY4,input   KEY3,input   KEY2,input   KEY1,input   SIG_IN,input   RXD,output  TXD,output  LED0,output  LED1,output  LED2,output  LED3,output  SIG_OUT1,output  SIG_OUT2,output  SIG_OUT3,output  SIG_OUT4,output  SIG_OUT5,output[7:0] DIG,output[5:0] SEL,output o_recv_acq_done,output o_recv_ctrl_done
);parameter CLK_FREQ = 50000000;    //定义系统时钟频率wire [29:0] smg_disp_data;vio_uart u_vio_uart (.i_sys_clk   (CLOCK_XTAL_50MHz),.i_sys_reset_n(RESET),.i_uart_rxd  (RXD),.o_uart_txd  (TXD),.i_ctrl_gram_0({KEY4,KEY3,KEY2,KEY1}),.o_acq_gram_0(smg_disp_data),.o_recv_acq_done (SIG_OUT1),.o_recv_ctrl_done (SIG_OUT2)
);smg u_smg (.clk(CLOCK_XTAL_50MHz),.rst_n(RESET),.din_data(smg_disp_data),.dp_in(~0),.sel(SEL),.dig(DIG)
);endmodule

文章转载自:
http://cattle.isnyv.cn
http://bunker.isnyv.cn
http://anecdotical.isnyv.cn
http://callop.isnyv.cn
http://alkekengi.isnyv.cn
http://algebraize.isnyv.cn
http://capeline.isnyv.cn
http://arvo.isnyv.cn
http://bowman.isnyv.cn
http://aquatel.isnyv.cn
http://bridgetown.isnyv.cn
http://abbevillian.isnyv.cn
http://aesthophysiology.isnyv.cn
http://capitalize.isnyv.cn
http://alder.isnyv.cn
http://anatolia.isnyv.cn
http://cabined.isnyv.cn
http://banjoist.isnyv.cn
http://balladist.isnyv.cn
http://chastely.isnyv.cn
http://asthma.isnyv.cn
http://bant.isnyv.cn
http://absinthium.isnyv.cn
http://betweentimes.isnyv.cn
http://amos.isnyv.cn
http://alley.isnyv.cn
http://admixture.isnyv.cn
http://asbestiform.isnyv.cn
http://acryl.isnyv.cn
http://amelioration.isnyv.cn
http://www.dtcms.com/a/281357.html

相关文章:

  • 自己训练大模型?MiniMind 全流程解析 (一) 预训练
  • 如何科学做好企业软件许可优化?
  • Day03_C语言网络编程20250715
  • Datawhale AI 夏令营第一期(机器学习方向)Task2 笔记:用户新增预测挑战赛 —— 从业务理解到技术实现
  • 如何理解flex: 1 1 50%
  • 【Unity基础】Unity中元素的层级排序
  • WPF,Winform,HTML5网页,哪个UI开发速度最快?
  • 线程(一) linux
  • 前端医疗生命体征
  • MIPI DSI(四) video 和 command 模式
  • 比较vue和react框架
  • Windows 下 Visual Studio 开发 C++ 项目的部署流程
  • Spring Boot 启动原理揭秘:从 main 方法到自动装配
  • 判断QMetaObject::invokeMethod()里的函数是否调用成功
  • Process Lasso:提升电脑性能的得力助手
  • C++20 协程参考手册详解 - 源自 cppreference.com
  • Expression 类的静态方法
  • PostgreSQL 大数据量(超过50GB)导出方案
  • 国产化Excel处理组件Spire.XLS教程:在 C# 中生成 Excel文件
  • 关于LM74700-Q1低IQ理想二极管的应用与参数极限
  • saltstack安装部署
  • 对象数组列表转成树形结构--树形结构转成列表(处理菜单)
  • ORA-06413: 连接未打开
  • 设计网站集:经济信息数据 统计数据 + 农业 + 金属 + 药品 + 电子 + 加密货币 + 债券 + 期货 + 其他
  • 构建企业级项目管理全面数字化运营体系︱易趋(蓝云软件)总裁唐智勇
  • 东鹏饮料牵手盈飞无限质量管理系统(QMS)
  • 多方学习与安全多方计算
  • 电动汽车制动系统及其工作原理
  • 梁的振动特征函数分析
  • 算法学习笔记(1):组合数