算是对前几天学的做了一个复习,利用串口收发模块和ram ip核进行了一个简易收发显示。资源已经上传有需要自取。
实验中遇到问题:1:创建的simple ram 双端口只有一个写请求信号,可以控制是否写入,但是会一直读出数据,ram ip配置界面没找到读请求控制信号,所以就算写入一些数据,最终会一直重复读取存储的数据。
2:wea信号不用一直触发,写一个数据时触发一次就好了
3:使用vivado+vscdoe时,如果还有文件在vscode打开,仿真和综合时会提示
必须关掉vscode才能继续。
4:小梅哥的crtl模块对tx_done进行了三个延时,因为ram读出数据加了两个寄存器,有3个周期延时,才能正确控制uart_tx模块的send_en信号,但是我没看他写的uart_tx模块,自己写的时候是要求一直触发send_en才能进行发送,所以不需要考虑tx_done延时,只需要发送状态为发送数据时即有按键输入时就触发,这比他的简单多了。
仿真时模拟串口依次发送:5a 11 22 33 44 55 66 5a
总共8个字节,所以addra一直加到08,dina为接收到的data_rx数据进行存储,但是想要读出数据时,addrb一直增加到所有的数据都读完再循环,但是除了写入的数据都是00,addra和addrb都是7位宽,所以应该以128个数据为一次循环,如图doutb:
上板验证:波特率设置为115200,从串口调试助手依次发送15 16 17 18 19,最终成功循环接收数据,验证确实为128个数据为一组循环。
主模块代码:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/04/25 10:21:48
// Design Name:
// Module Name: uart_ram
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_ram_t_r(
clk,
rst,
uart_tx,
uart_rx,
key_in,
led1,
led2
);
input clk;
input rst;
input uart_rx;
output uart_tx;
input key_in;
output led1;//Tx_done 显示
output led2;//Rx_done显示
//tx模块参数
wire [7:0]Data_tx;
wire Send_en;
wire Tx_done;
//rx模块参数
wire [7:0]Data_rx;
wire Rx_done;
//uart_ram ip 参数
wire [6:0]addra;
//wire [7:0]data;
wire wea;
wire [6:0]addrb;
//key_filter参数
//wire key_out;
//消除rst亚稳态
reg rst_reg1;
reg rst_reg2;
assign led1=Tx_done;
assign led2=Rx_done;
always @(posedge clk or negedge rst) begin
if(~rst)
rst_reg1<=1'b0;
else
rst_reg1<=1'b1;
end
always @(posedge clk or negedge rst) begin
if(~rst)
rst_reg2<=1'b0;
else
rst_reg2<=rst_reg1;
end
uart_tx uart_tx1(
.clk(clk),
.rst_n(rst_reg2),
.Data(Data_tx),
.Send_en(Send_en),
.Baud_set(3'b100),
.uart_tx(uart_tx),
.Tx_done(Tx_done)
);
uart_rx uart_rx1(
.uart_rx(uart_rx),
.clk(clk),
.rst_n(rst_reg2),
.Data_rx(Data_rx),
.Rx_done(Rx_done)
);
uart_ram uart_ram1(
.clka(clk),
.wea(wea),
.addra(addra),
.dina(Data_rx),
.clkb(clk),
.addrb(addrb),
.doutb(Data_tx)
);
ctrl ctrl(
.clk(clk),
.rst_reg2(rst_reg2),
.key(key_in),
.Rx_done(Rx_done),
.Tx_done(Tx_done),
.Send_en(Send_en),
.wea(wea),
.addra(addra),
.addrb(addrb)
);
endmodule
uart_tx模块:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/03/08 20:35:22
// Design Name:
// Module Name: uart
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_tx(
clk,
rst_n,
Data,
Send_en,
Baud_set,
uart_tx,
Tx_done
);
input clk;
input rst_n;
input [7:0]Data;
input Send_en;
input [2:0]Baud_set;
output reg uart_tx;
output reg Tx_done;
reg [19:0] count;
reg [19:0] BPS; //set Baud
reg [3:0]bit_count;//比特计数器
reg [7:0]Data_reg;//数据寄存器
parameter START_BIT=1'b0;
parameter STOP_BIT=1'b1;
//串口是异步收发器,保证发送的数据在时钟到来前稳定,对输入数据寄存
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
Data_reg<=8'd0;
else if(Send_en==1'b1);
Data_reg<=Data;
end