Succesfully generated hard macro of user project and wrapper cell
diff --git a/verilog/rtl/gpioModule/gpioCtrl.v b/verilog/rtl/gpioModule/gpioCtrl.v new file mode 100644 index 0000000..df5d8e1 --- /dev/null +++ b/verilog/rtl/gpioModule/gpioCtrl.v
@@ -0,0 +1,327 @@ +// gpio control module +// address space: +// Ctrl Reg 0b00 +// GPIO Input 0b01 +// GPIO Output 0b10 +// GPIO OutEnable 0b11 + +module gpioCtrl ( + // system + input wire CLK, + input wire RSTb, + // control interface + input wire CTRL_WE, + input wire [3:0] CTRL_ADDR, + input wire [31:0] CTRL_DATA_IN, + output wire [31:0] CTRL_DATA_OUT, + // caravel gpio signaling + input wire [37:0] GPIO_IN, + output wire [37:0] GPIO_OUT, + output wire [37:0] GPIO_OEb, + // RAM interface + output wire RAM_CSb, + output wire RAM_WEb, + output wire [7:0] RAM_ADDR, + output wire [31:0] RAM_DATA_IN, + input wire [31:0] RAM_DATA_OUT +); + // constants input fsm + parameter sFSM_IN_STOP = 2'b00; + parameter sFSM_IN_SHIFT = 2'b01; + parameter sFSM_IN_STORE = 2'b10; + // constants output fsm + parameter sFSM_OUT_STOP = 2'b00; + parameter sFSM_OUT_LOAD = 2'b01; + parameter sFSM_OUT_SHIFT = 2'b10; + parameter sFSM_OUT_LOAD_NEXT = 2'b11; + + // internal output signals + reg [31:0] CTRL_DATA_OUT_i; + reg RAM_WEb_i; + reg [31:0] RAM_ADDR_i; + reg [31:0] RAM_DATA_IN_i; + // control register + reg [31:0] CTRL_REG_Q; + reg [31:0] CTRL_REG_D; + // control register aliases + wire aSHIFT_IN_EN; + wire [4:0] aINPUT_SEL; + wire aSHIFT_OUT_EN; + wire [4:0] aOUTPUT_SEL; + wire aOUTPUT_LOOP; + wire [9:0] aOUTPUT_LEN; + wire aOUTPUT_LIMIT; + // data registers + reg [31:0] DATA_IN_Q; + reg [31:0] DATA_IN_D; + reg [31:0] DATA_OUT_Q; + reg [31:0] DATA_OUT_D; + reg [31:0] DATA_OE_Q; + reg [31:0] DATA_OE_D; + // Shift registers + reg [31:0] SHIFT_IN_Q; + reg [31:0] SHIFT_IN_D; + reg [31:0] SHIFT_OUT_Q; + reg [31:0] SHIFT_OUT_D; + // fsm registers + reg [1:0] FSM_IN_Q; + reg [1:0] FSM_IN_D; + reg [1:0] FSM_OUT_Q; + reg [1:0] FSM_OUT_D; + // fsm control signals + reg SET_SHIFT_DATA; + reg SET_OUT_DATA; + reg RST_SHIFT_IN_EN; + reg RST_SHIFT_OUT_EN; + reg OVERRIDE_RAM_ADDR; + reg RAM_CSb_IN; + reg RAM_CSb_OUT; + // bit counters + reg [9:0] BIT_IN_COUNT_Q; + reg [9:0] BIT_IN_COUNT_D; + reg [9:0] BIT_OUT_COUNT_Q; + reg [9:0] BIT_OUT_COUNT_D; + + // module output + assign CTRL_DATA_OUT = CTRL_DATA_OUT_i; + assign GPIO_OUT[31:0] = DATA_OUT_Q; + assign GPIO_OUT[37:32] = 6'b000000; + assign GPIO_OEb[31:0] = ~(DATA_OE_Q); + assign GPIO_OEb[37:32] = 6'b111111; + assign RAM_WEb = RAM_WEb_i; + assign RAM_ADDR = RAM_ADDR_i; + assign RAM_DATA_IN = RAM_DATA_IN_i; + + // control register read aliases (...is there a way to define real aliases?) + assign aSHIFT_OUT_EN = CTRL_REG_Q[0]; + assign aOUTPUT_SEL = CTRL_REG_Q[5:1]; + assign aSHIFT_IN_EN = CTRL_REG_Q[6]; + assign aINPUT_SEL = CTRL_REG_Q[11:7]; + assign aOUTPUT_LOOP = CTRL_REG_Q[12]; + assign aOUTPUT_LEN = CTRL_REG_Q[22:13]; + assign aOUTPUT_LIMIT = CTRL_REG_Q[23]; + + // control interface read access + always @(*) begin : interface_read_access + case (CTRL_ADDR[3:2]) + // control register + 2'b00: CTRL_DATA_OUT_i <= CTRL_REG_Q; + // input data + 2'b01: CTRL_DATA_OUT_i <= DATA_IN_Q; + // output data + 2'b10: CTRL_DATA_OUT_i <= DATA_OUT_Q; + // output enable + 2'b11: CTRL_DATA_OUT_i <= DATA_OE_Q; + // something's wrong + default: CTRL_DATA_OUT_i <= 8'b0000_0000; + endcase + end + + // control interface write access + always @(*) begin : interface_write_access + // default + CTRL_REG_D <= CTRL_REG_Q; + SET_OUT_DATA <= 1'b0; + DATA_OE_D <= DATA_OE_Q; + // actual write request + if (CTRL_WE == 1'b1) begin + // address selection + case (CTRL_ADDR[3:2]) + // control register + 2'b00: begin + CTRL_REG_D <= CTRL_DATA_IN; + end + // output data + 2'b10: SET_OUT_DATA <= 1'b1; + // output enable + 2'b11: DATA_OE_D <= CTRL_DATA_IN; + endcase + end + // auto set/reset shift enables + if (RST_SHIFT_IN_EN == 1'b1) CTRL_REG_D[6] <= 1'b0; + if (RST_SHIFT_OUT_EN == 1'b1) CTRL_REG_D[0] <= 1'b0; + //if (SET_SHIFT_OUT_EN == 1'b1) CTRL_REG_D[0] <= 1'b1; + end + + // fsm data in + always @(*) begin : fsm_data_in + // default + FSM_IN_D <= FSM_IN_Q; + BIT_IN_COUNT_D <= BIT_IN_COUNT_Q; + RST_SHIFT_IN_EN <= 1'b0; + //RAM_CSb_IN <= 1'b1; + RAM_WEb_i <= 1'b1; + // fsm logic + case (FSM_IN_Q) + // input sampling inactive + sFSM_IN_STOP: begin + BIT_IN_COUNT_D <= 10'b00_0000_0000; + if (aSHIFT_IN_EN == 1'b1) begin + RST_SHIFT_IN_EN <= 1'b1; + FSM_IN_D <= sFSM_IN_SHIFT; + end + end + // input sampling active + sFSM_IN_SHIFT: begin + BIT_IN_COUNT_D <= BIT_IN_COUNT_Q + 1; + if (BIT_IN_COUNT_Q[4:0] == 5'b1_1110) FSM_IN_D <= sFSM_IN_STORE; + end + // store 32bit input data to ram + sFSM_IN_STORE: begin + BIT_IN_COUNT_D <= BIT_IN_COUNT_Q + 1; + //RAM_CSb_IN <= 1'b0; + RAM_WEb_i <= 1'b0; + if (BIT_IN_COUNT_Q[9:5] == 5'b1_1111) FSM_IN_D <= sFSM_IN_STOP; + else FSM_IN_D <= sFSM_IN_SHIFT; + end + // error + default: FSM_IN_D <= sFSM_IN_STOP; + endcase + end + + // fsm data out + always @(*) begin : fsm_data_out + // default + FSM_OUT_D <= FSM_OUT_Q; + BIT_OUT_COUNT_D <= BIT_OUT_COUNT_Q; + RST_SHIFT_OUT_EN <= 1'b0; + SET_SHIFT_DATA <= 1'b0; + //RAM_CSb_OUT <= 1'b1; + OVERRIDE_RAM_ADDR <= 1'b0; + // fsm logic + case (FSM_OUT_Q) + // output generation inactive + sFSM_OUT_STOP: begin + BIT_OUT_COUNT_D <= 10'b11_1111_1111; + if (aSHIFT_OUT_EN == 1'b1) begin + RST_SHIFT_OUT_EN <= 1'b1; + //RAM_CSb_OUT <= 1'b0; + FSM_OUT_D <= sFSM_OUT_LOAD; + end + end + // load first 32bit output data from ram + sFSM_OUT_LOAD: begin + BIT_OUT_COUNT_D <= 10'b00_0000_0000; + SET_SHIFT_DATA <= 1'b1; + FSM_OUT_D <= sFSM_OUT_SHIFT; + end + // output generation active + sFSM_OUT_SHIFT: begin + BIT_OUT_COUNT_D <= BIT_OUT_COUNT_Q + 1; + // single shot: configured length reached + if ( aOUTPUT_LOOP == 1'b0 + && (aOUTPUT_LIMIT == 1'b1 && BIT_OUT_COUNT_Q == aOUTPUT_LEN-1)) + FSM_OUT_D <= sFSM_OUT_STOP; + // loop mode: configured length reached + else if ( aOUTPUT_LOOP == 1'b1 + && (aOUTPUT_LIMIT == 1'b1 && BIT_OUT_COUNT_Q == (aOUTPUT_LEN-2))) begin + OVERRIDE_RAM_ADDR <= 1'b1; + //RAM_CSb_OUT <= 1'b0; + FSM_OUT_D <= sFSM_OUT_LOAD; + // need new 32-bit data + end else if (BIT_OUT_COUNT_Q[4:0] == 5'b1_1110) begin + //RAM_CSb_OUT <= 1'b0; + FSM_OUT_D <= sFSM_OUT_LOAD_NEXT; + end + end + // load next 32bit output data from ram + sFSM_OUT_LOAD_NEXT: begin + // single shot: max or configured length reached + if ( aOUTPUT_LOOP == 1'b0 + && ( BIT_OUT_COUNT_Q[9:5] == 5'b1_1111 + || (aOUTPUT_LIMIT == 1'b1 && BIT_OUT_COUNT_Q == aOUTPUT_LEN-1))) + FSM_OUT_D <= sFSM_OUT_STOP; + // loop mode: max or configured length reached + else if ( aOUTPUT_LOOP == 1'b1 + && ( BIT_OUT_COUNT_Q[9:5] == 5'b1_1111 + || (aOUTPUT_LIMIT == 1'b1 && BIT_OUT_COUNT_Q == aOUTPUT_LEN-2))) begin + OVERRIDE_RAM_ADDR <= 1'b1; + //RAM_CSb_OUT <= 1'b0; + FSM_OUT_D <= sFSM_OUT_LOAD; + // continue generating data bits + end else begin + SET_SHIFT_DATA <= 1'b1; + BIT_OUT_COUNT_D <= BIT_OUT_COUNT_Q + 1; + FSM_OUT_D <= sFSM_OUT_SHIFT; + end + end + // error + default: FSM_OUT_D <= sFSM_OUT_STOP; + endcase + end + + // input data path + always @(*) begin : input_data_path + reg vDataInMux; + // input registers + DATA_IN_D <= GPIO_IN[31:0]; + // input multiplexer + vDataInMux = DATA_IN_Q[aINPUT_SEL]; + // input shift register + SHIFT_IN_D <= {SHIFT_IN_Q[30:0], vDataInMux}; + // ram data input + RAM_DATA_IN_i <= SHIFT_IN_Q; + end + + // output data path + always @(*) begin : output_data_path + // default: output shift register + SHIFT_OUT_D <= {SHIFT_OUT_Q[30:0], 1'b0}; + // set shift data + if(SET_SHIFT_DATA == 1'b1) SHIFT_OUT_D <= RAM_DATA_OUT; + // default: hold output data + DATA_OUT_D <= DATA_OUT_Q; + // bus write access + if (SET_OUT_DATA == 1'b1) DATA_OUT_D <= CTRL_DATA_IN; + // shift register input + if (FSM_OUT_Q != sFSM_OUT_STOP) DATA_OUT_D[aOUTPUT_SEL] <= SHIFT_OUT_Q[31]; + end + + // logic for ram access + always @(*) begin + // default + RAM_CSb_IN <= 1'b1; + RAM_CSb_OUT <= 1'b1; + RAM_ADDR_i <= 32'h00_00_00_00; + if (OVERRIDE_RAM_ADDR == 1'b1) begin + RAM_CSb_OUT <= 1'b0; + RAM_ADDR_i <= 32'h00_00_00_00; + end else if (FSM_IN_Q != sFSM_IN_STOP) begin + RAM_CSb_IN <= 1'b0; + RAM_ADDR_i <= {BIT_IN_COUNT_Q[9:5], 2'b00}; + end else if (FSM_OUT_Q != sFSM_OUT_STOP) begin + RAM_CSb_OUT <= 1'b0; + RAM_ADDR_i <= {BIT_OUT_COUNT_Q[9:5] + 1, 2'b00}; + end + end + //assign RAM_ADDR = (FSM_IN_Q != sFSM_IN_STOP) ? {BIT_IN_COUNT_Q[9:5], 2'b00} : {BIT_OUT_COUNT_Q[9:5] + 1, 2'b00}; + assign RAM_CSb = RAM_CSb_IN & RAM_CSb_OUT; + + // flip flops + always @(posedge CLK, negedge RSTb) begin : flip_flops + if(RSTb == 1'b0) begin + CTRL_REG_Q <= 32'h00_00_00_00; + DATA_IN_Q <= 32'h00_00_00_00; + DATA_OUT_Q <= 32'h00_00_00_00; + DATA_OE_Q <= 32'h00_00_00_00; + SHIFT_IN_Q <= 32'h00_00_00_00; + SHIFT_OUT_Q <= 32'h00_00_00_00; + FSM_IN_Q <= sFSM_IN_STOP; + FSM_OUT_Q <= sFSM_OUT_STOP; + BIT_IN_COUNT_Q <= 10'b00_0000_0000; + BIT_OUT_COUNT_Q <= 10'b00_0000_0000; + end else begin + CTRL_REG_Q <= CTRL_REG_D; + DATA_IN_Q <= DATA_IN_D; + DATA_OUT_Q <= DATA_OUT_D; + DATA_OE_Q <= DATA_OE_D; + SHIFT_IN_Q <= SHIFT_IN_D; + SHIFT_OUT_Q <= SHIFT_OUT_D; + FSM_IN_Q <= FSM_IN_D; + FSM_OUT_Q <= FSM_OUT_D; + BIT_IN_COUNT_Q <= BIT_IN_COUNT_D; + BIT_OUT_COUNT_Q <= BIT_OUT_COUNT_D; + end + end + +endmodule \ No newline at end of file
diff --git a/verilog/rtl/ramInterface/openRam.v b/verilog/rtl/ramInterface/openRam.v new file mode 100644 index 0000000..8acdb3f --- /dev/null +++ b/verilog/rtl/ramInterface/openRam.v
@@ -0,0 +1,44 @@ +// open RAM implemented as flip flops (fall back solution) + +module openRam ( + input wire CLK, + input wire CSb, + input wire WEb, + input wire [4:0] ADDR, + input wire [7:0] DATA_IN, + output wire [7:0] DATA_OUT +); + + // control signal flip flops + reg CSb_Q; + reg WEb_Q; + reg [4:0] ADDR_Q; + reg [7:0] DATA_IN_Q; + // "RAM" flip flops (32 x 8bit = 256bit) + reg [7:0] RAM_Q [31:0]; + reg [7:0] RAM_OUT_Q; + + // module output + assign DATA_OUT = RAM_OUT_Q; + + // latch control signals first + always @(posedge(CLK)) begin + CSb_Q <= CSb; + WEb_Q <= WEb; + ADDR_Q <= ADDR; + DATA_IN_Q <= DATA_IN; + end + + // actual ram cell access + always @(negedge(CLK)) begin + // new ram access + if (CSb_Q == 1'b0) begin + // valid write access + if (WEb_Q == 1'b0) begin + RAM_Q[ADDR_Q] <= DATA_IN_Q; + RAM_OUT_Q <= DATA_IN_Q; + // valid read access + end else RAM_OUT_Q <= RAM_Q[ADDR_Q]; + end + end +endmodule \ No newline at end of file
diff --git a/verilog/rtl/ramInterface/ramArbiter.v b/verilog/rtl/ramInterface/ramArbiter.v new file mode 100644 index 0000000..37e1bc2 --- /dev/null +++ b/verilog/rtl/ramInterface/ramArbiter.v
@@ -0,0 +1,110 @@ +// RAM Arbiter for dual port access + +module ramArbiter ( + // system + input wire CLK, + input wire RSTb, + // ctrl interfaces 1 + input wire CTRL_CSb1, + input wire CTRL_WEb1, + input wire [7:0] CTRL_ADDR1, + input wire [31:0] CTRL_DATA_IN1, + output wire [31:0] CTRL_DATA_OUT1, + // ctrl interface 2 + input wire CTRL_CSb2, + input wire CTRL_WEb2, + input wire [7:0] CTRL_ADDR2, + input wire [31:0] CTRL_DATA_IN2, + output wire [31:0] CTRL_DATA_OUT2, + // RAM interface byte0 + output wire RAM_CSb0, + output wire RAM_WEb0, + output wire [4:0] RAM_ADDR0, + output wire [7:0] RAM_DATA_IN0, + input wire [7:0] RAM_DATA_OUT0, + // RAM interface byte1 + output wire RAM_CSb1, + output wire RAM_WEb1, + output wire [4:0] RAM_ADDR1, + output wire [7:0] RAM_DATA_IN1, + input wire [7:0] RAM_DATA_OUT1, + // RAM interface byte2 + output wire RAM_CSb2, + output wire RAM_WEb2, + output wire [4:0] RAM_ADDR2, + output wire [7:0] RAM_DATA_IN2, + input wire [7:0] RAM_DATA_OUT2, + // RAM interface byte3 + output wire RAM_CSb3, + output wire RAM_WEb3, + output wire [4:0] RAM_ADDR3, + output wire [7:0] RAM_DATA_IN3, + input wire [7:0] RAM_DATA_OUT3 +); + // internal output signals + reg RAM_WEb_i; + reg [4:0] RAM_ADDR_i; + reg [31:0] RAM_DATA_IN_i; + // interface read data + reg [31:0] READ_DATA1_Q; + reg [31:0] READ_DATA1_D; + reg [31:0] READ_DATA2_Q; + reg [31:0] READ_DATA2_D; + + // module outputs + assign RAM_CSb0 = 1'b0; + assign RAM_WEb0 = RAM_WEb_i; + assign RAM_ADDR0 = RAM_ADDR_i; + assign RAM_DATA_IN0 = RAM_DATA_IN_i[7:0]; + assign RAM_CSb1 = 1'b0; + assign RAM_WEb1 = RAM_WEb_i; + assign RAM_ADDR1 = RAM_ADDR_i; + assign RAM_DATA_IN1 = RAM_DATA_IN_i[15:8]; + assign RAM_CSb2 = 1'b0; + assign RAM_WEb2 = RAM_WEb_i; + assign RAM_ADDR2 = RAM_ADDR_i; + assign RAM_DATA_IN2 = RAM_DATA_IN_i[23:16]; + assign RAM_CSb3 = 1'b0; + assign RAM_WEb3 = RAM_WEb_i; + assign RAM_ADDR3 = RAM_ADDR_i; + assign RAM_DATA_IN3 = RAM_DATA_IN_i[31:24]; + + // interface read access (if1 always wins) + always @(*) begin : if_read_access + reg [31:0] vRamDataOut; + // default + READ_DATA1_D <= READ_DATA1_Q; + READ_DATA2_D <= READ_DATA2_Q; + // concatenate RAM data + vRamDataOut = {RAM_DATA_OUT3, RAM_DATA_OUT2, RAM_DATA_OUT1, RAM_DATA_OUT0}; + // interface selection + if(CTRL_CSb1 == 1'b0) READ_DATA1_D <= vRamDataOut; + else if(CTRL_CSb2 == 1'b0 ) READ_DATA2_D <= vRamDataOut; + end + assign CTRL_DATA_OUT1 = (CTRL_CSb1 == 1'b0) ? {RAM_DATA_OUT3, RAM_DATA_OUT2, RAM_DATA_OUT1, RAM_DATA_OUT0} : READ_DATA1_Q; + assign CTRL_DATA_OUT2 = (CTRL_CSb2 == 1'b0) ? {RAM_DATA_OUT3, RAM_DATA_OUT2, RAM_DATA_OUT1, RAM_DATA_OUT0} : READ_DATA2_Q; + + // interface multiplexer (if1 always wins) + always @(*) begin + if(CTRL_CSb1 == 1'b0) begin + RAM_WEb_i = CTRL_WEb1; + RAM_ADDR_i = CTRL_ADDR1[7:2]; + RAM_DATA_IN_i = CTRL_DATA_IN1; + end else begin + RAM_WEb_i = CTRL_WEb2; + RAM_ADDR_i = CTRL_ADDR2[7:2]; + RAM_DATA_IN_i = CTRL_DATA_IN2; + end + end + + // flip flops + always @(posedge CLK, negedge RSTb) begin + if(RSTb == 1'b0) begin + READ_DATA1_Q <= 32'h00_00_00_00; + READ_DATA2_Q <= 32'h00_00_00_00; + end else begin + READ_DATA1_Q <= READ_DATA1_D; + READ_DATA2_Q <= READ_DATA2_D; + end + end +endmodule \ No newline at end of file
diff --git a/verilog/rtl/user_proj_example.v b/verilog/rtl/user_proj_example.v index 26081e9..880e693 100644 --- a/verilog/rtl/user_proj_example.v +++ b/verilog/rtl/user_proj_example.v
@@ -13,7 +13,8 @@ // limitations under the License. // SPDX-License-Identifier: Apache-2.0 -`default_nettype none +//`default_nettype none +`default_nettype wire /* *------------------------------------------------------------- * @@ -68,98 +69,162 @@ // IRQ output [2:0] irq ); - 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] rdata; - 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; - assign wstrb = wbs_sel_i & {4{wbs_we_i}}; - assign wbs_dat_o = rdata; - assign wdata = wbs_dat_i; - - // IO - assign io_out = count; - assign io_oeb = {(`MPRJ_IO_PADS-1){rst}}; + // gpio interface + wire GPIO_WE; + wire [3:0] GPIO_ADDR; + wire [31:0] GPIO_DATA_IN; + wire [31:0] GPIO_DATA_OUT; + // RAM interface 1 (wishbone bus) + wire WB_RAM_CSb; + wire WB_RAM_WEb; + wire [7:0] WB_RAM_ADDR; + wire [31:0] WB_RAM_DATA_IN; + wire [31:0] WB_RAM_DATA_OUT; + // RAM interface 2 (gpio control) + wire GPIO_RAM_CSb; + wire GPIO_RAM_WEb; + wire [7:0] GPIO_RAM_ADDR; + wire [31:0] GPIO_RAM_DATA_IN; + wire [31:0] GPIO_RAM_DATA_OUT; + // open RAM + wire RAM_CSb[3:0]; + wire RAM_WEb[3:0]; + wire [4:0] RAM_ADDR[3:0]; + wire [7:0] RAM_DATA_IN[3:0]; + wire [7:0] RAM_DATA_OUT[3:0]; // IRQ assign irq = 3'b000; // Unused - // LA - assign la_data_out = {{(127-BITS){1'b0}}, count}; - // Assuming LA probes [63:32] are for controlling the count register - assign la_write = ~la_oenb[63:32] & ~{BITS{valid}}; - // Assuming LA probes [65:64] are for controlling the count clk & reset - assign clk = (~la_oenb[64]) ? la_data_in[64]: wb_clk_i; - assign rst = (~la_oenb[65]) ? la_data_in[65]: wb_rst_i; + // logic analyzer output signals + assign la_data_out[0] = GPIO_WE; + assign la_data_out[1+:2] = GPIO_ADDR[3:2]; + assign la_data_out[3+:32] = GPIO_DATA_IN; + assign la_data_out[35] = RAM_CSb[0]; + assign la_data_out[36] = RAM_WEb[0]; + assign la_data_out[37+:5] = RAM_ADDR[0]; + assign la_data_out[42+:8] = RAM_DATA_IN[0]; + assign la_data_out[50+:8] = RAM_DATA_OUT[0]; + assign la_data_out[58] = RAM_CSb[0]; + assign la_data_out[59] = RAM_WEb[0]; + assign la_data_out[60+:5] = RAM_ADDR[0]; + assign la_data_out[65+:8] = RAM_DATA_IN[0]; + assign la_data_out[73+:8] = RAM_DATA_OUT[0]; + assign la_data_out[81] = RAM_CSb[0]; + assign la_data_out[82] = RAM_WEb[0]; + assign la_data_out[83+:5] = RAM_ADDR[0]; + assign la_data_out[88+:8] = RAM_DATA_IN[0]; + assign la_data_out[96+:8] = RAM_DATA_OUT[0]; + assign la_data_out[104] = RAM_CSb[0]; + assign la_data_out[105] = RAM_WEb[0]; + assign la_data_out[106+:5] = RAM_ADDR[0]; + assign la_data_out[111+:8] = RAM_DATA_IN[0]; + assign la_data_out[119+:8] = RAM_DATA_OUT[0]; + // logic analyter input signals (unused) + //la_data_in + //la_oenb - counter #( - .BITS(BITS) - ) counter( - .clk(clk), - .reset(rst), - .ready(wbs_ack_o), - .valid(valid), - .rdata(rdata), - .wdata(wbs_dat_i), - .wstrb(wstrb), - .la_write(la_write), - .la_input(la_data_in[63:32]), - .count(count) + // wishbone slave interface + wbSlave wbSlave_inst ( + // wishbone slave interface + .CLK_I (wb_clk_i), // bus clock signal + .RST_I (wb_rst_i), // bus reset signal + .STB_I (wbs_stb_i), // bus transaction request + .CYC_I (wbs_cyc_i), // active transaction + .WE_I (wbs_we_i), // write request + .SEL_I (wbs_sel_i), // byte select for request + .DAT_I (wbs_dat_i), // data for request + .ADR_I (wbs_adr_i), // address for request + .ACK_O (wbs_ack_o), // request acknowledge, read data valid + .DAT_O (wbs_dat_o), // requested read data + .CTRL_WE (GPIO_WE), + .CTRL_ADDR (GPIO_ADDR), + .CTRL_DATA_IN (GPIO_DATA_IN), + .CTRL_DATA_OUT (GPIO_DATA_OUT), + .RAM_CSb (WB_RAM_CSb), + .RAM_WEb (WB_RAM_WEb), + .RAM_ADDR (WB_RAM_ADDR), + .RAM_DATA_IN (WB_RAM_DATA_IN), + .RAM_DATA_OUT (WB_RAM_DATA_OUT) ); -endmodule + // gpio control module + gpioCtrl gpioCtrl_inst ( + // system + .CLK (wb_clk_i), + .RSTb (!wb_rst_i), + // control interface + .CTRL_WE (GPIO_WE), + .CTRL_ADDR (GPIO_ADDR), + .CTRL_DATA_IN (GPIO_DATA_IN), + .CTRL_DATA_OUT (GPIO_DATA_OUT), + // caravel gpio signaling + .GPIO_IN (io_in), + .GPIO_OUT (io_out), + .GPIO_OEb (io_oeb), + // RAM interface + .RAM_CSb (GPIO_RAM_CSb), + .RAM_WEb (GPIO_RAM_WEb), + .RAM_ADDR (GPIO_RAM_ADDR), + .RAM_DATA_IN (GPIO_RAM_DATA_IN), + .RAM_DATA_OUT (GPIO_RAM_DATA_OUT) + ); -module counter #( - parameter BITS = 32 -)( - input clk, - input reset, - input valid, - input [3:0] wstrb, - input [BITS-1:0] wdata, - input [BITS-1:0] la_write, - input [BITS-1:0] la_input, - output ready, - output [BITS-1:0] rdata, - output [BITS-1:0] count -); - reg ready; - reg [BITS-1:0] count; - reg [BITS-1:0] rdata; + // ram arbiter + ramArbiter ramArbiter_inst ( + // system + .CLK (CLK_I_tb), + .RSTb (!RST_I_tb), + // ctrl interface 1 + .CTRL_CSb1 (WB_RAM_CSb), + .CTRL_WEb1 (WB_RAM_WEb), + .CTRL_ADDR1 (WB_RAM_ADDR), + .CTRL_DATA_IN1 (WB_RAM_DATA_IN), + .CTRL_DATA_OUT1 (WB_RAM_DATA_OUT), + // ctrl interface 2 + .CTRL_CSb2 (GPIO_RAM_CSb), + .CTRL_WEb2 (GPIO_RAM_WEb), + .CTRL_ADDR2 (GPIO_RAM_ADDR), + .CTRL_DATA_IN2 (GPIO_RAM_DATA_IN), + .CTRL_DATA_OUT2 (GPIO_RAM_DATA_OUT), + // RAM interface byte0 + .RAM_CSb0 (RAM_CSb[0]), + .RAM_WEb0 (RAM_WEb[0]), + .RAM_ADDR0 (RAM_ADDR[0]), + .RAM_DATA_IN0 (RAM_DATA_IN[0]), + .RAM_DATA_OUT0 (RAM_DATA_OUT[0]), + // RAM interface byte1 + .RAM_CSb1 (RAM_CSb[1]), + .RAM_WEb1 (RAM_WEb[1]), + .RAM_ADDR1 (RAM_ADDR[1]), + .RAM_DATA_IN1 (RAM_DATA_IN[1]), + .RAM_DATA_OUT1 (RAM_DATA_OUT[1]), + // RAM interface byte2 + .RAM_CSb2 (RAM_CSb[2]), + .RAM_WEb2 (RAM_WEb[2]), + .RAM_ADDR2 (RAM_ADDR[2]), + .RAM_DATA_IN2 (RAM_DATA_IN[2]), + .RAM_DATA_OUT2 (RAM_DATA_OUT[2]), + // RAM interface byte3 + .RAM_CSb3 (RAM_CSb[3]), + .RAM_WEb3 (RAM_WEb[3]), + .RAM_ADDR3 (RAM_ADDR[3]), + .RAM_DATA_IN3 (RAM_DATA_IN[3]), + .RAM_DATA_OUT3 (RAM_DATA_OUT[3]) + ); - always @(posedge clk) begin - if (reset) begin - count <= 0; - ready <= 0; - end else begin - ready <= 1'b0; - if (~|la_write) begin - count <= count + 1; - end - if (valid && !ready) begin - ready <= 1'b1; - rdata <= count; - if (wstrb[0]) count[7:0] <= wdata[7:0]; - if (wstrb[1]) count[15:8] <= wdata[15:8]; - if (wstrb[2]) count[23:16] <= wdata[23:16]; - if (wstrb[3]) count[31:24] <= wdata[31:24]; - end else if (|la_write) begin - count <= la_write & la_input; - end + // 32-bit open RAM instanciation + generate + genvar vRamByte; + for (vRamByte=0; vRamByte<4; vRamByte=vRamByte+1) begin + openRam openRam_inst ( + .CLK (CLK_I_tb), + .CSb (RAM_CSb[vRamByte]), + .WEb (RAM_WEb[vRamByte]), + .ADDR (RAM_ADDR[vRamByte]), + .DATA_IN (RAM_DATA_IN[vRamByte]), + .DATA_OUT (RAM_DATA_OUT[vRamByte]) + ); end - end - -endmodule -`default_nettype wire + endgenerate +endmodule \ No newline at end of file
diff --git a/verilog/rtl/wishboneSlave/wbSlave.v b/verilog/rtl/wishboneSlave/wbSlave.v new file mode 100644 index 0000000..7d8a6bd --- /dev/null +++ b/verilog/rtl/wishboneSlave/wbSlave.v
@@ -0,0 +1,76 @@ +// wishbone slave module +// address space: +// caraval user block: 0x30000000 to 0x7FFFFFFFF +// GPIO user block: 0x30000000 to 0x30000000F +// RAM user block: 0x30000080 to 0x3000000FF + +module wbSlave ( + // wishbone slave interface + input wire CLK_I, // bus clock signal + input wire RST_I, // bus reset signal + input wire STB_I, // bus transaction request + input wire CYC_I, // active transaction + input wire WE_I, // write request + input wire [3:0] SEL_I, // byte select for request + input wire [31:0] DAT_I, // data for request + input wire [31:0] ADR_I, // address for request + output wire ACK_O, // request acknowledge, read data valid + output wire [31:0] DAT_O, // requested read data + // gpio interface + output wire CTRL_WE, + output wire [3:0] CTRL_ADDR, + output wire [31:0] CTRL_DATA_IN, + input wire [31:0] CTRL_DATA_OUT, + // RAM interface + output wire RAM_CSb, + output wire RAM_WEb, + output wire [7:0] RAM_ADDR, + output wire [31:0] RAM_DATA_IN, + input wire [31:0] RAM_DATA_OUT +); + + // acknowledge shift register + reg [1:0] ACK_O_Q; + // ram write enable edge detection + wire RAM_WE_i; + reg RAM_WE_Q; + // control write enable edge detection + wire CTRL_WE_i; + reg CTRL_WE_Q; + + // module output + assign DAT_O = DAT_O_i; + + // ram access + assign RAM_CSb = (ADR_I[7] == 1'b1) ? 1'b0 : 1'b1; + assign RAM_WE_i = (ADR_I[7] == 1'b1) ? CYC_I & STB_I & WE_I : 1'b0; + assign RAM_WEb = !(!RAM_WE_Q & RAM_WE_i); + assign RAM_ADDR = ADR_I[7:0]; + assign RAM_DATA_IN = DAT_I; + + // gpio access + assign CTRL_WE_i = (ADR_I[7] == 1'b0) ? CYC_I & STB_I & WE_I : 1'b0; + assign CTRL_WE = !CTRL_WE_Q & CTRL_WE_i; + assign CTRL_ADDR = ADR_I[3:0]; + assign CTRL_DATA_IN = DAT_I; + + // read multiplexer + assign DAT_O = (ADR_I[7] == 1'b1) ? RAM_DATA_OUT : CTRL_DATA_OUT; + + // acknowledge + assign ACK_O = ((CYC_I & STB_I) == 1'b0) ? 1'b0 : ACK_O_Q[1]; + + // flip flops + always @(posedge CLK_I, posedge RST_I) begin + if (RST_I == 1'b1) begin + ACK_O_Q <= 1'b0; + RAM_WE_Q <= 1'b0; + CTRL_WE_Q <= 1'b0; + end else begin + ACK_O_Q <= {ACK_O_Q[0], CYC_I & STB_I}; + RAM_WE_Q <= RAM_WE_i; + CTRL_WE_Q <= CTRL_WE_i; + end + end + +endmodule \ No newline at end of file
diff --git a/verilog/rtl/wishboneSlave/wbSlaveTb.v b/verilog/rtl/wishboneSlave/wbSlaveTb.v new file mode 100644 index 0000000..139597f --- /dev/null +++ b/verilog/rtl/wishboneSlave/wbSlaveTb.v
@@ -0,0 +1,2 @@ + +