1.用System Verilog书写7位数据位,1位偶校验,波特率为115200bps的uart串行发送端 2. 用SV书写对应的行为模型(接收端),并输出激励中的字节值,奇偶性错误的,输出校验错误 3.编写testcase
时间: 2024-05-05 09:16:44 浏览: 218
1. 以下是用System Verilog书写的7位数据位,1位偶校验,波特率为115200bps的uart串行发送端:
```systemverilog
module uart_tx (
input clk,
input reset,
input [6:0] data_in,
output reg tx_out
);
// 波特率计算
localparam BAUD_RATE = 115200;
localparam BIT_TIME = $floor(1000000000/BAUD_RATE); // 单位:ns
// 发送状态机
typedef enum logic [2:0] {
IDLE,
START_BIT,
DATA_BITS,
PARITY_BIT,
STOP_BIT
} TxState;
reg [2:0] state = IDLE;
reg [6:0] data = 7'b0000000;
reg parity = 1'b0;
reg [3:0] bit_cnt = 4'd0;
reg [31:0] bit_timer = 32'd0;
// 计时器
always @(posedge clk) begin
if (reset) begin
bit_timer <= 0;
end else begin
bit_timer <= bit_timer + 1;
end
end
// 状态机
always @(posedge clk) begin
if (reset) begin
state <= IDLE;
data <= 7'b0000000;
parity <= 1'b0;
bit_cnt <= 4'd0;
tx_out <= 1'b1;
end else begin
case (state)
IDLE: begin
if (!tx_out) begin
state <= START_BIT;
bit_cnt <= 4'd0;
bit_timer <= 0;
end
end
START_BIT: begin
if (bit_timer >= BIT_TIME) begin
tx_out <= 1'b0;
state <= DATA_BITS;
bit_cnt <= 4'd1;
bit_timer <= 0;
end
end
DATA_BITS: begin
if (bit_timer >= BIT_TIME) begin
data[bit_cnt-1] <= data_in[bit_cnt-1];
parity <= parity ^ data_in[bit_cnt-1];
bit_cnt <= bit_cnt + 1;
if (bit_cnt == 8) begin
state <= PARITY_BIT;
bit_cnt <= 4'd0;
end else begin
bit_timer <= 0;
end
end
end
PARITY_BIT: begin
if (bit_timer >= BIT_TIME) begin
tx_out <= parity;
state <= STOP_BIT;
bit_timer <= 0;
end
end
STOP_BIT: begin
if (bit_timer >= BIT_TIME) begin
tx_out <= 1'b1;
state <= IDLE;
bit_timer <= 0;
end
end
default: state <= IDLE;
endcase
end
end
endmodule
```
2. 以下是用SV书写的对应的行为模型(接收端),并输出激励中的字节值,奇偶性错误的,输出校验错误:
```systemverilog
module uart_rx (
input clk,
input reset,
input rx_in,
output [6:0] data_out,
output reg valid,
output reg parity_error,
output reg frame_error
);
// 波特率计算
localparam BAUD_RATE = 115200;
localparam BIT_TIME = $floor(1000000000/BAUD_RATE); // 单位:ns
// 接收状态机
typedef enum logic [2:0] {
IDLE,
START_BIT,
DATA_BITS,
PARITY_BIT,
STOP_BIT
} RxState;
reg [2:0] state = IDLE;
reg [6:0] data = 7'b0000000;
reg parity = 1'b0;
reg [3:0] bit_cnt = 4'd0;
reg [31:0] bit_timer = 32'd0;
// 计时器
always @(posedge clk) begin
if (reset) begin
bit_timer <= 0;
end else begin
bit_timer <= bit_timer + 1;
end
end
// 状态机
always @(posedge clk) begin
if (reset) begin
state <= IDLE;
data <= 7'b0000000;
parity <= 1'b0;
bit_cnt <= 4'd0;
valid <= 1'b0;
parity_error <= 1'b0;
frame_error <= 1'b0;
end else begin
case (state)
IDLE: begin
if (!rx_in) begin
state <= START_BIT;
bit_cnt <= 4'd0;
bit_timer <= 0;
end
end
START_BIT: begin
if (bit_timer >= BIT_TIME) begin
state <= DATA_BITS;
bit_cnt <= 4'd1;
bit_timer <= 0;
end
end
DATA_BITS: begin
if (bit_timer >= BIT_TIME) begin
data[bit_cnt-1] <= rx_in;
parity <= parity ^ rx_in;
bit_cnt <= bit_cnt + 1;
if (bit_cnt == 8) begin
state <= PARITY_BIT;
bit_cnt <= 4'd0;
end else begin
bit_timer <= 0;
end
end
end
PARITY_BIT: begin
if (bit_timer >= BIT_TIME) begin
if (rx_in != parity) begin
parity_error <= 1'b1;
end
state <= STOP_BIT;
bit_timer <= 0;
end
end
STOP_BIT: begin
if (bit_timer >= BIT_TIME) begin
if (rx_in) begin
frame_error <= 1'b1;
end else begin
data_out <= data;
valid <= 1'b1;
end
state <= IDLE;
bit_timer <= 0;
end
end
default: state <= IDLE;
endcase
end
end
endmodule
```
3. 以下是编写的testcase:
```systemverilog
module testbench;
// 参数
localparam BAUD_RATE = 115200;
localparam BIT_TIME = $floor(1000000000/BAUD_RATE); // 单位:ns
// 实例化
uart_tx tx (
.clk(clk),
.reset(reset),
.data_in(data_in),
.tx_out(tx_out)
);
uart_rx rx (
.clk(clk),
.reset(reset),
.rx_in(rx_in),
.data_out(data_out),
.valid(valid),
.parity_error(parity_error),
.frame_error(frame_error)
);
// 输入
reg clk = 1;
reg reset = 0;
reg [6:0] data_in;
reg [31:0] timer = 0;
reg [31:0] rand_seed = 1;
// 输出
wire tx_out;
wire [6:0] data_out;
wire valid;
wire parity_error;
wire frame_error;
// 生成随机字节
function automatic void gen_byte(ref byte b);
repeat (8) begin
b[$] = $urandom(rand_seed) % 2;
end
endfunction
// 生成随机奇偶校验的字节
function automatic void gen_parity_byte(ref byte b, ref bit p);
repeat (8) begin
b[$] = $urandom(rand_seed) % 2;
p ^= b[$];
end
b[$] = p;
endfunction
// 生成随机错误字节(奇偶性错误,数据位错误,停止位错误)
function automatic void gen_error_byte(ref byte b, input bit parity, input bit data, input bit stop);
repeat (8) begin
b[$] = $urandom(rand_seed) % 2;
end
b[0] = ~b[0] ^ parity;
if (data) begin
b[$-1] = ~b[$-1];
end
if (stop) begin
b[$] = ~b[$];
end
endfunction
// 生成随机字节序列
function automatic void gen_bytes(ref byte [][8] bytes, input int count, input bit parity);
bit p;
for (int i = 0; i < count; i++) begin
gen_parity_byte(bytes[i], p);
if (parity == 0) begin
p = ~p;
end
end
endfunction
// 生成随机错误字节序列
function automatic void gen_error_bytes(ref byte [][8] bytes, input int count, input bit parity, input bit data, input bit stop);
bit p;
for (int i = 0; i < count; i++) begin
gen_error_byte(bytes[i], parity, data, stop);
end
endfunction
// 计时器
always @(posedge clk) begin
timer <= timer + 1;
end
// 时钟
always #5 clk <= ~clk;
// 测试过程
initial begin
// 测试1:连续发送100个随机字节
$display("Test 1: send 100 random bytes");
gen_bytes(data_in, 100, 1);
repeat (100) begin
#1;
end
repeat (10) begin
#1;
end
// 测试2:发送一个有奇偶校验错误的字节
$display("Test 2: send a byte with parity error");
gen_error_bytes(data_in, 1, 1, 0, 0);
repeat (10) begin
#1;
end
// 测试3:发送一个有数据位错误的字节
$display("Test 3: send a byte with data error");
gen_error_bytes(data_in, 1, 0, 1, 0);
repeat (10) begin
#1;
end
// 测试4:发送一个有停止位错误的字节
$display("Test 4: send a byte with stop error");
gen_error_bytes(data_in, 1, 0, 0, 1);
repeat (10) begin
#1;
end
// 结束
$finish;
end
endmodule
```
阅读全文