blob: ecacb476c33addd1ce5b84e6f2b65eb79788efe9 [file] [log] [blame]
module wishbone_configuratorinator #(
parameter BASE_ADDR = 32'h3000_0000
) (
// Global signals
input wb_clk_i,
input wb_rst_i,
// Wishbone signals
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
// Write mask
input [3:0] wbs_sel_i,
input [31:0] wbs_data_i,
input [31:0] wbs_addr_i,
output reg wbs_ack_o, // Its bad form but its also 1 in the morning
output reg [31:0] wbs_data_o,
// Config output
output cen,
output [3:0] set_out,
output [3:0] shift_out
);
// Bus decoding
wire selected;
assign selected = (BASE_ADDR[31:4] == wbs_addr_i[31:4]) ? 1'b1 : 1'b0;
wire transaction_initiated;
assign transaction_initiated = wbs_stb_i & wbs_cyc_i & selected;
// State registers
reg read_transaction_in_progress;
reg write_transaction_in_progress;
reg output_initiated;
reg [2:0] bits_index;
reg [3:0] charged; // Heckin write masks
// Bus exposed registers:
// Management for the block:
// {~, free_run}
reg free_run;
wire [31:0] house_keeping;
assign house_keeping = {31'b0, free_run};
// Comprised of 4 8 bit segments
reg [7:0] bits_d, bits_c, bits_b, bits_a;
wire [31:0] bitstream;
assign bitstream = {bits_d, bits_c, bits_b, bits_a};
// 4 Set output counters, each solves at 255
reg [7:0] counter_d, counter_c, counter_b, counter_a;
wire [31:0] counters;
assign counters = {counter_d, counter_c, counter_b, counter_a};
// Bus Logic
always @(posedge wb_clk_i) begin
// Transaction initiation and read transaction management
if (transaction_initiated == 1 && !(read_transaction_in_progress || wbs_ack_o)) begin
read_transaction_in_progress <= 1;
if (wbs_addr_i[3:0] == 0) begin
wbs_data_o <= house_keeping;
end else if (wbs_addr_i[3:0] == 4) begin
wbs_data_o <= bitstream;
end else if (wbs_addr_i[3:0] == 8) begin
wbs_data_o <= counters;
end else begin
wbs_data_o <= 0;
end
if (wbs_we_i == 1 && read_transaction_in_progress == 0) begin
write_transaction_in_progress <= 1;
end
end
if (read_transaction_in_progress == 1 && write_transaction_in_progress == 0) begin
wbs_ack_o <= 1;
read_transaction_in_progress <= 0;
end
// Write management
if (write_transaction_in_progress == 1) begin
if (wbs_addr_i[3:0] == 0) begin
if (wbs_sel_i[0] == 1) free_run <= wbs_data_i[0];
write_transaction_in_progress <= 0;
end else if (wbs_addr_i[3:0] == 4) begin
write_transaction_in_progress <= 0;
end else if (wbs_addr_i[3:0] == 8) begin
if (wbs_sel_i[0] == 1) bits_a <= wbs_data_i[7:0];
if (wbs_sel_i[1] == 1) bits_b <= wbs_data_i[15:8];
if (wbs_sel_i[2] == 1) bits_c <= wbs_data_i[23:16];
if (wbs_sel_i[3] == 1) bits_d <= wbs_data_i[31:24];
bits_index <= 0;
if (output_initiated == 0) begin
charged <= charged | wbs_sel_i;
end else begin
charged <= 0;
end
if ((charged | wbs_sel_i) != 4'b1111) write_transaction_in_progress <= 0;
end else begin
write_transaction_in_progress <= 0;
end
end
if (charged == 4'b1111) begin
charged <= 0;
output_initiated <= 1;
end
if (output_initiated && bits_index != 3'b111) begin
bits_index <= bits_index + 1;
end else if (output_initiated) begin
bits_index <= 0;
output_initiated <= 0;
write_transaction_in_progress <= 0;
end
if (wbs_ack_o == 1) begin
wbs_ack_o <= 0;
wbs_data_o <= 0; // Maybe bad idea?
end
if (wb_rst_i == 1) begin
wbs_data_o <= 0;
bits_index <= 0;
output_initiated <= 0;
free_run <= 0;
read_transaction_in_progress <= 0;
write_transaction_in_progress <= 0;
charged <= 0;
wbs_ack_o <= 0;
end
end
// Config output management
assign cen = free_run | output_initiated;
assign set_out[0] = (counter_a == 8'h00 && output_initiated) ? 1'b1 : 1'b0;
assign set_out[1] = (counter_b == 8'h00 && output_initiated) ? 1'b1 : 1'b0;
assign set_out[2] = (counter_c == 8'h00 && output_initiated) ? 1'b1 : 1'b0;
assign set_out[3] = (counter_d == 8'h00 && output_initiated) ? 1'b1 : 1'b0;
assign shift_out[0] = (output_initiated) ? bits_a[bits_index] : 1'b0;
assign shift_out[1] = (output_initiated) ? bits_b[bits_index] : 1'b0;
assign shift_out[2] = (output_initiated) ? bits_c[bits_index] : 1'b0;
assign shift_out[3] = (output_initiated) ? bits_d[bits_index] : 1'b0;
always @(posedge wb_clk_i) begin
if (wb_rst_i == 1) begin
counter_a <= 8'hFF;
counter_b <= 8'hFF;
counter_c <= 8'hFF;
counter_d <= 8'hFF;
end
else if (output_initiated) begin
if (counter_a != 8'hFF) counter_a <= counter_a - 1;
if (counter_b != 8'hFF) counter_b <= counter_b - 1;
if (counter_c != 8'hFF) counter_c <= counter_c - 1;
if (counter_d != 8'hFF) counter_d <= counter_d - 1;
end
else if (write_transaction_in_progress == 1) begin
if (wbs_addr_i[3:0] == 4) begin
if (wbs_sel_i[0] == 1) counter_a <= wbs_data_i[7:0];
if (wbs_sel_i[1] == 1) counter_b <= wbs_data_i[15:8];
if (wbs_sel_i[2] == 1) counter_c <= wbs_data_i[23:16];
if (wbs_sel_i[3] == 1) counter_d <= wbs_data_i[31:24];
end
end
end
endmodule