Remove UART DTM
This commit is contained in:
parent
be6b2f3f76
commit
dfb07822ee
|
@ -1,4 +0,0 @@
|
|||
file hazard3_uart_dtm.v
|
||||
file hazard3_uart_dtm_fifo.v
|
||||
|
||||
file ../cdc/hazard3_sync_1bit.v
|
|
@ -1,349 +0,0 @@
|
|||
/**********************************************************************
|
||||
* DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE *
|
||||
* Version 3, April 2008 *
|
||||
* *
|
||||
* Copyright (C) 2021 Luke Wren *
|
||||
* *
|
||||
* Everyone is permitted to copy and distribute verbatim or modified *
|
||||
* copies of this license document and accompanying software, and *
|
||||
* changing either is allowed. *
|
||||
* *
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION *
|
||||
* *
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO. *
|
||||
* 1. We're NOT RESPONSIBLE WHEN IT DOESN'T FUCKING WORK. *
|
||||
* *
|
||||
*********************************************************************/
|
||||
|
||||
// UART Debug Transport Module: connect an external two-wire 1 Mbaud UART
|
||||
// interface to an APB Debug Module port.
|
||||
//
|
||||
// This is not suitable for production systems (it's a UART...) but is a
|
||||
// simple way to get your FPGA board up and running.
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module hazard3_uart_dtm #(
|
||||
// Expected to run at 1 Mbaud from some fixed reference frequency.
|
||||
parameter BAUD_CLKDIV = 12,
|
||||
parameter DTM_ID_REG = 32'hdeadbeef,
|
||||
parameter W_BAUDCTR = $clog2(BAUD_CLKDIV) // do not modify
|
||||
) (
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
// External UART interface
|
||||
input wire rx,
|
||||
output wire tx,
|
||||
|
||||
// APB port to Debug Module
|
||||
output wire psel,
|
||||
output wire penable,
|
||||
output wire pwrite,
|
||||
output wire [7:0] paddr,
|
||||
output wire [31:0] pwdata,
|
||||
input wire [31:0] prdata,
|
||||
input wire pready,
|
||||
input wire pslverr
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Serial interface
|
||||
|
||||
wire [7:0] tx_wdata;
|
||||
wire tx_wvld;
|
||||
wire tx_wrdy;
|
||||
wire [7:0] tx_rdata;
|
||||
wire tx_rvld;
|
||||
wire tx_rrdy = 1'b1;
|
||||
|
||||
wire [7:0] rx_wdata;
|
||||
wire rx_wvld;
|
||||
wire rx_wrdy;
|
||||
wire [7:0] rx_rdata;
|
||||
wire rx_rvld;
|
||||
wire rx_rrdy;
|
||||
|
||||
hazard3_uart_dtm_fifo #(
|
||||
.WIDTH(8),
|
||||
.LOG_DEPTH(2)
|
||||
) tx_fifo (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.wdata (tx_wdata),
|
||||
.wvld (tx_wvld),
|
||||
.wrdy (tx_wrdy),
|
||||
.rdata (tx_rdata),
|
||||
.rvld (tx_rvld),
|
||||
.rrdy (tx_rrdy)
|
||||
);
|
||||
|
||||
hazard3_uart_dtm_fifo #(
|
||||
.WIDTH(8),
|
||||
.LOG_DEPTH(2)
|
||||
) rx_fifo (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.wdata (rx_wdata),
|
||||
.wvld (rx_wvld),
|
||||
.wrdy (rx_wrdy),
|
||||
.rdata (rx_rdata),
|
||||
.rvld (rx_rvld),
|
||||
.rrdy (rx_rrdy)
|
||||
);
|
||||
|
||||
|
||||
reg [W_BAUDCTR-1:0] tx_baudctr;
|
||||
reg [9:0] tx_shiftreg;
|
||||
reg [3:0] tx_shiftctr;
|
||||
|
||||
assign tx_rrdy = ~|tx_shiftctr;
|
||||
assign tx = tx_shiftreg[0];
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
tx_baudctr <= {W_BAUDCTR{1'b0}};
|
||||
tx_shiftreg <= 10'h3ff;
|
||||
tx_shiftctr <= 4'd0;
|
||||
end else if (tx_rvld && tx_rrdy) begin
|
||||
tx_baudctr <= BAUD_CLKDIV - 1;
|
||||
tx_shiftreg <= {1'b1, tx_rdata, 1'b0};
|
||||
tx_shiftctr <= 4'd10;
|
||||
end else if (|tx_baudctr) begin
|
||||
tx_baudctr <= tx_baudctr - 1'b1;
|
||||
end else if (|tx_shiftctr) begin
|
||||
tx_baudctr <= BAUD_CLKDIV - 1;
|
||||
tx_shiftreg <= {1'b1, tx_shiftreg[9:1]};
|
||||
tx_shiftctr <= tx_shiftctr - 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
wire rx_sync;
|
||||
hazard3_sync_1bit #(
|
||||
.N_STAGES (2)
|
||||
) sync_req (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.i (rx),
|
||||
.o (rx_sync)
|
||||
);
|
||||
|
||||
reg [W_BAUDCTR-1:0] rx_baudctr;
|
||||
reg [7:0] rx_shiftreg;
|
||||
reg [3:0] rx_shiftctr;
|
||||
|
||||
// Only push if the frame ends with a valid stop bit:
|
||||
assign rx_wvld = ~|rx_baudctr && rx_shiftctr == 4'd1 && rx_sync;
|
||||
assign rx_wdata = rx_shiftreg;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
rx_baudctr <= {W_BAUDCTR{1'b0}};
|
||||
rx_shiftreg <= 8'h00;
|
||||
rx_shiftctr <= 4'd0;
|
||||
end else if (~|rx_shiftctr && ~|rx_baudctr && !rx_sync) begin
|
||||
rx_shiftctr <= 4'd10;
|
||||
// Start with half-period to get sampling alignment
|
||||
rx_baudctr <= (BAUD_CLKDIV - 1) / 2;
|
||||
end else if (|rx_baudctr) begin
|
||||
rx_baudctr <= rx_baudctr - 1'b1;
|
||||
end else if (|rx_shiftctr) begin
|
||||
rx_baudctr <= BAUD_CLKDIV - 1;
|
||||
rx_shiftctr <= rx_shiftctr - 1'b1;
|
||||
if (rx_shiftctr != 4'd1 && rx_shiftctr != 4'd10)
|
||||
rx_shiftreg <= {rx_sync, rx_shiftreg[7:1]};
|
||||
end
|
||||
end
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Command state machine
|
||||
|
||||
localparam W_STATE = 5;
|
||||
|
||||
localparam [W_STATE-1:0] S_DORMANT0 = 5'd0;
|
||||
localparam [W_STATE-1:0] S_DORMANT1 = 5'd1;
|
||||
localparam [W_STATE-1:0] S_DORMANT2 = 5'd2;
|
||||
localparam [W_STATE-1:0] S_DORMANT3 = 5'd3;
|
||||
|
||||
localparam [W_STATE-1:0] S_CMD = 5'd4;
|
||||
|
||||
localparam [W_STATE-1:0] S_ID0 = 5'd5;
|
||||
localparam [W_STATE-1:0] S_ID1 = 5'd6;
|
||||
localparam [W_STATE-1:0] S_ID2 = 5'd7;
|
||||
localparam [W_STATE-1:0] S_ID3 = 5'd8;
|
||||
|
||||
localparam [W_STATE-1:0] S_WADDR = 5'd9;
|
||||
localparam [W_STATE-1:0] S_WDATA0 = 5'd10;
|
||||
localparam [W_STATE-1:0] S_WDATA1 = 5'd11;
|
||||
localparam [W_STATE-1:0] S_WDATA2 = 5'd12;
|
||||
localparam [W_STATE-1:0] S_WDATA3 = 5'd13;
|
||||
localparam [W_STATE-1:0] S_WSETUP = 5'd14;
|
||||
localparam [W_STATE-1:0] S_WACCESS = 5'd15;
|
||||
|
||||
localparam [W_STATE-1:0] S_RADDR = 5'd16;
|
||||
localparam [W_STATE-1:0] S_RSETUP = 5'd17;
|
||||
localparam [W_STATE-1:0] S_RACCESS = 5'd18;
|
||||
localparam [W_STATE-1:0] S_RDATA0 = 5'd19;
|
||||
localparam [W_STATE-1:0] S_RDATA1 = 5'd20;
|
||||
localparam [W_STATE-1:0] S_RDATA2 = 5'd21;
|
||||
localparam [W_STATE-1:0] S_RDATA3 = 5'd22;
|
||||
|
||||
localparam CMD_NOP = 8'h00;
|
||||
localparam CMD_ID = 8'h01;
|
||||
localparam CMD_READ = 8'h02;
|
||||
localparam CMD_WRITE = 8'h03;
|
||||
localparam CMD_RETURN_TO_DORMANT = 8'ha5;
|
||||
|
||||
reg [W_STATE-1:0] state;
|
||||
reg [7:0] dm_addr;
|
||||
reg [31:0] dm_data;
|
||||
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
state <= S_DORMANT0;
|
||||
dm_addr <= 8'h0;
|
||||
dm_data <= 32'h0;
|
||||
end else case (state)
|
||||
S_DORMANT0: if (rx_rvld) state <= rx_rdata == "S" ? S_DORMANT1 : S_DORMANT0;
|
||||
S_DORMANT1: if (rx_rvld) state <= rx_rdata == "U" ? S_DORMANT2 : S_DORMANT0;
|
||||
S_DORMANT2: if (rx_rvld) state <= rx_rdata == "P" ? S_DORMANT3 : S_DORMANT0;
|
||||
S_DORMANT3: if (rx_rvld) state <= rx_rdata == "?" ? S_CMD : S_DORMANT0;
|
||||
S_CMD: if (rx_rvld) begin
|
||||
if (rx_rdata == CMD_READ)
|
||||
state <= S_RADDR;
|
||||
else if (rx_rdata == CMD_WRITE)
|
||||
state <= S_WADDR;
|
||||
else if (rx_rdata == CMD_ID)
|
||||
state <= S_ID0;
|
||||
else if (rx_rdata == CMD_RETURN_TO_DORMANT)
|
||||
state <= S_DORMANT0;
|
||||
// NOP or invalid leave DTM in command state.
|
||||
end
|
||||
|
||||
S_ID0: if (tx_wrdy) state <= S_ID1;
|
||||
S_ID1: if (tx_wrdy) state <= S_ID2;
|
||||
S_ID2: if (tx_wrdy) state <= S_ID3;
|
||||
S_ID3: if (tx_wrdy) state <= S_CMD;
|
||||
|
||||
S_WADDR: if (rx_rvld) begin
|
||||
state <= S_WDATA0;
|
||||
dm_addr <= rx_rdata;
|
||||
end
|
||||
S_WDATA0: if (rx_rvld) begin
|
||||
state <= S_WDATA1;
|
||||
dm_data <= {rx_rdata, dm_data[31:8]};
|
||||
end
|
||||
S_WDATA1: if (rx_rvld) begin
|
||||
state <= S_WDATA2;
|
||||
dm_data <= {rx_rdata, dm_data[31:8]};
|
||||
end
|
||||
S_WDATA2: if (rx_rvld) begin
|
||||
state <= S_WDATA3;
|
||||
dm_data <= {rx_rdata, dm_data[31:8]};
|
||||
end
|
||||
S_WDATA3: if (rx_rvld) begin
|
||||
state <= S_WSETUP;
|
||||
dm_data <= {rx_rdata, dm_data[31:8]};
|
||||
end
|
||||
S_WSETUP: state <= S_WACCESS;
|
||||
S_WACCESS: if (pready) state <= S_CMD;
|
||||
|
||||
S_RADDR: if (rx_rvld) begin
|
||||
state <= S_RSETUP;
|
||||
dm_addr <= rx_rdata;
|
||||
end
|
||||
S_RSETUP: state <= S_RACCESS;
|
||||
S_RACCESS: if (pready) begin
|
||||
dm_data <= prdata;
|
||||
state <= S_RDATA0;
|
||||
end
|
||||
S_RDATA0: if (tx_wrdy) begin
|
||||
dm_data <= {rx_rdata, dm_data[31:8]};
|
||||
state <= S_RDATA1;
|
||||
end
|
||||
S_RDATA1: if (tx_wrdy) begin
|
||||
dm_data <= {rx_rdata, dm_data[31:8]};
|
||||
state <= S_RDATA2;
|
||||
end
|
||||
S_RDATA2: if (tx_wrdy) begin
|
||||
dm_data <= {rx_rdata, dm_data[31:8]};
|
||||
state <= S_RDATA3;
|
||||
end
|
||||
S_RDATA3: if (tx_wrdy) begin
|
||||
dm_data <= {rx_rdata, dm_data[31:8]};
|
||||
state <= S_CMD;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Bus & FIFO hookup
|
||||
|
||||
wire state_is_dormant =
|
||||
state == S_DORMANT0 ||
|
||||
state == S_DORMANT1 ||
|
||||
state == S_DORMANT2 ||
|
||||
state == S_DORMANT3;
|
||||
|
||||
wire state_is_id =
|
||||
state == S_ID0 ||
|
||||
state == S_ID1 ||
|
||||
state == S_ID2 ||
|
||||
state == S_ID3;
|
||||
|
||||
wire state_is_wdata =
|
||||
state == S_WDATA0 ||
|
||||
state == S_WDATA1 ||
|
||||
state == S_WDATA2 ||
|
||||
state == S_WDATA3;
|
||||
|
||||
wire state_is_rdata =
|
||||
state == S_RDATA0 ||
|
||||
state == S_RDATA1 ||
|
||||
state == S_RDATA2 ||
|
||||
state == S_RDATA3;
|
||||
|
||||
// Note we don't consume the read padding bytes during the read data phase --
|
||||
// these are actually interpreted as NOPs preceding the next command.
|
||||
// (They are still important for bus pacing though.)
|
||||
assign rx_rrdy =
|
||||
state_is_dormant ||
|
||||
state == S_CMD ||
|
||||
state == S_WADDR ||
|
||||
state == S_RADDR ||
|
||||
state_is_wdata;
|
||||
|
||||
assign tx_wvld =
|
||||
(state_is_wdata && rx_rvld) ||
|
||||
state_is_rdata ||
|
||||
state_is_id;
|
||||
|
||||
assign tx_wdata =
|
||||
state_is_wdata ? rx_rdata :
|
||||
state == S_ID0 ? DTM_ID_REG[ 7: 0] :
|
||||
state == S_ID1 ? DTM_ID_REG[15: 8] :
|
||||
state == S_ID2 ? DTM_ID_REG[23:16] :
|
||||
state == S_ID3 ? DTM_ID_REG[31:24] : dm_data[7:0];
|
||||
|
||||
assign psel =
|
||||
state == S_WSETUP ||
|
||||
state == S_WACCESS ||
|
||||
state == S_RSETUP ||
|
||||
state == S_RACCESS;
|
||||
|
||||
assign penable =
|
||||
state == S_WACCESS ||
|
||||
state == S_RACCESS;
|
||||
|
||||
assign pwrite =
|
||||
state == S_WSETUP ||
|
||||
state == S_WACCESS;
|
||||
|
||||
assign paddr = dm_addr;
|
||||
assign pwdata = dm_data;
|
||||
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
|
@ -1,65 +0,0 @@
|
|||
/**********************************************************************
|
||||
* DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE *
|
||||
* Version 3, April 2008 *
|
||||
* *
|
||||
* Copyright (C) 2021 Luke Wren *
|
||||
* *
|
||||
* Everyone is permitted to copy and distribute verbatim or modified *
|
||||
* copies of this license document and accompanying software, and *
|
||||
* changing either is allowed. *
|
||||
* *
|
||||
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION *
|
||||
* *
|
||||
* 0. You just DO WHAT THE FUCK YOU WANT TO. *
|
||||
* 1. We're NOT RESPONSIBLE WHEN IT DOESN'T FUCKING WORK. *
|
||||
* *
|
||||
*********************************************************************/
|
||||
|
||||
// Nothing to see here, just a sync FIFO
|
||||
|
||||
`default_nettype none
|
||||
|
||||
module hazard3_uart_dtm_fifo #(
|
||||
parameter WIDTH = 8,
|
||||
parameter LOG_DEPTH = 2
|
||||
) (
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire [WIDTH-1:0] wdata,
|
||||
input wire wvld,
|
||||
output wire wrdy,
|
||||
|
||||
output wire [WIDTH-1:0] rdata,
|
||||
output wire rvld,
|
||||
input wire rrdy
|
||||
);
|
||||
|
||||
reg [WIDTH-1:0] fifo_mem [0:(1 << LOG_DEPTH) - 1];
|
||||
|
||||
reg [LOG_DEPTH:0] wptr;
|
||||
reg [LOG_DEPTH:0] rptr;
|
||||
|
||||
assign wrdy = (rptr ^ {1'b1, {LOG_DEPTH{1'b0}}}) != wptr;
|
||||
assign rvld = rptr != wptr;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
wptr <= {LOG_DEPTH+1{1'b0}};
|
||||
rptr <= {LOG_DEPTH+1{1'b0}};
|
||||
end else begin
|
||||
if (wvld && wrdy) begin
|
||||
fifo_mem[wptr[LOG_DEPTH-1:0]] <= wdata;
|
||||
wptr <= wptr + 1'b1;
|
||||
end
|
||||
if (rvld && rrdy) begin
|
||||
rptr <= rptr + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign rdata = fifo_mem[rptr[LOG_DEPTH-1:0]];
|
||||
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
Loading…
Reference in New Issue