Root/lm32/logic/sakc/rtl/lac/lac.v

1//------------------------------------------------------------------
2// Logic Analyzer Component
3//------------------------------------------------------------------
4
5module lac #(
6    parameter uart_freq_hz = 100000000,
7    parameter uart_baud = 115200,
8    parameter adr_width = 11,
9    parameter width = 8
10) (
11    input reset,
12    input uart_clk,
13    input uart_rxd,
14    output uart_cts,
15    output uart_txd,
16    input uart_rts,
17    // actual probe input
18    input probe_clk,
19    input [width-1:0] probe,
20    output reg [7:0] select
21);
22
23parameter cmd_nop = 8'h20;
24parameter cmd_arm = 8'h01;
25parameter cmd_disarm = 8'h02;
26
27//------------------------------------------------------------------
28// uart instantiation
29//------------------------------------------------------------------
30assign uart_cts = 1;
31
32reg tx_wr;
33wire tx_busy;
34reg [7:0] tx_data;
35
36wire [7:0] rx_data;
37wire rx_avail;
38reg rx_ack;
39
40uart #(
41    .freq_hz( uart_freq_hz ),
42    .baud( uart_baud )
43) uart0 (
44    .reset( reset ),
45    .clk( uart_clk ),
46    // UART
47    .uart_txd( uart_txd ),
48    .uart_rxd( uart_rxd ),
49    //
50    .rx_data( rx_data ),
51    .rx_avail( rx_avail ),
52    .rx_error( rx_error ),
53    .rx_ack( rx_ack ),
54    .tx_data( tx_data ),
55    .tx_wr( tx_wr ),
56    .tx_busy( tx_busy )
57);
58
59//------------------------------------------------------------------
60// handshake signal between clock domains
61//------------------------------------------------------------------
62reg [7:0] trig_mask;
63reg [7:0] trig_cond;
64reg [7:0] trig_pre;
65
66reg [adr_width-1:0] start_adr; // set in probe_clk domain
67
68reg armed; // set in uart_clk domain
69reg triggered; // set in probe_clk domain
70
71//------------------------------------------------------------------
72// uart state machine
73//------------------------------------------------------------------
74wire rx_req;
75assign rx_req = rx_avail & ~rx_ack;
76
77reg triggered_synced;
78wire [width-1:0] read_dat;
79reg [adr_width-1:0] read_adr;
80wire [adr_width-1:0] read_adr_next;
81
82assign read_adr_next = read_adr + 1;
83
84reg [2:0] state;
85
86parameter s_idle = 0;
87parameter s_read_select= 1;
88parameter s_read_mask = 2;
89parameter s_read_comp = 3;
90parameter s_read_pre = 4;
91parameter s_triggered = 5;
92parameter s_send_byte = 6;
93
94always @(posedge uart_clk)
95begin
96    if (reset) begin
97        state <= s_idle;
98        select <= 0;
99        armed <= 0;
100        tx_wr <= 0;
101    end else begin
102        triggered_synced <= triggered;
103
104        rx_ack <= 0; // default until set otherwise
105        tx_wr <= 0;
106
107        case (state)
108        s_idle: begin
109
110            if (rx_req) begin
111                case (rx_data)
112                cmd_arm: begin
113                    rx_ack <= 1;
114                    state <= s_read_select;
115                end
116                cmd_disarm: begin
117                    rx_ack <= 1;
118                    armed <= 0;
119                end
120                default: begin
121                    rx_ack <= 1;
122                end
123                endcase
124            end
125
126            if (~rx_req && triggered_synced) begin
127                state <= s_triggered;
128            end
129        end
130        s_read_select: begin
131            if (rx_req) begin
132                rx_ack <= 1;
133                select <= rx_data;
134                state <= s_read_mask;
135            end
136        end
137        s_read_mask: begin
138            if (rx_req) begin
139                rx_ack <= 1;
140                trig_mask <= rx_data;
141                state <= s_read_comp;
142            end
143        end
144        s_read_comp: begin
145            if (rx_req) begin
146                rx_ack <= 1;
147                trig_cond <= rx_data;
148                armed <= 1;
149                state <= s_read_pre;
150            end
151        end
152        s_read_pre: begin
153            if (rx_req) begin
154                rx_ack <= 1;
155                trig_pre <= rx_data;
156                armed <= 1;
157                state <= s_idle;
158            end
159        end
160        s_triggered: begin
161            armed <= 0;
162            read_adr <= start_adr;
163            tx_data <= adr_width;
164            tx_wr <= 1;
165            state <= s_send_byte;
166        end
167        s_send_byte: begin
168            tx_wr <= 0;
169
170            if (~tx_busy & ~tx_wr) begin
171                if (read_adr_next == start_adr)
172                    state <= s_idle;
173
174                read_adr <= read_adr_next;
175                tx_data <= read_dat;
176                tx_wr <= 1;
177            end
178        end
179        default:
180            state <= s_idle;
181        endcase
182    end
183end
184
185//------------------------------------------------------------------
186// Sampling clock domain
187//------------------------------------------------------------------
188
189// register probe input for better F_max
190reg [width-1:0] probe_r;
191
192always @(posedge probe_clk)
193    probe_r <= probe;
194
195// Sampling machinery
196reg armed_synced;
197reg armed_synced2;
198reg sampling;
199
200reg [adr_width-1:0] write_adr;
201wire [adr_width-1:0] next_adr;
202assign next_adr = write_adr + 1;
203
204wire cond_match;
205assign cond_match = (probe_r & trig_mask) == (trig_cond & trig_mask) && armed_synced2;
206
207always @(posedge probe_clk)
208begin
209    if (reset) begin
210        armed_synced <= 0;
211        armed_synced2 <= 0;
212        sampling <= 0;
213        triggered <= 0;
214        write_adr <= 0;
215    end else begin
216        armed_synced <= armed;
217        armed_synced2 <= armed_synced;
218    
219        if (armed_synced2 || sampling) begin
220            write_adr <= next_adr;
221        end
222
223        if (~triggered && armed_synced2) begin
224            if (cond_match) begin
225                sampling <= 1;
226                triggered <= 1;
227                start_adr <= write_adr;
228            end
229        end
230        
231        if (sampling && next_adr == start_adr) begin
232            sampling <= 0;
233        end
234
235        if (~sampling && ~armed_synced2 && triggered)
236            triggered <= 0;
237    end
238end
239
240
241//------------------------------------------------------------------
242// dual port memory
243//------------------------------------------------------------------
244wire write_en;
245assign write_en = sampling || cond_match;
246
247dp_ram #(
248    .adr_width( adr_width ),
249    .dat_width( width )
250) ram0 (
251    // read port a
252    .clk_a( uart_clk ),
253    .adr_a( read_adr ),
254    .dat_a( read_dat ),
255    // write port b
256    .clk_b( probe_clk ),
257    .adr_b( write_adr ),
258    .dat_b( probe_r ),
259    .we_b( write_en )
260);
261
262endmodule
263

Archive Download this file

Branches:
master



interactive