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]),