嵌入式终端AtShell的verilog版
·
参考
简易寄存器接口SMMR的vio_uart桥接.csdn
Verilog串口的寄存器访问模块–vio_uart.csdn
简易寄存器接口SMMR.csdn
高级外设总线APB.csdn
Tang-Nano-1K移植vio_uart
vio_uart的浏览器版上位机
嵌入式终端AtShell.csdn
树莓派Pico移植Atshell.csdn
嵌入式终端AtShell的精简版.csdn
基于rtdef.h的轻量级设备管理、终端、协程与应用管理框架设计.csdn
zynq的linux驱动版终端AtShellDrv.csdn
目的
用于实现verilog 版的print
接收命令用 按键 或 Verilog串口的寄存器访问模块–vio_uart.csdn
一个系统时钟向串口发送一个不定长的数据包
发送的内容 如下 (16进制)
每行为1个数据包,时间间隔为1个系统时钟
30
31
32 33
34 35 36
37 38 39 40
61 62 63 64 65
66 67 68 69 70 71
72 73 74 75 76 77 78
通用部分
axis_uart_sender.v
`timescale 1ns/1ps
module axis_uart_sender #(
parameter P_CLK_FREQ = 50_000_000,
parameter P_UART_BPS = 115200,
parameter P_FIFO_DEPTH = 128
)(
input i_clk,
input i_rst_n,
// AXI-Stream 输入
input s_axis_uart_tvalid,
output s_axis_uart_tready,
input [127:0] s_axis_uart_tdata,
// UART TX
output reg o_uart_tx
);
// 50MHz / 115200 ≈ 434
localparam integer P_CLKS_PER_BIT = P_CLK_FREQ / P_UART_BPS;
// UART bit 计数器宽度
localparam integer P_CNT_WIDTH = $clog2(P_CLKS_PER_BIT + 1);
// FIFO 地址宽度
localparam integer P_FIFO_AW =$clog2(P_FIFO_DEPTH);
// =========================================================================
// FIFO
// =========================================================================
reg [7:0] r_fifo_mem [0:P_FIFO_DEPTH-1];
// 写指针
reg [P_FIFO_AW:0] r_fifo_wr_ptr;
// 读指针
reg [P_FIFO_AW:0] r_fifo_rd_ptr;
// FIFO 数据数量
wire [P_FIFO_AW:0] w_fifo_count;
assign w_fifo_count = r_fifo_wr_ptr - r_fifo_rd_ptr;
// FIFO 空
wire w_fifo_empty;
assign w_fifo_empty = (r_fifo_wr_ptr == r_fifo_rd_ptr);
// FIFO 满
wire w_fifo_full;
assign w_fifo_full =(w_fifo_count >= P_FIFO_DEPTH);
// =========================================================================
// 写 FIFO 状态机
// =========================================================================
localparam [1:0]
S_WR_IDLE = 2'd0,
S_WR_DATA = 2'd1;
reg [1:0] r_wr_state;
// 整包数据寄存器
reg [127:0] r_packet_data;
// 当前包长度
reg [4:0] r_packet_len;
// 当前写第几个 byte
reg [4:0] r_packet_index;
// =========================================================================
// AXIS READY
// =========================================================================
assign s_axis_uart_tready =(r_wr_state == S_WR_IDLE) && !w_fifo_full;
// 当前需要写入 FIFO 的 byte
reg [7:0] w_current_byte;
always @(*) begin
case (r_packet_index)
5'd0: w_current_byte = r_packet_data[119:112];
5'd1: w_current_byte = r_packet_data[111:104];
5'd2: w_current_byte = r_packet_data[103:96];
5'd3: w_current_byte = r_packet_data[95:88];
5'd4: w_current_byte = r_packet_data[87:80];
5'd5: w_current_byte = r_packet_data[79:72];
5'd6: w_current_byte = r_packet_data[71:64];
5'd7: w_current_byte = r_packet_data[63:56];
5'd8: w_current_byte = r_packet_data[55:48];
5'd9: w_current_byte = r_packet_data[47:40];
5'd10: w_current_byte = r_packet_data[39:32];
5'd11: w_current_byte = r_packet_data[31:24];
5'd12: w_current_byte = r_packet_data[23:16];
5'd13: w_current_byte = r_packet_data[15:8];
5'd14: w_current_byte = r_packet_data[7:0];
default: w_current_byte = 8'h00;
endcase
end
// FIFO 写入状态机
always @(posedge i_clk or negedge i_rst_n) begin
if (!i_rst_n) begin
// 状态机
r_wr_state <= S_WR_IDLE;
// 整包数据
r_packet_data <= 128'd0;
// 数据长度
r_packet_len <= 5'd0;
// 当前 byte index
r_packet_index <= 5'd0;
// FIFO 写指针
r_fifo_wr_ptr <= {(P_FIFO_AW + 1){1'b0}};
end
else begin
case (r_wr_state)
S_WR_IDLE: begin
// 等待 AXIS 数据
if (s_axis_uart_tvalid && s_axis_uart_tready) begin
// 锁存整个 128bit 数据
r_packet_data <= s_axis_uart_tdata;
// 锁存长度
r_packet_len <= s_axis_uart_tdata[127:120];
r_packet_index <= 5'd0;
// 判断长度
if ((s_axis_uart_tdata[127:120] != 8'd0) &&(s_axis_uart_tdata[127:120] <= 8'd15)) begin
r_wr_state <= S_WR_DATA;
end
else begin
// 无效长度,不写 FIFO
r_wr_state <= S_WR_IDLE;
end
end
end
// 拆包写 FIFO
S_WR_DATA: begin
if (!w_fifo_full) begin
// 写入当前 byte
r_fifo_mem[ r_fifo_wr_ptr[P_FIFO_AW-1:0]] <= w_current_byte;
// FIFO 写指针 +1
r_fifo_wr_ptr <= r_fifo_wr_ptr + 1'b1;
// 判断是否已经写完这一包
if (r_packet_index ==(r_packet_len - 1'b1)) begin
// 当前包发送完毕
r_packet_index <= 5'd0;
r_wr_state <= S_WR_IDLE;
end
else begin
// 下一个 byte
r_packet_index <= r_packet_index + 1'b1;
end
end
end
default: begin
r_wr_state <= S_WR_IDLE;
end
endcase
end
end
// =========================================================================
// UART TX 状态机
// =========================================================================
localparam [2:0]
S_TX_IDLE = 3'd0,
S_TX_START = 3'd1,
S_TX_DATA = 3'd2,
S_TX_STOP = 3'd3;
// UART 状态
reg [2:0] r_tx_state;
// UART bit 计数器
reg [P_CNT_WIDTH-1:0] r_tx_cnt;
// 当前发送 bit
reg [2:0] r_tx_bit_idx;
// 当前 UART byte
reg [7:0] r_tx_shift;
// FIFO 读使能
reg r_fifo_rd_en;
// =========================================================================
// FIFO 读指针
// =========================================================================
always @(posedge i_clk or negedge i_rst_n) begin
if (!i_rst_n) begin
r_fifo_rd_ptr <={(P_FIFO_AW + 1){1'b0}};
end
else begin
if (r_fifo_rd_en) begin
r_fifo_rd_ptr <= r_fifo_rd_ptr + 1'b1;
end
end
end
// =========================================================================
// UART TX
// =========================================================================
always @(posedge i_clk or negedge i_rst_n) begin
if (!i_rst_n) begin
r_tx_state <= S_TX_IDLE;
r_tx_cnt <={(P_CNT_WIDTH){1'b0}};
r_tx_bit_idx <= 3'd0;
r_tx_shift <= 8'h00;
r_fifo_rd_en <= 1'b0;
o_uart_tx <= 1'b1;
end
else begin
// 默认不读 FIFO
r_fifo_rd_en <= 1'b0;
case (r_tx_state)
S_TX_IDLE: begin
// UART 空闲为高
o_uart_tx <= 1'b1;
if (!w_fifo_empty) begin
// 取出 FIFO 当前 byte
r_tx_shift <=r_fifo_mem[r_fifo_rd_ptr[P_FIFO_AW-1:0]];
//FIFO 读指针前进
r_fifo_rd_en <= 1'b1;
r_tx_cnt <= {(P_CNT_WIDTH){1'b0}};
r_tx_state <= S_TX_START;
end
end
S_TX_START: begin
// START bit = 0
o_uart_tx <= 1'b0;
if (r_tx_cnt == P_CLKS_PER_BIT - 1) begin
r_tx_cnt <={(P_CNT_WIDTH){1'b0}};
r_tx_bit_idx <= 3'd0;
r_tx_state <= S_TX_DATA;
end
else begin
r_tx_cnt <= r_tx_cnt + 1'b1;
end
end
S_TX_DATA: begin
// UART LSB First
o_uart_tx <= r_tx_shift[r_tx_bit_idx];
if (r_tx_cnt == P_CLKS_PER_BIT - 1) begin
r_tx_cnt <= {(P_CNT_WIDTH){1'b0}};
if (r_tx_bit_idx == 3'd7) begin
// 8bit 数据发送完毕
r_tx_state <= S_TX_STOP;
end
else begin
// 下一个 bit
r_tx_bit_idx <= r_tx_bit_idx + 1'b1;
end
end
else begin
r_tx_cnt <= r_tx_cnt + 1'b1;
end
end
S_TX_STOP: begin
// STOP bit = 1
o_uart_tx <= 1'b1;
if (r_tx_cnt == P_CLKS_PER_BIT - 1) begin
r_tx_cnt <={(P_CNT_WIDTH){1'b0}};
// 当前 byte 发送完成
r_tx_state <= S_TX_IDLE;
end
else begin
r_tx_cnt <=r_tx_cnt + 1'b1;
end
end
// 异常恢复
default: begin
r_tx_state <= S_TX_IDLE;
o_uart_tx <= 1'b1;
end
endcase
end
end
endmodule
key_debounce.v
module key_debounce
#(
parameter P_CLK_FREQ_MHZ = 50, // 时钟频率,单位MHz,默认50MHz
parameter P_DEBOUNCE_MS = 20, // 消抖时间,单位ms,默认20ms
parameter L_CNT_WIDTH = 32 // 需要外部计算后传入
)
(
input wire i_clk , //系统时钟50Mhz
input wire i_rst_n , //全局复位
input wire i_key , //按键输入信号
output reg o_key_pulse //消抖后的脉冲信号
);
// 根据时钟频率和消抖时间计算需要计数的最大值
localparam L_MAX_CNT = P_CLK_FREQ_MHZ * 1000 * P_DEBOUNCE_MS;
reg [L_CNT_WIDTH-1:0] r_cnt ;
// ==================================================
// r_cnt :记录按键按键的时间
// ==================================================
always@(posedge i_clk or negedge i_rst_n)
if(i_rst_n == 1'b0)
r_cnt <= {(L_CNT_WIDTH+1){1'b0}};
//按键松开,计数器清零
else if(i_key == 1)
r_cnt <= {(L_CNT_WIDTH+1){1'b0}};
//按键按下时,计数器计数
else if(i_key == 1'b0 && r_cnt < L_MAX_CNT-1)
r_cnt <= r_cnt + 1'b1;
else
//如果按键一直不释放,则r_cnt维持最大值,防止多次触发
r_cnt <= r_cnt;
// ==================================================
// o_key_pulse :输出脉冲信号,当按键稳定按下超过设定时间,输出一个时钟周期的脉冲
// ==================================================
always@(posedge i_clk or negedge i_rst_n)
if(i_rst_n == 1'b0)
o_key_pulse <= 1'b0;
//计数快满时,产生一个时钟周期的脉冲,因为按住不松手时,计数器会维持在L_MAX_CNT-1
else if(r_cnt == L_MAX_CNT-3)
o_key_pulse <= 1'b1;
else
o_key_pulse <= 1'b0;
endmodule
不同板子
黑金AX301的 HC_FPGA_Demo_Top.v
`timescale 1ns/1ps
module HC_FPGA_Demo_Top
(
input CLOCK_XTAL_50MHz,
input RESET,
input KEY2,
input RXD,
output TXD
);
// ============================================================
// 参数
// ============================================================
localparam P_CLK_FREQ = 50_000_000;
localparam P_UART_BPS = 115200;
// ============================================================
// 状态机
// ============================================================
localparam [2:0]
S0 = 3'd0,
S1 = 3'd1,
S2 = 3'd2,
S3 = 3'd3,
S4 = 3'd4,
S5 = 3'd5,
S6 = 3'd6,
S7 = 3'd7;
// ============================================================
// 内部信号
// ============================================================
wire w_start;
wire m_axis_uart_tready;
reg m_axis_uart_tvalid;
reg [127:0] m_axis_uart_tdata;
wire w_uart_tx;
reg [2:0] r_cur_state;
// ============================================================
// 按键消抖
// ============================================================
key_debounce u_key_debounce(
.i_clk (CLOCK_XTAL_50MHz),
.i_rst_n (RESET),
.i_key (KEY2),
.o_key_pulse (w_start)
);
// ============================================================
// UART Sender
// ============================================================
axis_uart_sender #(
.P_CLK_FREQ (P_CLK_FREQ),
.P_UART_BPS (P_UART_BPS),
.P_FIFO_DEPTH (64)
)
u_axis_uart_sender
(
.i_clk (CLOCK_XTAL_50MHz),
.i_rst_n (RESET),
.s_axis_uart_tvalid (m_axis_uart_tvalid),
.s_axis_uart_tready (m_axis_uart_tready),
.s_axis_uart_tdata (m_axis_uart_tdata),
.o_uart_tx (w_uart_tx)
);
assign TXD = w_uart_tx;
// ============================================================
// UART 发送一个字符
// ============================================================
task uart_put_char;
input [7:0] char_data;
begin
m_axis_uart_tdata <= {
8'd1, // 长度 = 1
char_data, // 字符
112'd0
};
m_axis_uart_tvalid <= 1'b1;
end
endtask
// ============================================================
// AXIS 数据发送状态机
// ============================================================
always @(posedge CLOCK_XTAL_50MHz or negedge RESET) begin
if (!RESET) begin
r_cur_state <= S0;
m_axis_uart_tvalid <= 1'b0;
m_axis_uart_tdata <= 128'd0;
end
else begin
// ========================================================
// m_axis_uart_tvalid 只有在握手完成之后才清零
if (m_axis_uart_tvalid) begin
if (m_axis_uart_tready) begin
// 当前数据已经被 uart_sender 接收
m_axis_uart_tvalid <= 1'b0;
end
end
else begin
// ====================================================
// 当前没有待发送的数据
// 如果按键按下:
// 开始发送第一包
// ====================================================
case (r_cur_state)
// ------------------------------------------------
// 第一包
// 30
// ------------------------------------------------
S0: begin
if (w_start) begin
uart_put_char(8'h30);
r_cur_state <= S1;
end
end
// ------------------------------------------------
// 第二包
// 31
// ------------------------------------------------
S1: begin
uart_put_char(8'h31);
r_cur_state <= S2;
end
// ------------------------------------------------
// 第三包
// 32 33
// ------------------------------------------------
S2: begin
m_axis_uart_tdata <= {8'd2, 8'h32,8'h33,104'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S3;
end
// ------------------------------------------------
// 第四包
// 34 35 36
// ------------------------------------------------
S3: begin
m_axis_uart_tdata <= {8'd3,8'h34,8'h35,8'h36,96'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S4;
end
// ------------------------------------------------
// 第五包
// 37 38 39 40
// ------------------------------------------------
S4: begin
m_axis_uart_tdata <= { 8'd4, 8'h37, 8'h38, 8'h39,8'h40,88'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S5;
end
// ------------------------------------------------
// 第六包
// 61 62 63 64 65
// ------------------------------------------------
S5: begin
m_axis_uart_tdata <= {8'd5, 8'h61,8'h62,8'h63,8'h64,8'h65, 80'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S6;
end
// ------------------------------------------------
// 第七包
// 66 67 68 69 70 71
// ------------------------------------------------
S6: begin
m_axis_uart_tdata <= { 8'd6, 8'h66,8'h67,8'h68,8'h69,8'h70,8'h71, 72'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S7;
end
// ------------------------------------------------
// 第八包
// 72 73 74 75 76 77 78
// ------------------------------------------------
S7: begin
m_axis_uart_tdata <= { 8'd7,8'h72,8'h73,8'h74,8'h75,8'h76,8'h77,8'h78, 64'd0 };
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S0;
end
default: begin
r_cur_state <= S0;
end
endcase
end
end
end
endmodule
Tang-Nano-1K 的 TANG_FPGA_Demo_Top.v
module TANG_FPGA_Demo_Top
(
input CLOCK_XTAL_27MHz,
input RESET,
input KEY1,
output TXD,
output [2:0] LED // 110 R, 101 B, 011 G
);
reg[2:0] r_led;
assign LED=r_led;
localparam P_CLK_FREQ = 27_000_000;
localparam P_UART_BPS = 115200;
// ============================================================
// 状态机
// ============================================================
localparam [2:0]
S0 = 3'd0,
S1 = 3'd1,
S2 = 3'd2,
S3 = 3'd3,
S4 = 3'd4,
S5 = 3'd5,
S6 = 3'd6,
S7 = 3'd7;
// ============================================================
// 内部信号
// ============================================================
wire w_start;
wire m_axis_uart_tready;
reg m_axis_uart_tvalid;
reg [127:0] m_axis_uart_tdata;
wire w_uart_tx;
reg [2:0] r_cur_state;
// ============================================================
// 按键消抖
// ============================================================
key_debounce#(
.P_CLK_FREQ_MHZ(27)
) u_key_debounce(
.i_clk (CLOCK_XTAL_27MHz),
.i_rst_n (RESET),
.i_key (KEY1),
.o_key_pulse (w_start)
);
// ============================================================
// UART Sender
// ============================================================
axis_uart_sender #(
.P_CLK_FREQ (P_CLK_FREQ),
.P_UART_BPS (P_UART_BPS),
.P_FIFO_DEPTH (64)
)
u_axis_uart_sender
(
.i_clk (CLOCK_XTAL_27MHz),
.i_rst_n (RESET),
.s_axis_uart_tvalid (m_axis_uart_tvalid),
.s_axis_uart_tready (m_axis_uart_tready),
.s_axis_uart_tdata (m_axis_uart_tdata),
.o_uart_tx (w_uart_tx)
);
assign TXD = w_uart_tx;
// ============================================================
// UART 发送一个字符
// ============================================================
task uart_put_char;
input [7:0] char_data;
begin
m_axis_uart_tdata <= {
8'd1, // 长度 = 1
char_data, // 字符
112'd0
};
m_axis_uart_tvalid <= 1'b1;
end
endtask
// ============================================================
// AXIS 数据发送状态机
// ============================================================
always @(posedge CLOCK_XTAL_27MHz or negedge RESET) begin
if (!RESET) begin
r_led<=0;
r_cur_state <= S0;
m_axis_uart_tvalid <= 1'b0;
m_axis_uart_tdata <= 128'd0;
end
else begin
// ========================================================
// m_axis_uart_tvalid 只有在握手完成之后才清零
if (m_axis_uart_tvalid) begin
if (m_axis_uart_tready) begin
// 当前数据已经被 uart_sender 接收
m_axis_uart_tvalid <= 1'b0;
end
end
else begin
// ====================================================
// 当前没有待发送的数据
// 如果按键按下:
// 开始发送第一包
// ====================================================
case (r_cur_state)
// ------------------------------------------------
// 第一包
// 30
// ------------------------------------------------
S0: begin
if (w_start) begin
r_led<=~r_led;
uart_put_char(8'h30);
r_cur_state <= S1;
end
end
// ------------------------------------------------
// 第二包
// 31
// ------------------------------------------------
S1: begin
uart_put_char(8'h31);
r_cur_state <= S2;
end
// ------------------------------------------------
// 第三包
// 32 33
// ------------------------------------------------
S2: begin
m_axis_uart_tdata <= {8'd2, 8'h32,8'h33,104'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S3;
end
// ------------------------------------------------
// 第四包
// 34 35 36
// ------------------------------------------------
S3: begin
m_axis_uart_tdata <= {8'd3,8'h34,8'h35,8'h36,96'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S4;
end
// ------------------------------------------------
// 第五包
// 37 38 39 40
// ------------------------------------------------
S4: begin
m_axis_uart_tdata <= { 8'd4, 8'h37, 8'h38, 8'h39,8'h40,88'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S5;
end
// ------------------------------------------------
// 第六包
// 61 62 63 64 65
// ------------------------------------------------
S5: begin
m_axis_uart_tdata <= {8'd5, 8'h61,8'h62,8'h63,8'h64,8'h65, 80'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S6;
end
// ------------------------------------------------
// 第七包
// 66 67 68 69 70 71
// ------------------------------------------------
S6: begin
m_axis_uart_tdata <= { 8'd6, 8'h66,8'h67,8'h68,8'h69,8'h70,8'h71, 72'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S7;
end
// ------------------------------------------------
// 第八包
// 72 73 74 75 76 77 78
// ------------------------------------------------
S7: begin
m_axis_uart_tdata <= { 8'd7,8'h72,8'h73,8'h74,8'h75,8'h76,8'h77,8'h78, 64'd0 };
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S0;
end
default: begin
r_cur_state <= S0;
end
endcase
end
end
end
endmodule
IO_LOC "CLOCK_XTAL_27MHz" 47;
IO_PORT "CLOCK_XTAL_27MHz" IO_TYPE=LVCMOS33 PULL_MODE=UP;
IO_LOC "RESET" 13;
IO_PORT "RESET" IO_TYPE=LVCMOS33 PULL_MODE=UP;
IO_LOC "KEY1" 44;
IO_PORT "KEY1" IO_TYPE=LVCMOS33 PULL_MODE=UP;
IO_LOC "TXD" 40;
IO_PORT "TXD" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8;
IO_LOC "LED[2]" 11;
IO_PORT "LED[2]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8;
IO_LOC "LED[1]" 10;
IO_PORT "LED[1]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8;
IO_LOC "LED[0]" 9;
IO_PORT "LED[0]" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8;
正点原子领航者 ATK_FPGA_Demo_Top.v
`timescale 1ns/1ps
module ATK_FPGA_Demo_Top
(
input CLOCK_XTAL_50MHz,
input RESET,
input KEY,
input RXD,
output TXD
);
// ============================================================
// 参数
// ============================================================
localparam P_CLK_FREQ = 50_000_000;
localparam P_UART_BPS = 115200;
// ============================================================
// 状态机
// ============================================================
localparam [2:0]
S0 = 3'd0,
S1 = 3'd1,
S2 = 3'd2,
S3 = 3'd3,
S4 = 3'd4,
S5 = 3'd5,
S6 = 3'd6,
S7 = 3'd7;
// ============================================================
// 内部信号
// ============================================================
wire w_start;
wire m_axis_uart_tready;
reg m_axis_uart_tvalid;
reg [127:0] m_axis_uart_tdata;
wire w_uart_tx;
reg [2:0] r_cur_state;
// ============================================================
// 按键消抖
// ============================================================
key_debounce u_key_debounce(
.i_clk (CLOCK_XTAL_50MHz),
.i_rst_n (RESET),
.i_key (KEY),
.o_key_pulse (w_start)
);
// ============================================================
// UART Sender
// ============================================================
axis_uart_sender #(
.P_CLK_FREQ (P_CLK_FREQ),
.P_UART_BPS (P_UART_BPS),
.P_FIFO_DEPTH (64)
)
u_axis_uart_sender
(
.i_clk (CLOCK_XTAL_50MHz),
.i_rst_n (RESET),
.s_axis_uart_tvalid (m_axis_uart_tvalid),
.s_axis_uart_tready (m_axis_uart_tready),
.s_axis_uart_tdata (m_axis_uart_tdata),
.o_uart_tx (w_uart_tx)
);
assign TXD = w_uart_tx;
// ============================================================
// UART 发送一个字符
// ============================================================
task uart_put_char;
input [7:0] char_data;
begin
m_axis_uart_tdata <= {
8'd1, // 长度 = 1
char_data, // 字符
112'd0
};
m_axis_uart_tvalid <= 1'b1;
end
endtask
// ============================================================
// AXIS 数据发送状态机
// ============================================================
always @(posedge CLOCK_XTAL_50MHz or negedge RESET) begin
if (!RESET) begin
r_cur_state <= S0;
m_axis_uart_tvalid <= 1'b0;
m_axis_uart_tdata <= 128'd0;
end
else begin
// ========================================================
// m_axis_uart_tvalid 只有在握手完成之后才清零
if (m_axis_uart_tvalid) begin
if (m_axis_uart_tready) begin
// 当前数据已经被 uart_sender 接收
m_axis_uart_tvalid <= 1'b0;
end
end
else begin
// ====================================================
// 当前没有待发送的数据
// 如果按键按下:
// 开始发送第一包
// ====================================================
case (r_cur_state)
// ------------------------------------------------
// 第一包
// 30
// ------------------------------------------------
S0: begin
if (w_start) begin
uart_put_char(8'h30);
r_cur_state <= S1;
end
end
// ------------------------------------------------
// 第二包
// 31
// ------------------------------------------------
S1: begin
uart_put_char(8'h31);
r_cur_state <= S2;
end
// ------------------------------------------------
// 第三包
// 32 33
// ------------------------------------------------
S2: begin
m_axis_uart_tdata <= {8'd2, 8'h32,8'h33,104'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S3;
end
// ------------------------------------------------
// 第四包
// 34 35 36
// ------------------------------------------------
S3: begin
m_axis_uart_tdata <= {8'd3,8'h34,8'h35,8'h36,96'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S4;
end
// ------------------------------------------------
// 第五包
// 37 38 39 40
// ------------------------------------------------
S4: begin
m_axis_uart_tdata <= { 8'd4, 8'h37, 8'h38, 8'h39,8'h40,88'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S5;
end
// ------------------------------------------------
// 第六包
// 61 62 63 64 65
// ------------------------------------------------
S5: begin
m_axis_uart_tdata <= {8'd5, 8'h61,8'h62,8'h63,8'h64,8'h65, 80'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S6;
end
// ------------------------------------------------
// 第七包
// 66 67 68 69 70 71
// ------------------------------------------------
S6: begin
m_axis_uart_tdata <= { 8'd6, 8'h66,8'h67,8'h68,8'h69,8'h70,8'h71, 72'd0};
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S7;
end
// ------------------------------------------------
// 第八包
// 72 73 74 75 76 77 78
// ------------------------------------------------
S7: begin
m_axis_uart_tdata <= { 8'd7,8'h72,8'h73,8'h74,8'h75,8'h76,8'h77,8'h78, 64'd0 };
m_axis_uart_tvalid <= 1'b1;
r_cur_state <= S0;
end
default: begin
r_cur_state <= S0;
end
endcase
end
end
end
endmodule
pin.xdc
create_clock -period 20.000 -name CLOCK_XTAL_50MHz [get_ports CLOCK_XTAL_50MHz]
set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports CLOCK_XTAL_50MHz]
set_property -dict {PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports RESET]
set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports KEY]
set_property -dict {PACKAGE_PIN T19 IOSTANDARD LVCMOS33} [get_ports RXD]
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports TXD]
测试
[18:18:43.172]收←◆30 31 32 33 34 35 36 37 38 39 40 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
[18:18:43.424]收←◆30 31 32 33 34 35 36 37 38 39 40 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
更多推荐
所有评论(0)