rtl: fully working wb_pio_top file This adds a fully-working wb_pio_top file that should be functional in real hardware. Signed-off-by: Sean Cross <sean@xobs.io>
diff --git a/verilog/rtl/wb_pio_top.v b/verilog/rtl/wb_pio_top.v index fc10948..aa464cc 100644 --- a/verilog/rtl/wb_pio_top.v +++ b/verilog/rtl/wb_pio_top.v
@@ -79,32 +79,25 @@ wire clk; wire rst; - wire [`MPRJ_IO_PADS-1:0] io_in; - wire [`MPRJ_IO_PADS-1:0] io_out; - wire [`MPRJ_IO_PADS-1:0] io_oeb; - - wire [31:0] wdata; - wire [BITS-1:0] count; - wire valid; wire [3:0] wstrb; wire [31:0] la_write; - // WB MI A - assign valid = wbs_cyc_i && wbs_stb_i && wbs_adr_i[31:16] == 16'h761c; - assign wstrb = wbs_sel_i & {4{wbs_we_i}}; - assign wdata = wbs_dat_i; + reg manual_reset = 0; - // IO - assign io_out = count; + // WB MI A + assign valid = wbs_cyc_i && wbs_stb_i && wbs_adr_i[31:16] == 16'h3000; + assign wstrb = wbs_sel_i & {4{wbs_we_i}}; + + assign wbs_dat_o = pio_dout; // PIO registers and wires - reg [31:0] din; // Data sent to PIO + wire [31:0] pio_din; // Data sent to PIO reg [4:0] index; // Instruction index reg [1:0] mindex; // Machine index - reg [31:0] dout; // Output from PIO - wire [3:0] action; // Action to be done by PIO + wire [31:0] pio_dout; // Output from PIO + reg [3:0] action = 4'b0000; // Action to be done by PIO wire irq0, irq1; // IRQ flags from PIO wire [3:0] tx_full; // Set when TX fifo is full wire [3:0] rx_empty; // Set when RX fifo is empty @@ -113,50 +106,68 @@ reg ack; assign wbs_ack_o = ack; - assign wbs_dat_o = dout; always @(posedge wb_clk_i) begin - if (wb_rst_i) begin - ack <= 1'b0; + if (wb_rst_i | manual_reset) begin + index <= 0; + manual_reset <= 0; end else begin ack <= 1'b0; - if (valid && !ack) begin - ack <= 1'b1; - if (wbs_we_i) begin - action[3:0] <= wbs_adr_i[5:2]; - if (wbs_we_i) begin - if (wstrb[0]) din[7:0] <= wbs_dat_i[7:0]; - if (wstrb[1]) din[15:8] <= wbs_dat_i[15:8]; - if (wstrb[2]) din[23:16] <= wbs_dat_i[23:16]; - if (wstrb[3]) din[31:24] <= wbs_dat_i[31:24]; - end else begin - if (wstrb[0]) wbs_dat_o[7:0] <= dout[7:0]; - if (wstrb[1]) wbs_dat_o[15:8] <= dout[15:8]; - if (wstrb[2]) wbs_dat_o[23:16] <= dout[23:16]; - if (wstrb[3]) wbs_dat_o[31:24] <= dout[31:24]; - end + if (valid) begin + if (!ack) begin + ack <= 1'b1; + if ((action == 4'b0000) && (pio_din[31] == 1'b1)) begin + manual_reset <= 1; + end end else begin - // When there is no action, set the action to `NONE` - action[3:0] <= 4'b0000; + if (action == 4'b0001) begin + // Increment the program counter when injecting values into + // the PIO memory space. + index <= index + 1 + pio_din[19:16]; + end end end end end + // Tie unused pins down, so as to avoid uninitialized values. + assign io_out[4:0] = 0; + assign io_out[37] = 0; + assign io_oeb[4:0] = 0; + assign io_oeb[37] = 0; + + // Wire up the PIO data input lines. Ideally we should consult + // `wstrb` here to figure out which values to copy. + assign pio_din[7:0] = wbs_dat_i[7:0]; + assign pio_din[15:8] = wbs_dat_i[15:8]; + assign pio_din[23:16] = wbs_dat_i[23:16]; + assign pio_din[31:24] = wbs_dat_i[31:24]; + + always @(*) begin + // Default action to `NONE` + action <= 0; + mindex <= 0; + // When there's a valid command, set the action. + if (valid) begin + action <= wbs_adr_i[5:2]; + mindex <= wbs_adr_i[7:6]; + end + end + // PIO instance 1 pio pio_1 ( .clk(wb_clk_i), - .reset(wb_rst_i), + .reset(wb_rst_i | manual_reset), .mindex(mindex), - .din(din), + .din(pio_din), .index(index), .action(action), - .dout(dout), + .dout(pio_dout), - .gpio_in(io_in), - .gpio_out(io_out), - .gpio_dir(io_oeb), + .gpio_in(io_in[36:5]), + .gpio_out(io_out[36:5]), + .gpio_dir(io_oeb[36:5]), .irq0(irq[0]), .irq1(irq[1]),