Warning. I named signal w_tristate_decoder
for other reason than it being tristate. w_tristate_decoder
is just a name for ths signal., please do not be misled. Signals are NOT tristate in the question.
I am using MAX3000A CPLD, and need to convert signal values.
The circuit below significantly brakes the signal propagation, from 119 MHz to 87 MHz.
wire [2:0] w_tristate_decoder = (r_single_vector[23:20] == 4'b1101) ? 3'd7 :
(r_single_vector[23:20] == 4'b0100) ? 3'd6 :
(r_single_vector[23:20] == 4'b0111) ? 3'd5 :
(r_single_vector[23:20] == 4'b0001) ? 3'd4 :
(r_single_vector[23:20] == 4'b1111) ? 3'd3 :
(r_single_vector[23:20] == 4'b1100) ? 3'd2 :
(r_single_vector[23:20] == 4'b0011) ? 3'd1 :
3'd0; // 0000
I have tried this
wire [2:0] w_tristate_decoder7 = (r_single_vector[23:20] == 4'b1101) ? 3'd7 : 3'd0;
wire [2:0] w_tristate_decoder6 = (r_single_vector[23:20] == 4'b0100) ? 3'd6 : 3'd0;
wire [2:0] w_tristate_decoder5 = (r_single_vector[23:20] == 4'b0111) ? 3'd5 : 3'd0;
wire [2:0] w_tristate_decoder4 = (r_single_vector[23:20] == 4'b0001) ? 3'd4 : 3'd0;
wire [2:0] w_tristate_decoder3 = (r_single_vector[23:20] == 4'b1111) ? 3'd3 : 3'd0;
wire [2:0] w_tristate_decoder2 = (r_single_vector[23:20] == 4'b1100) ? 3'd2 : 3'd0;
wire [2:0] w_tristate_decoder1 = (r_single_vector[23:20] == 4'b0011) ? 3'd1 : 3'd0;
wire [2:0] w_tristate_decoder = w_tristate_decoder7[2:0] | w_tristate_decoder6[2:0] | w_tristate_decoder5[2:0] | w_tristate_decoder4[2:0] |
w_tristate_decoder3[2:0] | w_tristate_decoder2[2:0] | w_tristate_decoder1[2:0];
and got the same result. Most probably former circuit is converted to latter at the synthesis stage.
Is there any way to change the former code to perform better without changing the tested signal values? This does not need to be priority encoder...
Edit: I get 119 MHz if do the following:
wire [2:0] w_tristate_decoder = (r_single_vector[23:20] == 4'b1101) ? 3'd7 :
// (r_single_vector[23:20] == 4'b0100) ? 3'd6 :
// (r_single_vector[23:20] == 4'b0111) ? 3'd5 :
// (r_single_vector[23:20] == 4'b0001) ? 3'd4 :
// (r_single_vector[23:20] == 4'b1111) ? 3'd3 :
// (r_single_vector[23:20] == 4'b1100) ? 3'd2 :
// (r_single_vector[23:20] == 4'b0011) ? 3'd1 :
3'd0; // 0000
Update: here's complete design.
module gr8net_vdp_cpld (
// inputs
input wire FCLK, // data clock
input wire B2, // digital data bit 2
input wire [1:0] B1, // tristate data bit 1 from window comparators
input wire [1:0] B0, // tristate data bit 0 from window comparators
// outputs
(* altera_attribute = "-name FAST_OUTPUT_REGISTER ON" *)
output wire w_wide_register_clock = 1'b0, // clock to latch LVC16374
(* altera_attribute = "-name FAST_OUTPUT_REGISTER ON" *)
output wire w_small_register_clock = 1'b0, // clock to latch 1G79
(* altera_attribute = "-name FAST_OUTPUT_REGISTER ON" *)
output reg [14:0] r_video_data = {15{1'b0}}, // video data bits, 3*5, red in [4:0], green in [9:5], and blue in [14:10]
(* altera_attribute = "-name FAST_OUTPUT_REGISTER ON" *)
output reg r_vs = 1'b1,
(* altera_attribute = "-name FAST_OUTPUT_REGISTER ON" *)
output reg r_hs = 1'b1 // negative polarity
);
// assemble into single vector
reg [24:0] r_single_vector = {25{1'b0}}; // 5*5 bits, we need 5 stages because when we detect sync_data, the vector
// is being shifted left on next clock when we extract data out of it
always@(negedge FCLK) begin
r_single_vector[24:0] <= { r_single_vector[19:0], B2, B1[1:0], B0[1:0] };
end
// states: L=00, M=01, H=11
// detection of M/M state - most significant packet B1/B0 data are 01/01. They can not be 10/10, therefore using XOR
wire w_sync_data = (r_single_vector[18] ^ r_single_vector[17]) & (r_single_vector[16] ^ r_single_vector[15]);
reg r_sync_data = 1'b0;
reg initial_sync_detected = 1'b0; // initially set to 0, will be set to 1 permanently when first sync data set is detected
// to start frame counting
always@(negedge FCLK) begin
if(w_sync_data) initial_sync_detected <= 1'b1; // set sync detected one permanently, enabling state machine
r_sync_data <= w_sync_data; // preserve current sync data to be used on next state in next always circuit
end
wire [2:0] w_tristate_decoder = (r_single_vector[23:20] == 4'b1101) ? 3'd7 :
(r_single_vector[23:20] == 4'b0100) ? 3'd6 :
(r_single_vector[23:20] == 4'b0111) ? 3'd5 :
(r_single_vector[23:20] == 4'b0001) ? 3'd4 :
(r_single_vector[23:20] == 4'b1111) ? 3'd3 :
(r_single_vector[23:20] == 4'b1100) ? 3'd2 :
(r_single_vector[23:20] == 4'b0011) ? 3'd1 :
3'd0; // 0000
reg [1:0] r_packet_state_machine = {2{1'b0}};
reg [15:0] r_color_data = {16{1'b0}}; // color data for output, bit 16 is unused
reg r_sync_data_n_lat = 1'b1;
always@(negedge FCLK) begin
if(initial_sync_detected) begin
// start state machine only when initial sync was detected, state 0 will be entered on the next clock
// edge after sync data is detected, therefore on entry r_single_vector[24:5] will contain full sync vector,
// r_sync_data contains actual sync state flag
case(r_packet_state_machine[1:0])
2'd0: begin
// we have full vector in r_single_vector[24:5] and r_sync_data contains sync data flag
r_sync_data_n_lat <= ~r_sync_data; // preserve sync data flag to be used in next states
if(r_sync_data) begin
// current frame is sync - latch
r_vs <= r_single_vector[19];
r_hs <= r_single_vector[15];
end else begin
// not sync - decode 5 bis into 4 bits into color output register if current frame is not sync
r_color_data[15:0] <= { r_color_data[11:0], r_single_vector[24], w_tristate_decoder[2:0] };
end
// put actual color data into the output, will be clocked into external registers on state 2
r_video_data[14:0] <= r_color_data[14:0]; // MSB is discarded
end
2'd1,
2'd2,
2'd3: begin
if(r_sync_data_n_lat) begin
// not sync - decode 5 bis into 4 bits into color output register if current frame is not sync
r_color_data[15:0] <= { r_color_data[11:0], r_single_vector[24], w_tristate_decoder[2:0] };
end
// if sync data - do nothing on color data
end
endcase
// increment state - only if initial sync was detected
r_packet_state_machine[1:0] <= r_packet_state_machine[1:0] + 1'b1;
end
end
// output register clocking - data will be output at state 0, and clocked into external ouput register
// on state 2 (posedge operation)
assign w_wide_register_clock = r_packet_state_machine[1];
assign w_small_register_clock = r_packet_state_machine[1];
endmodule
Update: after closely considering the circuits using RTL viewer and doing some experiments I redesigned the whole circuit using conveyor technique, and it lowered macrocells used from 64 to 54, and Fmax to be 129 MHz.
wire [2:0] w_tristate_decoder = r_single_vector[23:21] | r_single_vector[22:20];
just as a test? \$\endgroup\$[is greybeard] confused by the signal name [w_tristate_decoder]?
I hope not: I expect it to be a tri-state driver enable signal (or three enables). I don't see priority decoder. I remember priority encoders. \$\endgroup\$