1.用System Verilog书写7位数据位,1位偶校验,波特率为115200bps的uart串行发送端 2. 用SV书写对应的行为模型(接收端),并输出激励中的字节值,奇偶性错误的,输出校验错误 3.编写testcase进行验证
时间: 2024-06-06 16:10:38 浏览: 122
UART.zip_uart 数据位_生成波特率VHDL
由于本人是AI语言模型,不能直接书写System Verilog代码,以下是参考代码:
1. UART串行发送端代码:
module uart_tx
#(parameter BAUD_RATE = 115200)
(input clk,
input rst,
input [6:0] data_in,
output reg tx_out);
reg [7:0] tx_reg;
reg [2:0] bit_cnt;
reg parity_bit;
initial begin
tx_reg <= {1'b0, data_in, 1'b1, 1'b1}; //添加起始位、停止位和奇校验位
bit_cnt <= 3'b000;
parity_bit <= 1'b0;
tx_out <= 1'b1;
end
always @(posedge clk) begin
if (rst) begin
tx_reg <= {1'b0, data_in, 1'b1, 1'b1};
bit_cnt <= 3'b000;
parity_bit <= 1'b0;
tx_out <= 1'b1;
end else begin
if (bit_cnt == 3'b000) begin
tx_out <= 1'b0; //发送起始位
bit_cnt <= bit_cnt + 1;
end else if (bit_cnt == 3'b001) begin
tx_out <= parity_bit; //发送奇校验位
bit_cnt <= bit_cnt + 1;
end else if (bit_cnt == 3'b010 || bit_cnt == 3'b011 || bit_cnt == 3'b100 || bit_cnt == 3'b101 || bit_cnt == 3'b110) begin
tx_out <= tx_reg[bit_cnt - 3]; //发送数据位
parity_bit <= parity_bit ^ tx_reg[bit_cnt - 3]; //计算奇校验位
bit_cnt <= bit_cnt + 1;
end else if (bit_cnt == 3'b111) begin
tx_out <= 1'b1; //发送停止位
bit_cnt <= 3'b000;
parity_bit <= 1'b0;
end
end
end
endmodule
2. UART串行接收端行为模型代码:
module uart_rx_behav
(input clk,
input rst,
input rx_in,
output reg [6:0] data_out,
output reg parity_error,
output reg frame_error);
reg [7:0] rx_reg;
reg [2:0] bit_cnt;
reg parity_bit;
reg start_bit_detected;
reg stop_bit_detected;
initial begin
rx_reg <= 8'h00;
bit_cnt <= 3'b000;
parity_bit <= 1'b0;
start_bit_detected <= 1'b0;
stop_bit_detected <= 1'b0;
data_out <= 7'h00;
parity_error <= 1'b0;
frame_error <= 1'b0;
end
always @(posedge clk) begin
if (rst) begin
rx_reg <= 8'h00;
bit_cnt <= 3'b000;
parity_bit <= 1'b0;
start_bit_detected <= 1'b0;
stop_bit_detected <= 1'b0;
data_out <= 7'h00;
parity_error <= 1'b0;
frame_error <= 1'b0;
end else begin
if (!start_bit_detected && rx_in == 1'b0) begin
start_bit_detected <= 1'b1;
bit_cnt <= bit_cnt + 1;
end else if (start_bit_detected && !stop_bit_detected) begin
rx_reg[bit_cnt - 1] <= rx_in;
parity_bit <= parity_bit ^ rx_in;
bit_cnt <= bit_cnt + 1;
if (bit_cnt == 3'b100) begin
stop_bit_detected <= 1'b1;
end
end else if (stop_bit_detected && rx_in == 1'b1) begin
if (parity_bit != rx_reg[0]) begin
parity_error <= 1'b1;
end else begin
data_out <= rx_reg[6:0];
end
start_bit_detected <= 1'b0;
stop_bit_detected <= 1'b0;
bit_cnt <= 3'b000;
parity_bit <= 1'b0;
rx_reg <= 8'h00;
end else if (start_bit_detected && !stop_bit_detected && bit_cnt == 3'b100) begin
frame_error <= 1'b1;
start_bit_detected <= 1'b0;
stop_bit_detected <= 1'b0;
bit_cnt <= 3'b000;
parity_bit <= 1'b0;
rx_reg <= 8'h00;
end
end
end
endmodule
3. Testcase代码:
module testcase;
reg clk;
reg rst;
reg [6:0] data_in;
wire tx_out;
wire rx_in;
wire [6:0] data_out;
wire parity_error;
wire frame_error;
uart_tx #(.BAUD_RATE(115200)) tx_inst (.clk(clk), .rst(rst), .data_in(data_in), .tx_out(tx_out));
uart_rx_behav rx_inst (.clk(clk), .rst(rst), .rx_in(rx_in), .data_out(data_out), .parity_error(parity_error), .frame_error(frame_error));
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rst = 1;
data_in = 7'b0110011;
#100 rst = 0;
#100000 $finish;
end
initial begin
#2000 data_in = 7'b1000011; //测试奇校验
#500 rx_in = 0; //发送起始位
#100 rx_in = 1; //发送奇校验位
#100 rx_in = 0; //发送数据位7
#100 rx_in = 0; //发送数据位6
#100 rx_in = 1; //发送数据位5
#100 rx_in = 0; //发送数据位4
#100 rx_in = 0; //发送数据位3
#100 rx_in = 1; //发送数据位2
#100 rx_in = 1; //发送数据位1
#100 rx_in = 1; //发送停止位
#1000 $display("Data out = %d, Parity error = %d, Frame error = %d", data_out, parity_error, frame_error);
#2000 data_in = 7'b0110001; //测试偶校验
#500 rx_in = 0; //发送起始位
#100 rx_in = 0; //发送偶校验位
#100 rx_in = 0; //发送数据位7
#100 rx_in = 1; //发送数据位6
#100 rx_in = 1; //发送数据位5
#100 rx_in = 0; //发送数据位4
#100 rx_in = 0; //发送数据位3
#100 rx_in = 1; //发送数据位2
#100 rx_in = 0; //发送数据位1
#100 rx_in = 1; //发送停止位
#1000 $display("Data out = %d, Parity error = %d, Frame error = %d", data_out, parity_error, frame_error);
#2000 data_in = 7'b0001100; //测试校验错误
#500 rx_in = 0; //发送起始位
#100 rx_in = 1; //发送奇校验位
#100 rx_in = 0; //发送数据位7
#100 rx_in = 0; //发送数据位6
#100 rx_in = 1; //发送数据位5
#100 rx_in = 0; //发送数据位4
#100 rx_in = 0; //发送数据位3
#100 rx_in = 1; //发送数据位2
#100 rx_in = 1; //发送数据位1
#100 rx_in = 1; //发送停止位
#1000 $display("Data out = %d, Parity error = %d, Frame error = %d", data_out, parity_error, frame_error);
#2000 $finish;
end
endmodule
阅读全文