113 lines
2.7 KiB
Verilog
113 lines
2.7 KiB
Verilog
`timescale 1ns/1ps
|
|
|
|
module wb_gpio (
|
|
input wire i_wb_clk,
|
|
input wire i_wb_rst, // optional; tie low if unused
|
|
input wire [31:0] i_wb_adr, // optional; can ignore for single-reg
|
|
input wire [31:0] i_wb_dat,
|
|
input wire [3:0] i_wb_sel,
|
|
input wire i_wb_we,
|
|
input wire i_wb_stb,
|
|
|
|
output reg [31:0] o_wb_rdt,
|
|
output reg o_wb_ack,
|
|
output reg [31:0] o_gpio
|
|
);
|
|
|
|
initial o_gpio <= 32'h00000000;
|
|
initial o_wb_rdt <= 32'h00000000;
|
|
|
|
// One-cycle ACK pulse per request (works even if stb stays high)
|
|
always @(posedge i_wb_clk) begin
|
|
if (i_wb_rst) begin
|
|
o_wb_ack <= 1'b0;
|
|
end else begin
|
|
o_wb_ack <= i_wb_stb & ~o_wb_ack; // pulse while stb asserted
|
|
end
|
|
end
|
|
|
|
// Read data (combinational or registered; registered here)
|
|
always @(posedge i_wb_clk) begin
|
|
if (i_wb_rst) begin
|
|
o_wb_rdt <= 32'h0;
|
|
end else if (i_wb_stb && !i_wb_we) begin
|
|
o_wb_rdt <= o_gpio;
|
|
end
|
|
end
|
|
|
|
// Write latch (update on the acknowledged cycle)
|
|
always @(posedge i_wb_clk) begin
|
|
if (i_wb_rst) begin
|
|
o_gpio <= 32'h0;
|
|
end else if (i_wb_stb && i_wb_we && (i_wb_stb & ~o_wb_ack)) begin
|
|
// Apply byte enables (so sb works if the master uses sel)
|
|
if (i_wb_sel[0]) o_gpio[7:0] <= i_wb_dat[7:0];
|
|
if (i_wb_sel[1]) o_gpio[15:8] <= i_wb_dat[15:8];
|
|
if (i_wb_sel[2]) o_gpio[23:16] <= i_wb_dat[23:16];
|
|
if (i_wb_sel[3]) o_gpio[31:24] <= i_wb_dat[31:24];
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
|
|
module tb_serving();
|
|
// Clock and reset generation
|
|
reg clk;
|
|
reg resetn;
|
|
initial clk <= 1'b0;
|
|
always #4.17 clk <= !clk;
|
|
initial begin
|
|
resetn <= 1'b1;
|
|
#(4.17*40) resetn <= 1'b0;
|
|
#(4.17*40) resetn <= 1'b1;
|
|
end;
|
|
|
|
// Default run
|
|
initial begin
|
|
$dumpfile("out.vcd");
|
|
$dumpvars;
|
|
#5_000
|
|
$finish;
|
|
end;
|
|
|
|
wire [31:0] wb_adr;
|
|
wire [31:0] wb_dat;
|
|
wire [3:0] wb_sel;
|
|
wire wb_we;
|
|
wire wb_stb;
|
|
wire [31:0] wb_rdt;
|
|
wire wb_ack;
|
|
|
|
wire [31:0] GPIO;
|
|
|
|
serving #(
|
|
.memfile("../sw/blinky/blinky.hex"),
|
|
.memsize(8192),
|
|
.sim(1'b0),
|
|
.RESET_STRATEGY("MINI"),
|
|
.WITH_CSR(1)
|
|
) serv (
|
|
.i_clk(clk),
|
|
.i_rst(!resetn),
|
|
.i_timer_irq(1'b0),
|
|
.i_wb_rdt(wb_rdt),
|
|
.i_wb_ack(wb_ack),
|
|
.o_wb_adr(wb_adr),
|
|
.o_wb_dat(wb_dat),
|
|
.o_wb_sel(wb_sel),
|
|
.o_wb_we(wb_we),
|
|
.o_wb_stb(wb_stb)
|
|
);
|
|
|
|
wb_gpio gpio (
|
|
.i_wb_clk(clk),
|
|
.i_wb_dat(wb_dat),
|
|
.i_wb_we(wb_we),
|
|
.i_wb_stb(wb_stb),
|
|
.i_wb_sel(wb_sel),
|
|
.o_wb_rdt(wb_rdt),
|
|
.o_wb_ack(wb_ack),
|
|
.o_gpio(GPIO)
|
|
);
|
|
|
|
endmodule |