记录写SDRAM项目过程中出现的问题
? ? ? ? 输入信号:系统时钟,复位信号(低电平有效),输入数据(串行)
? ? ? ? 输出信号:串转并输出数据(8位),并行输出后拉高信号
? ? ? ? 中间变量:串行输入数据延时三拍(延时三拍为了信号更加稳定,防止亚稳态?延迟两拍送入串行数据,延时三拍获得接收信号下降沿),接收标志信号(接收数据时拉高)波特计数(当计数到中间值时将数据读取,此时信号最稳定),比特计数(记录8个比特为一个寄存器)
????????
`define SIM
module uart(
input sclk,
input srst,
input rs232_rx,
output reg [7:0] rx_data,
output reg po_flag
);
//****************************************************
//define parameter and internal signals
//****************************************************
`ifndef SIM
localparam baud_end = 5207;
`else
localparam baud_end = 56;
`endif
localparam baud_m = baud_end /2 -1;
localparam bit_end = 8;
reg rx_r1;
reg rx_r2;
reg rx_r3;
reg rx_flag;
reg [12:0] baud_cnt; //5208
reg bit_flag;
reg [3:0] bit_cnt;
wire rx_neg;
//====================================================
// main code
//====================================================
assign rx_neg = ~rx_r2 & rx_r3;
always @(posedge sclk) begin
rx_r1 <= rs232_rx;
rx_r2 <= rx_r1;
rx_r3 <= rx_r2;
end
always@(posedge sclk or negedge srst) begin
if(srst == 1'b0)
rx_flag <= 1'b0;
else if(rx_neg == 1'b1)
rx_flag <= 1'b1;
else if(baud_cnt == baud_end && bit_end == 'd0)
rx_flag <= 1'b0; //else
end
always@(posedge sclk or negedge srst) begin // else if是有优先级的
if(srst == 1'b0)
baud_cnt <= 'd0;
else if(baud_cnt == baud_end)
baud_cnt <= 'd0;
else if (rx_flag ==1'b1 )
baud_cnt <=baud_cnt +1'b1;
else
baud_cnt <= 'd0;
end
always@(posedge sclk or negedge srst) begin
if(srst == 1'b0)
bit_flag <= 1'b0;
else if(baud_cnt == baud_m)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
end
always@(posedge sclk or negedge srst) begin
if(srst == 1'b0)
bit_cnt <= 'd0;
else if(bit_flag == 1'b1 && bit_cnt == bit_end)
bit_cnt <= 'd0;
else if(bit_flag == 1'b1)
bit_cnt <= bit_cnt + 1'b1;
end
always@(posedge sclk or negedge srst) begin
if(srst == 1'b0)
rx_data <= 'd0;
else if(bit_flag == 1'b1 && bit_cnt >= 'd1)
rx_data <= {rx_r2 , rx_data[7:1]};
end
always@(posedge sclk or negedge srst) begin
if(srst ==1'b0)
po_flag <= 1'b0;
else if(bit_cnt == bit_end && bit_flag == 1'b1)
po_flag <= 1'b1;
else
po_flag <= 1'b0;
end
endmodule
测试代码:
for语句一般不用在功能代码中,这样会综合出复杂的电路
注意串行数据循环传输(data[ ])时要有延时
问题1:readmemh函数传输时候一开始出现x信号,是因为写的相对路径(./data.txt),而仿真时候的工作路径与文件保存的位置不一样,改成了绝对路径。
问题2:波形仿真没有变化,通过查看波形图发现bit_cnt信号定义写错(baud_cnt写成bit_cnt)
问题3:仿真出来的数据只有00和55,后面的数据不一致(未解决),但是其他信号的波形图与视频上的一致。
收获1:串行数据的传递代码示例(寻找更好地写法)
收获2:task函数格式,readmemh函数格式(并不深入)
收获3:通过仿真波形寻找自己代码中问题(解决了data数据无法传输的问题,通过信号没有变化发现了代码中的bit_cnt和baud_cnt写错)
`timescale 1ns/1ns
module tb_uart_rx;
reg sclk;
reg srst;
reg rs232;
wire po_flag;
wire [7:0] rx_data;
//外部txt文件数据写入存储器
reg [7:0] mem[3:0];
initial begin
sclk <= 1;
srst <= 0;
rs232 <= 1;
#100
srst <= 1;
#100
tx_byte();
end
always #5 sclk = ~sclk; //10ns
initial $readmemh("D:/tx_data.txt", mem);
task tx_byte();
integer i ;
for(i=0;i<4;i=i+1)begin
tx_bit(mem[i]);
end
endtask
task tx_bit( //for循环最好只在仿真时候写,如果写功能语句则会综合出复杂的电路
input [7:0] data
);
integer i;
for(i=0;i<10;i=i+1)begin
case(i)
0: rs232 <= 1'b0; //起始位
1: rs232 <= data[0];
2: rs232 <= data[1];
3: rs232 <= data[2];
4: rs232 <= data[3];
5: rs232 <= data[4];
6: rs232 <= data[5];
7: rs232 <= data[6];
8: rs232 <= data[7];
9: rs232 <= 1'b1; //停止位
endcase
#560;
end
endtask
uart uart_inst(
.sclk (sclk),
.srst (srst),
.rs232_rx (rs232),
.rx_data (rx_data),
.po_flag (po_flag)
);
endmodule