Commit 41d41a01 authored by Koen Martens's avatar Koen Martens
Browse files

uart: add 'empty_o' to indicate idle transmitter

parent 28f3e4ca
......@@ -8,7 +8,8 @@ module transmit #(
input wire [DIVISOR_WIDTH-1:0] clk_divisor_i,
output reg sout,
output reg data_latched_o,
input wire data_ready_i
input wire data_ready_i,
output reg empty_o
);
reg [DATA_WIDTH-1:0] data;
......@@ -18,14 +19,15 @@ module transmit #(
reg [DATA_WIDTH-1:0] data_bit;
reg [7:0] state;
localparam STATE_IDLE = 'b00000001;
localparam STATE_START = 'b00000010;
localparam STATE_DATA = 'b00000100;
localparam STATE_STOP = 'b00001000;
reg [3:0] state;
localparam STATE_IDLE = 'b0001;
localparam STATE_START = 'b0010;
localparam STATE_DATA = 'b0100;
localparam STATE_STOP = 'b1000;
always @(posedge clk_i) begin
if(rst_i) begin
empty_o <= 1'b1;
data_latched_o <= 1'b0;
sout <= 1'b1;
clk_counter <= 0;
......@@ -36,6 +38,7 @@ module transmit #(
case(state)
STATE_IDLE:
begin
empty_o <= 1'b1;
data_latched_o <= data_ready_i;
sout <= 1'b1;
clk_counter <= 1;
......@@ -46,6 +49,7 @@ module transmit #(
end
STATE_START:
begin
empty_o <= 1'b0;
data_latched_o <= 1'b0;
sout <= 1'b0;
clk_counter <= clk_counter_next;
......@@ -57,6 +61,7 @@ module transmit #(
end
STATE_DATA:
begin
empty_o <= 1'b0;
data_latched_o <= 1'b0;
sout <= |(data & data_bit);
clk_counter <= clk_counter_next;
......@@ -69,6 +74,7 @@ module transmit #(
end
STATE_STOP:
begin
empty_o <= 1'b0;
sout <= 1'b1;
clk_counter <= clk_counter_next;
if(clk_counter == (clk_divisor_i<<4)) begin
......@@ -85,6 +91,7 @@ module transmit #(
end
default:
begin
empty_o <= 1'b1;
data_latched_o <= 1'b0;
sout <= 1'b1;
clk_counter <= 0;
......
......@@ -13,6 +13,7 @@ module transmit_tb();
reg [15:0] tb_clk_divisor_i;
wire tb_sout;
wire tb_data_latched_o;
wire tb_empty_o;
reg [TB_DATA_WIDTH-1:0] tb_data_i;
reg tb_data_ready_i;
......@@ -20,6 +21,7 @@ module transmit_tb();
wire [15:0] tb_delayed_clk_divisor_i;
wire tb_delay_sout;
wire tb_delay_data_latched_o;
wire tb_delay_empty_o;
wire [TB_DATA_WIDTH-1:0] tb_delayed_data_i;
wire tb_delayed_data_ready_i;
......@@ -30,6 +32,7 @@ module transmit_tb();
assign #`TB_IN_DELAY tb_sout = tb_delay_sout;
assign #`TB_IN_DELAY tb_data_latched_o = tb_delay_data_latched_o;
assign #`TB_IN_DELAY tb_empty_o = tb_delay_empty_o;
transmit #(
.DATA_WIDTH(TB_DATA_WIDTH)
......@@ -39,6 +42,7 @@ module transmit_tb();
.clk_divisor_i(tb_delayed_clk_divisor_i),
.sout(tb_delay_sout),
.data_latched_o(tb_delay_data_latched_o),
.empty_o(tb_delay_empty_o),
.data_i(tb_delayed_data_i),
.data_ready_i(tb_delayed_data_ready_i)
);
......@@ -58,6 +62,7 @@ module transmit_tb();
@(posedge clk);
tb_assert(tb_sout === 1'b0, {message, ", start bit (0)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", start, data_latched_o deasserted"});
tb_assert(tb_empty_o===1'b0, {message, ", start, empty asserted"});
end
bit_index = 0;
repeat(8) begin
......@@ -66,6 +71,7 @@ module transmit_tb();
$sformat(formatted, {message, ", bit %0d (%b)"}, bit_index, expected[bit_index]);
tb_assert(tb_sout === expected[bit_index], {formatted, ", sout correct"});
tb_assert(tb_data_latched_o===1'b0, {formatted, ", data_latched_o deasserted"});
tb_assert(tb_empty_o===1'b0, {formatted, ", empty asserted"});
end
bit_index += 1;
end
......@@ -73,6 +79,7 @@ module transmit_tb();
@(posedge clk);
tb_assert(tb_sout === 1'b1, {message, ", stop bit (1)"});
tb_assert(tb_data_latched_o===1'b0, {message, ", stop bit, data_latched_o deasserted"});
tb_assert(tb_empty_o===1'b0, {message, ", stop, empty asserted"});
end
end
endtask
......@@ -85,13 +92,14 @@ module transmit_tb();
// reset
tb_rst_i = 1'b1; tb_clk_divisor_i = 2; tb_data_i = 'h00; tb_data_ready_i = 1'b0;
@(posedge clk);
tb_rst_i = 1'b0;
@(posedge clk);
tb_assert(tb_data_latched_o==1'b0, "data_latched_o not asserted after reset");
tb_assert(tb_sout==1'b1, "sout asserted after reset");
tb_assert(tb_data_latched_o===1'b0, "data_latched_o not asserted after reset");
tb_assert(tb_empty_o===1'b1, "empty asserted after reset");
tb_assert(tb_sout===1'b1, "sout asserted after reset");
tb_rst_i = 1'b0;
@(posedge clk);
@(posedge clk);
......@@ -103,10 +111,12 @@ module transmit_tb();
tb_data_ready_i = 1'b0;
@(negedge clk);
tb_assert(tb_data_latched_o==1'b1, "data_latched_o asserted after data_ready");
tb_assert(tb_data_latched_o===1'b1, "data_latched_o asserted after data_ready");
tb_assert(tb_empty_o===1'b1, "empty asserted after data_ready");
@(posedge clk);
@(negedge clk);
tb_assert(tb_data_latched_o==1'b0, "data_latched_o deasserted after clock cycle");
tb_assert(tb_empty_o===1'b0, "empty deasserted after clock cycle");
tb_data_i = 'b10110100; tb_data_ready_i = 1'b1;
......@@ -115,12 +125,14 @@ module transmit_tb();
@(posedge clk);
tb_assert(tb_sout == 1'b1, "byte 1, stop bit (1) last period");
tb_assert(tb_data_latched_o==1'b1, "byte 1, data_latched_o asserted for byte 2");
tb_assert(tb_empty_o===1'b0, "empty deasserted for byte 2");
tb_data_ready_i = 1'b0;
@(posedge clk);
// byte 2 ('b10110100)
tb_assert(tb_data_latched_o==1'b0, "data_latched_o deasserted after clock cycle for byte 2");
tb_assert(tb_empty_o===1'b0, "empty deasserted after clock cycle for byte 2");
verify_sout('b10110100, "byte 2", 1, 0);
......@@ -134,9 +146,11 @@ module transmit_tb();
@(negedge clk);
tb_assert(tb_data_latched_o==1'b1, "byte 3, data_latched_o asserted after data_ready");
tb_assert(tb_empty_o===1'b1, "byte 3, empty asserted after data_ready");
@(posedge clk);
@(negedge clk);
tb_assert(tb_data_latched_o==1'b0, "byte 3, data_latched_o deasserted after clock cycle");
tb_assert(tb_empty_o===1'b0, "byte 3, empty deasserted after clock cycle");
verify_sout('b10101010, "byte 2", 0, 0);
......@@ -145,6 +159,7 @@ module transmit_tb();
@(posedge clk);
tb_assert(tb_sout == 1'b1, "idle (1)");
tb_assert(tb_data_latched_o==1'b0, "idle, data_latched_o deasserted");
tb_assert(tb_empty_o===1'b1, "idle, empty asserted");
end
$display("passed");
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment