参考
Verilog串口的寄存器访问模块–vio_uart.csdn
简易寄存器接口SMMR.csdn
高级外设总线APB.csdn
Tang-Nano-1K移植vio_uart
vio_uart的浏览器版上位机
帧格式和两类操作
这里的地址是slot 外设中u32寄存器在整个smmr_slot_router 中的索引号
这个桥接模块只能以u32的方式访问slot 外设
📦 帧格式
主机发送 r_rx_buffer [6]
从机回复 r_tx_buffer [6]
通信帧为定长 6 字节结构,以实现对32位寄存器的读写
读写标志 r_rx_buffer[0].0只占用1个bit,如果8位地址不够,
可以用 r_rx_buffer[0][7:1]+r_rx_buffer[1][7:0]扩充到15位地址
| 字段名称 | 说明 | 字节数 |
|---|---|---|
| 读写标志 | 0x00= 读,0x01= 写 | 1 字节 |
| 地址 | 寄存器地址(范围0 ~ 255) | 1 字节 |
| 数据 | 4 字节有效数据 | 4 字节 |
✅ 读操作
读取地址0x01的数据:
| 读写标志 | 地址 | 数据 |
|---|---|---|
0x00 | 0x01 | 00 00 00 00 |
📖 主机请求读取地址
0x01的寄存器,数据字段为占位。
✅ 写操作
向地址0x01写入01 02 03 04:
| 读写标志 | 地址 | 数据 |
|---|---|---|
0x01 | 0x01 | 01 02 03 04 |
✍️ 主机向地址
0x01写入 4 字节控制数据。
代码
TANG_FPGA_Demo_Top.v
module TANG_FPGA_Demo_Top#( // 内部 SMMR 字节地址宽度。 parameter P_ADDR_WIDTH = 8, // 寄存器宽度 parameter P_DATA_WIDTH = 32, // 系统时钟频率。 parameter P_CLK_FREQ = 27_000_000 ) ( input CLOCK_XTAL_27MHz, input RESET, input KEY1, input RXD, output TXD, output [2:0] LED // 110 R, 101 B, 011 G ); //////////////////////////////////////////////////////////////////////////// // vio_uart桥接模块到 SMMR 路由模块之间的信号 //////////////////////////////////////////////////////////////////////////// wire w_reg_wr_en; wire [8-1:0] w_reg_wr_addr; wire [8-1:0] w_reg_rd_addr; wire [P_DATA_WIDTH-1:0] w_reg_wr_data; wire [P_DATA_WIDTH-1:0] w_reg_rd_data; wire [P_ADDR_WIDTH-1:0] w_slot_wr_addr; wire [P_ADDR_WIDTH-1:0] w_slot_rd_addr; // 写数据会同时送到所有 slot,真正写入哪个 slot 由对应写使能决定。 wire [P_DATA_WIDTH-1:0] w_slot_wr_data; // slot0 的写使能和读数据。 wire w_slot0_wr_en; wire [P_DATA_WIDTH-1:0] w_slot0_rd_data; // slot1 的写使能和读数据。 wire w_slot1_wr_en; wire [P_DATA_WIDTH-1:0] w_slot1_rd_data; vio_uart_smmr_bridge #( .P_CLK_FREQ(P_CLK_FREQ), .P_UART_BPS(115200) ) u_vio_uart_smmr_bridge ( .i_clk (CLOCK_XTAL_27MHz), .i_rst_n (RESET), .i_uart_rxd (RXD), .o_uart_txd (TXD), .o_reg_wr_en (w_reg_wr_en), .o_reg_wr_addr (w_reg_wr_addr), .o_reg_wr_data (w_reg_wr_data), .o_reg_rd_addr (w_reg_rd_addr), .i_reg_rd_data (w_reg_rd_data) ); //////////////////////////////////////////////////////////////////////////// // SMMR slot 路由模块 // // 该模块根据 SMMR 地址范围选择目标 slot。 // 写操作时,它给对应 slot 产生写使能。 // 读操作时,它把被选中 slot 的读数据返回给 AXI-Lite 桥接模块。 // // 当前地址映射: // slot0:寄存器地址 0 到 3 // slot1:寄存器地址 5 到 8 //////////////////////////////////////////////////////////////////////////// smmr_slot_router u_smmr_slot_router ( .i_clk (CLOCK_XTAL_27MHz), .i_rst_n (RESET), .i_reg_wr_en (w_reg_wr_en), .i_reg_wr_addr (w_reg_wr_addr), .i_reg_wr_data (w_reg_wr_data), .i_reg_rd_addr (w_reg_rd_addr), .o_reg_rd_data (w_reg_rd_data), .o_slot_wr_addr (w_slot_wr_addr), .o_slot_wr_data (w_slot_wr_data), .o_slot_rd_addr (w_slot_rd_addr), .o_slot0_wr_en (w_slot0_wr_en), .i_slot0_rd_data(w_slot0_rd_data), .o_slot1_wr_en (w_slot1_wr_en), .i_slot1_rd_data(w_slot1_rd_data) ); //////////////////////////////////////////////////////////////////////////// // slot0 外设 // // slot0 是一个简单寄存器块。 // 它可以作为新增 SMMR 外设的模板:只需要接入写使能、地址、写数据、 // 读地址和读数据,就可以挂到系统中。 //////////////////////////////////////////////////////////////////////////// slot0 u_slot0 ( .i_clk (CLOCK_XTAL_27MHz), .i_rst_n (RESET), .i_reg_wr_en (w_slot0_wr_en), .i_reg_wr_addr (w_slot_wr_addr), .i_reg_wr_data (w_slot_wr_data), .i_reg_rd_addr (w_slot_rd_addr), .o_reg_rd_data (w_slot0_rd_data) ); //////////////////////////////////////////////////////////////////////////// // slot1 外设 // // slot1 也是一个 SMMR 寄存器块,同时多了一个实际硬件输出 o_led。 // 这展示了如何通过寄存器写入来控制 FPGA 内部或外部硬件信号。 //////////////////////////////////////////////////////////////////////////// slot1 u_slot1 ( .i_clk (CLOCK_XTAL_27MHz), .i_rst_n (RESET), .i_reg_wr_en (w_slot1_wr_en), .i_reg_wr_addr (w_slot_wr_addr), .i_reg_wr_data (w_slot_wr_data), .i_reg_rd_addr (w_slot_rd_addr), .o_reg_rd_data (w_slot1_rd_data), .o_led (LED) ); endmodulevio_uart_smmr_bridge.v
`timescale 1ns/1ps module vio_uart_smmr_bridge #( parameter P_CLK_FREQ=50000000, parameter P_UART_BPS=115200 )( input wire i_clk, input wire i_rst_n, input wire i_uart_rxd, output wire o_uart_txd, output reg o_reg_wr_en, output reg [7:0] o_reg_wr_addr, output reg [32-1:0] o_reg_wr_data, output reg [7:0] o_reg_rd_addr, input wire [32-1:0] i_reg_rd_data ); // Instantiate existing UART blocks. 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 #( .P_CLK_FREQ(P_CLK_FREQ), .P_UART_BPS(P_UART_BPS) ) u_uart_rx( .i_clk(i_clk), .i_rst_n(i_rst_n), .i_uart_rxd(i_uart_rxd), .o_uart_rx_done(w_rx_done), .o_uart_rx_data(w_rx_data) ); uart_tx #( .P_CLK_FREQ(P_CLK_FREQ), .P_UART_BPS(P_UART_BPS) ) u_uart_tx( .i_clk(i_clk), .i_rst_n(i_rst_n), .i_uart_tx_en(r_tx_en), .i_uart_tx_data(r_tx_data), .o_uart_tx_busy(w_tx_busy), .o_uart_txd(o_uart_txd) ); // ========== 内部信号 ========== //接收缓冲区 reg [7:0] r_rx_buffer [0:5]; //发送缓冲区 reg [7:0] r_tx_buffer [0:5]; //接收计数器 reg [3:0] r_rx_cnt; //发送计数器 reg [3:0] r_tx_cnt; //状态 reg [2:0] r_state; //0,则等发送下个字节 reg r_wait_busy; localparam S_IDLE = 3'd0, S_RECV = 3'd1, S_SETUP = 3'd2, S_ACCESS = 3'd3, S_RESP = 3'd4, S_SEND = 3'd5; always @(posedge i_clk or negedge i_rst_n) begin if (!i_rst_n) begin r_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_reg_wr_en <= 1'b0; o_reg_wr_addr <= 8'd0; o_reg_wr_data <= 32'd0; o_reg_rd_addr <= 8'd0; end else begin r_tx_en <= 1'b0; o_reg_wr_en<=0; case (r_state) S_IDLE: begin r_rx_cnt <= 0; r_tx_cnt <= 0; r_wait_busy <= 0; r_state <= S_RECV; end S_RECV: begin if (w_rx_done) begin r_rx_buffer[r_rx_cnt] <= w_rx_data; if (r_rx_cnt == 6 - 1) begin r_state <= S_SETUP; end r_rx_cnt <= r_rx_cnt + 1; end end S_SETUP: begin //写 if (r_rx_buffer[0] == 8'h01) begin o_reg_wr_addr <= r_rx_buffer[1]; o_reg_wr_data <= {r_rx_buffer[5], r_rx_buffer[4], r_rx_buffer[3], r_rx_buffer[2]}; r_state <= S_ACCESS; end //读 else if(r_rx_buffer[0] == 8'h00) begin o_reg_rd_addr <= r_rx_buffer[1]; r_state <= S_ACCESS; end //忽略 else begin r_state<=S_IDLE; end end S_ACCESS: begin //写 if (r_rx_buffer[0] ==8'h01) begin o_reg_wr_en<=1; end r_state <= S_RESP; end S_RESP: begin r_tx_cnt<=0; r_tx_buffer[0] <= r_rx_buffer[0]; r_tx_buffer[1] <= r_rx_buffer[1]; //写返回的 if(r_rx_buffer[0] == 8'h01) begin r_tx_buffer[2] <= r_rx_buffer[2]; r_tx_buffer[3] <= r_rx_buffer[3]; r_tx_buffer[4] <= r_rx_buffer[4]; r_tx_buffer[5] <= r_rx_buffer[5]; //读返回的 end else if(r_rx_buffer[0] == 8'h00) begin r_tx_buffer[2] <= i_reg_rd_data[7:0]; r_tx_buffer[3] <= i_reg_rd_data[15:8]; r_tx_buffer[4] <= i_reg_rd_data[23:16]; r_tx_buffer[5] <= i_reg_rd_data[31:24]; end r_state <= S_SEND; end S_SEND: begin if (!w_tx_busy && !r_wait_busy) begin r_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) begin r_wait_busy <= 1'b0; if (r_tx_cnt >= 6) begin r_state <= S_IDLE; end end end default: begin r_state <= S_IDLE; end endcase end end endmodulesmmr_slot_router.v
//////////////////////////////////////////////////////////////////////////////// // 简单内存映射寄存器路由模块 // - 将一路 SMMR 接口路由到多个寄存器槽 //////////////////////////////////////////////////////////////////////////////// module smmr_slot_router #( // AXI-Lite 侧使用字节地址,寄存器槽侧使用寄存器索引。 parameter P_ADDR_WIDTH = 8, parameter P_DATA_WIDTH = 32, // 寄存器槽地址范围以 32 位寄存器为单位。 parameter P_SLOT0_BASE = 8'd0, parameter P_SLOT0_SIZE = 8'd4, parameter P_SLOT1_BASE = 8'd4, parameter P_SLOT1_SIZE = 8'd4 )( input wire i_clk, input wire i_rst_n, // 上游简单寄存器总线,地址为字节地址。 input wire i_reg_wr_en, input wire [P_ADDR_WIDTH-1:0] i_reg_wr_addr, input wire [P_DATA_WIDTH-1:0] i_reg_wr_data, input wire [P_ADDR_WIDTH-1:0] i_reg_rd_addr, output reg [P_DATA_WIDTH-1:0] o_reg_rd_data, // 下游寄存器槽总线,地址为 32 位寄存器索引。 output wire [P_ADDR_WIDTH-3:0] o_slot_wr_addr, output wire [P_DATA_WIDTH-1:0] o_slot_wr_data, output wire [P_ADDR_WIDTH-3:0] o_slot_rd_addr, output wire o_slot0_wr_en, input wire [P_DATA_WIDTH-1:0] i_slot0_rd_data, output wire o_slot1_wr_en, input wire [P_DATA_WIDTH-1:0] i_slot1_rd_data ); wire [P_ADDR_WIDTH-3:0] w_reg_wr_addr_u32 = i_reg_wr_addr; wire [P_ADDR_WIDTH-3:0] w_reg_rd_addr_u32 = i_reg_rd_addr; reg r_slot0_wr_sel; reg r_slot1_wr_sel; reg r_slot0_rd_sel; reg r_slot1_rd_sel; always @(*) begin r_slot0_wr_sel = 1'b0; r_slot1_wr_sel = 1'b0; if ((w_reg_wr_addr_u32 >= P_SLOT0_BASE) && (w_reg_wr_addr_u32 < (P_SLOT0_BASE + P_SLOT0_SIZE))) begin r_slot0_wr_sel = 1'b1; end else if ((w_reg_wr_addr_u32 >= P_SLOT1_BASE) && (w_reg_wr_addr_u32 < (P_SLOT1_BASE + P_SLOT1_SIZE))) begin r_slot1_wr_sel = 1'b1; end end always @(*) begin r_slot0_rd_sel = 1'b0; r_slot1_rd_sel = 1'b0; if ((w_reg_rd_addr_u32 >= P_SLOT0_BASE) && (w_reg_rd_addr_u32 < (P_SLOT0_BASE + P_SLOT0_SIZE))) begin r_slot0_rd_sel = 1'b1; end else if ((w_reg_rd_addr_u32 >= P_SLOT1_BASE) && (w_reg_rd_addr_u32 < (P_SLOT1_BASE + P_SLOT1_SIZE))) begin r_slot1_rd_sel = 1'b1; end end assign o_slot0_wr_en = i_reg_wr_en && r_slot0_wr_sel; assign o_slot1_wr_en = i_reg_wr_en && r_slot1_wr_sel; assign o_slot_wr_addr = w_reg_wr_addr_u32; assign o_slot_wr_data = i_reg_wr_data; assign o_slot_rd_addr = w_reg_rd_addr_u32; always @(*) begin if (r_slot0_rd_sel) begin o_reg_rd_data = i_slot0_rd_data; end else if (r_slot1_rd_sel) begin o_reg_rd_data = i_slot1_rd_data; end else begin o_reg_rd_data = {P_DATA_WIDTH{1'b0}}; end end endmoduleslot0.v
module slot0 #( parameter P_ADDR_WIDTH = 8, parameter P_DATA_WIDTH = 32, parameter [P_ADDR_WIDTH-1:0] P_SLOT_BASE = 0, parameter P_REG_COUNT = 4 )( input wire i_clk, input wire i_rst_n, input wire i_reg_wr_en, input wire [P_ADDR_WIDTH-1:0] i_reg_wr_addr, input wire [P_DATA_WIDTH-1:0] i_reg_wr_data, input wire [P_ADDR_WIDTH-1:0] i_reg_rd_addr, output reg [P_DATA_WIDTH-1:0] o_reg_rd_data ); reg [P_DATA_WIDTH-1:0] r_mem [0:P_REG_COUNT-1]; //写 integer i; always @(posedge i_clk or negedge i_rst_n) begin if (!i_rst_n) begin for (i = 0; i < P_REG_COUNT; i = i + 1) begin r_mem[i] <= {P_DATA_WIDTH{1'b0}}; end end else if (i_reg_wr_en && (i_reg_wr_addr >= P_SLOT_BASE) && (i_reg_wr_addr < (P_SLOT_BASE + P_REG_COUNT))) begin r_mem[i_reg_wr_addr-P_SLOT_BASE] <= i_reg_wr_data; end end //读 always @(*) begin if ((i_reg_rd_addr >= P_SLOT_BASE) && (i_reg_rd_addr < (P_SLOT_BASE + P_REG_COUNT))) begin o_reg_rd_data = r_mem[i_reg_rd_addr-P_SLOT_BASE]; end else begin o_reg_rd_data = {P_DATA_WIDTH{1'b0}}; end end endmoduleslot1.v
module slot1 #( parameter P_ADDR_WIDTH = 8, parameter P_DATA_WIDTH = 32, parameter [P_ADDR_WIDTH-1:0] P_SLOT_BASE = 4, parameter P_REG_COUNT = 4 )( input wire i_clk, input wire i_rst_n, input wire i_reg_wr_en, input wire [P_ADDR_WIDTH-1:0] i_reg_wr_addr, input wire [P_DATA_WIDTH-1:0] i_reg_wr_data, input wire [P_ADDR_WIDTH-1:0] i_reg_rd_addr, output reg [P_DATA_WIDTH-1:0] o_reg_rd_data, output reg [2:0] o_led ); // 控制寄存器:bit0:o_led localparam [P_ADDR_WIDTH-1:0] ADDR_CONTROL = P_SLOT_BASE + 8'd0; reg [P_DATA_WIDTH-1:0] r_mem [0:P_REG_COUNT-1]; integer i; always @(posedge i_clk or negedge i_rst_n) begin if (!i_rst_n) begin for (i = 0; i < P_REG_COUNT; i = i + 1) begin r_mem[i] <= {P_DATA_WIDTH{1'b0}}; end o_led<=0; end else if (i_reg_wr_en && (i_reg_wr_addr >= P_SLOT_BASE) && (i_reg_wr_addr < (P_SLOT_BASE + P_REG_COUNT))) begin r_mem[i_reg_wr_addr-P_SLOT_BASE] <= i_reg_wr_data; case (i_reg_wr_addr) ADDR_CONTROL: begin o_led <= i_reg_wr_data; end endcase end end always @(*) begin if ((i_reg_rd_addr >= P_SLOT_BASE) && (i_reg_rd_addr < (P_SLOT_BASE + P_REG_COUNT))) begin o_reg_rd_data = r_mem[i_reg_rd_addr-P_SLOT_BASE]; end else begin o_reg_rd_data = {P_DATA_WIDTH{1'b0}}; end end endmoduleuart_tx.v
module uart_tx #( parameter P_CLK_FREQ = 50_000_000, parameter P_UART_BPS = 115200 ) ( // from system input i_clk , input i_rst_n , input i_uart_tx_en , input [7 : 0] i_uart_tx_data , output reg o_uart_tx_busy , // 发送中标志 // output output reg o_uart_txd ); // parameter define localparam L_BAUD_CNT_MAX = P_CLK_FREQ / P_UART_BPS; // reg define reg [3:0] r_bit_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_clk or negedge i_rst_n) begin if (!i_rst_n) r_uart_tx_en_d <= 1'b0; else r_uart_tx_en_d <= i_uart_tx_en; end assign w_uart_tx_en_posedge = i_uart_tx_en && !r_uart_tx_en_d; // baud rate counter always @(posedge i_clk or negedge i_rst_n) begin if (!i_rst_n) r_baud_cnt <= 16'd0; else if (o_uart_tx_busy) begin if (r_baud_cnt == L_BAUD_CNT_MAX - 1) r_baud_cnt <= 16'd0; else r_baud_cnt <= r_baud_cnt + 1'b1; end else begin r_baud_cnt <= 16'd0; end end // tx bit counter always @(posedge i_clk or negedge i_rst_n) begin if (!i_rst_n) r_bit_cnt <= 4'd0; else if (o_uart_tx_busy && (r_baud_cnt == L_BAUD_CNT_MAX - 1)) r_bit_cnt <= r_bit_cnt + 1'b1; else if (!o_uart_tx_busy) r_bit_cnt <= 4'd0; end // control busy and latch data always @(posedge i_clk or negedge i_rst_n) begin if (!i_rst_n) begin r_tx_data_t <= 8'd0; o_uart_tx_busy <= 1'b0; end else if (w_uart_tx_en_posedge && !o_uart_tx_busy) begin r_tx_data_t <= i_uart_tx_data; o_uart_tx_busy <= 1'b1; end else if (o_uart_tx_busy && r_bit_cnt == 4'd9 && r_baud_cnt == L_BAUD_CNT_MAX - 1) begin o_uart_tx_busy <= 1'b0; end end // generate txd signal always @(posedge i_clk or negedge i_rst_n) begin if (!i_rst_n) o_uart_txd <= 1'b1; else if (o_uart_tx_busy) begin case(r_bit_cnt) 4'd0 : o_uart_txd <= 1'b0; // start bit 4'd1 : o_uart_txd <= r_tx_data_t[0]; 4'd2 : o_uart_txd <= r_tx_data_t[1]; 4'd3 : o_uart_txd <= r_tx_data_t[2]; 4'd4 : o_uart_txd <= r_tx_data_t[3]; 4'd5 : o_uart_txd <= r_tx_data_t[4]; 4'd6 : o_uart_txd <= r_tx_data_t[5]; 4'd7 : o_uart_txd <= r_tx_data_t[6]; 4'd8 : o_uart_txd <= r_tx_data_t[7]; 4'd9 : o_uart_txd <= 1'b1; // stop bit default : o_uart_txd <= 1'b1; endcase end else o_uart_txd <= 1'b1; end endmoduleuart_rx.v
module uart_rx #( parameter P_CLK_FREQ = 50_000_000, parameter P_UART_BPS = 115200 ) ( input i_clk , input i_rst_n , input i_uart_rxd , output reg o_uart_rx_done , output reg [7:0] o_uart_rx_data ); //parameter define localparam L_BAUD_CNT_MAX= P_CLK_FREQ/P_UART_BPS ; //reg define reg r_uart_rxd0 ; reg r_uart_rxd1 ; reg r_uart_rxd2 ; reg r_rx_flag ; //正在接收中的标志 reg [3:0] r_bit_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_clk or negedge i_rst_n) begin if(!i_rst_n) begin r_uart_rxd0 <= 1'b0 ; r_uart_rxd1 <= 1'b0 ; r_uart_rxd2 <= 1'b0 ; end else begin r_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_clk or negedge i_rst_n) begin if(!i_rst_n) r_baud_cnt <= 16'd0; else if(r_rx_flag) begin if(r_baud_cnt == L_BAUD_CNT_MAX - 1'b1) r_baud_cnt <= 16'd0; else r_baud_cnt <= r_baud_cnt + 16'b1; end else r_baud_cnt <= 16'd0; end //generate r_bit_cnt always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) begin r_bit_cnt <= 4'd0; end else if(r_rx_flag) begin if(r_baud_cnt == L_BAUD_CNT_MAX - 1'b1) r_bit_cnt <= r_bit_cnt + 1'b1; else r_bit_cnt <= r_bit_cnt; end else r_bit_cnt <= 4'd0; end //generate r_rx_flag always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_rx_flag <= 1'b0; else if(w_start_en) r_rx_flag <= 1'b1; else if((r_bit_cnt == 4'd9) && (r_baud_cnt == L_BAUD_CNT_MAX/2 - 1'b1)) r_rx_flag <= 1'b0; else r_rx_flag <= r_rx_flag; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_rx_data_t <= 8'b0; else if(r_rx_flag) begin if(r_baud_cnt == L_BAUD_CNT_MAX/2 - 1'b1) begin case(r_bit_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 : ; endcase end else r_rx_data_t <= r_rx_data_t; end else r_rx_data_t <= 8'b0; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) begin o_uart_rx_done <= 1'b0; o_uart_rx_data <= 8'b0; end else if(r_bit_cnt == 4'd9 && r_baud_cnt == L_BAUD_CNT_MAX/2 - 1'b1) begin o_uart_rx_done <= 1'b1; o_uart_rx_data <= r_rx_data_t; end else begin o_uart_rx_done <= 1'b0; o_uart_rx_data <= o_uart_rx_data; end end endmoduleReadMe.md
# 导入文件setsrc_dir"D:/workspace/gitee/0/ming_tang_nano_1k/vio_uart/src"setrtl_dir"D:/workspace/gitee/0/ming_tang_nano_1k/vio_uart/src/rtl"add_file$rtl_dir/TANG_FPGA_Demo_Top.v add_file$rtl_dir/uart_rx.v add_file$rtl_dir/uart_tx.v add_file$rtl_dir/vio_uart_smmr_bridge.v add_file$rtl_dir/smmr_slot_router.v add_file$rtl_dir/slot0.v add_file$rtl_dir/slot1.v add_file$src_dir/vio_uart_prj.cst add_file$src_dir/vio_uart_prj.sdcvio_uart_prj.cst
IO_LOC"CLOCK_XTAL_27MHz"47;IO_PORT"CLOCK_XTAL_27MHz"IO_TYPE=LVCMOS33PULL_MODE=UP;IO_LOC"RESET"13;IO_PORT"RESET"IO_TYPE=LVCMOS33PULL_MODE=UP;IO_LOC"KEY1"44;IO_PORT"KEY1"IO_TYPE=LVCMOS33PULL_MODE=UP;IO_LOC"TXD"40;IO_PORT"TXD"IO_TYPE=LVCMOS33PULL_MODE=UPDRIVE=8;IO_LOC"RXD"41;IO_PORT"RXD"IO_TYPE=LVCMOS33PULL_MODE=UP;IO_LOC"LED[2]"11;IO_PORT"LED[2]"IO_TYPE=LVCMOS33PULL_MODE=UPDRIVE=8;IO_LOC"LED[1]"10;IO_PORT"LED[1]"IO_TYPE=LVCMOS33PULL_MODE=UPDRIVE=8;IO_LOC"LED[0]"9;IO_PORT"LED[0]"IO_TYPE=LVCMOS33PULL_MODE=UPDRIVE=8;vio_uart_prj.sdc
create_clock-nameCLOCK_XTAL_27MHz-period37.037-waveform{018.518}[get_ports{CLOCK_XTAL_27MHz}]测试
# 关灯[13:42:35.232]发→◇01 04 07 00 00 00 □[13:42:35.235]收←◆01 04 07 00 00 00# 开灯[13:58:15.089]发→◇01 04 01 00 00 00 □[13:58:15.092]收←◆01 04 01 00 00 00