1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2025-01-10 15:20:14 +02:00
nn-usb-fpga/lm32/logic/sakc/rtl/lac/lac.v

263 lines
5.8 KiB
Coq
Raw Normal View History

2010-05-26 05:49:58 +03:00
//------------------------------------------------------------------
// Logic Analyzer Component
//------------------------------------------------------------------
module lac #(
parameter uart_freq_hz = 100000000,
parameter uart_baud = 115200,
parameter adr_width = 11,
parameter width = 8
) (
input reset,
input uart_clk,
input uart_rxd,
output uart_cts,
output uart_txd,
input uart_rts,
// actual probe input
input probe_clk,
input [width-1:0] probe,
output reg [7:0] select
);
parameter cmd_nop = 8'h20;
parameter cmd_arm = 8'h01;
parameter cmd_disarm = 8'h02;
//------------------------------------------------------------------
// uart instantiation
//------------------------------------------------------------------
assign uart_cts = 1;
reg tx_wr;
wire tx_busy;
reg [7:0] tx_data;
wire [7:0] rx_data;
wire rx_avail;
reg rx_ack;
uart #(
.freq_hz( uart_freq_hz ),
.baud( uart_baud )
) uart0 (
.reset( reset ),
.clk( uart_clk ),
// UART
.uart_txd( uart_txd ),
.uart_rxd( uart_rxd ),
//
.rx_data( rx_data ),
.rx_avail( rx_avail ),
.rx_error( rx_error ),
.rx_ack( rx_ack ),
.tx_data( tx_data ),
.tx_wr( tx_wr ),
.tx_busy( tx_busy )
);
//------------------------------------------------------------------
// handshake signal between clock domains
//------------------------------------------------------------------
reg [7:0] trig_mask;
reg [7:0] trig_cond;
reg [7:0] trig_pre;
reg [adr_width-1:0] start_adr; // set in probe_clk domain
reg armed; // set in uart_clk domain
reg triggered; // set in probe_clk domain
//------------------------------------------------------------------
// uart state machine
//------------------------------------------------------------------
wire rx_req;
assign rx_req = rx_avail & ~rx_ack;
reg triggered_synced;
wire [width-1:0] read_dat;
reg [adr_width-1:0] read_adr;
wire [adr_width-1:0] read_adr_next;
assign read_adr_next = read_adr + 1;
reg [2:0] state;
parameter s_idle = 0;
parameter s_read_select= 1;
parameter s_read_mask = 2;
parameter s_read_comp = 3;
parameter s_read_pre = 4;
parameter s_triggered = 5;
parameter s_send_byte = 6;
always @(posedge uart_clk)
begin
if (reset) begin
state <= s_idle;
select <= 0;
armed <= 0;
tx_wr <= 0;
end else begin
triggered_synced <= triggered;
rx_ack <= 0; // default until set otherwise
tx_wr <= 0;
case (state)
s_idle: begin
if (rx_req) begin
case (rx_data)
cmd_arm: begin
rx_ack <= 1;
state <= s_read_select;
end
cmd_disarm: begin
rx_ack <= 1;
armed <= 0;
end
default: begin
rx_ack <= 1;
end
endcase
end
if (~rx_req && triggered_synced) begin
state <= s_triggered;
end
end
s_read_select: begin
if (rx_req) begin
rx_ack <= 1;
select <= rx_data;
state <= s_read_mask;
end
end
s_read_mask: begin
if (rx_req) begin
rx_ack <= 1;
trig_mask <= rx_data;
state <= s_read_comp;
end
end
s_read_comp: begin
if (rx_req) begin
rx_ack <= 1;
trig_cond <= rx_data;
armed <= 1;
state <= s_read_pre;
end
end
s_read_pre: begin
if (rx_req) begin
rx_ack <= 1;
trig_pre <= rx_data;
armed <= 1;
state <= s_idle;
end
end
s_triggered: begin
armed <= 0;
read_adr <= start_adr;
tx_data <= adr_width;
tx_wr <= 1;
state <= s_send_byte;
end
s_send_byte: begin
tx_wr <= 0;
if (~tx_busy & ~tx_wr) begin
if (read_adr_next == start_adr)
state <= s_idle;
read_adr <= read_adr_next;
tx_data <= read_dat;
tx_wr <= 1;
end
end
default:
state <= s_idle;
endcase
end
end
//------------------------------------------------------------------
// Sampling clock domain
//------------------------------------------------------------------
// register probe input for better F_max
reg [width-1:0] probe_r;
always @(posedge probe_clk)
probe_r <= probe;
// Sampling machinery
reg armed_synced;
reg armed_synced2;
reg sampling;
reg [adr_width-1:0] write_adr;
wire [adr_width-1:0] next_adr;
assign next_adr = write_adr + 1;
wire cond_match;
assign cond_match = (probe_r & trig_mask) == (trig_cond & trig_mask) && armed_synced2;
always @(posedge probe_clk)
begin
if (reset) begin
armed_synced <= 0;
armed_synced2 <= 0;
sampling <= 0;
triggered <= 0;
write_adr <= 0;
end else begin
armed_synced <= armed;
armed_synced2 <= armed_synced;
if (armed_synced2 || sampling) begin
write_adr <= next_adr;
end
if (~triggered && armed_synced2) begin
if (cond_match) begin
sampling <= 1;
triggered <= 1;
start_adr <= write_adr;
end
end
if (sampling && next_adr == start_adr) begin
sampling <= 0;
end
if (~sampling && ~armed_synced2 && triggered)
triggered <= 0;
end
end
//------------------------------------------------------------------
// dual port memory
//------------------------------------------------------------------
wire write_en;
assign write_en = sampling || cond_match;
dp_ram #(
.adr_width( adr_width ),
.dat_width( width )
) ram0 (
// read port a
.clk_a( uart_clk ),
.adr_a( read_adr ),
.dat_a( read_dat ),
// write port b
.clk_b( probe_clk ),
.adr_b( write_adr ),
.dat_b( probe_r ),
.we_b( write_en )
);
endmodule