| 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 |