Someone sent me a note this week wanting to find a source for the MOS 6523T Tri Port Interface, and I felt after looking at the datasheet that I could just whip one up in Verilog.
And... I think I have, but along the way, I am stuck on a chunk of Verilog that I can't seem to get my arms around.
To create the design, I created 6 registers (3 output holding regs for the output data, and 3 ddr regs).
Code:
register reg_port_a(r_w, reset, ce & (address == 0), data[7:0], rega_out);
register reg_port_b(r_w, reset, ce & (address == 1), data[7:0], regb_out);
register reg_port_c(r_w, reset, ce & (address == 2), data[7:0], regc_out);
register reg_ddr_a(r_w, reset, ce & (address == 3), data[7:0], ddra);
register reg_ddr_b(r_w, reset, ce & (address == 4), data[7:0], ddrb);
register reg_ddr_c(r_w, reset, ce & (address == 5), data[7:0], ddrc);
Mux to handle the addressing:
Code:
mux8_1 reg_mux(address[2:0],rega_in, regb_in , regc_in, ddra, ddrb, ddrc,0,0,reg_data);
assign data = (r_w & ce ? reg_data : 8'bz); // show values on read
and 3 io ports:
Code:
ioport ioport_a(ddra,porta, rega_out, rega_in);
ioport ioport_b(ddrb,portb, regb_out, regb_in);
ioport ioport_c(ddrc,portc, regc_out, regc_in);
It's this last part that I am struggling with. I got it to compile and the RTL looks right (need to test it, obviously), but the code is not generic like I want:
Code:
module ioport(ddr, io_port, d, q);
parameter WIDTH = 8 ;
input [WIDTH-1:0] ddr; // data direction register
inout [WIDTH-1:0] io_port; // external IO
input [WIDTH-1:0] d; // data from IO pins to be read into memory
output [WIDTH-1:0] q; // data from internal register to be placed on IO pins
reg [WIDTH-1:0] q;
integer i;
// also tried to put a generate/begin/for block here, but no dice.
assign io_port[0] = (ddr[0] ? d[0] : 'bz); // if ddr is high, put data on output pin, else hi z
assign io_port[1] = (ddr[1] ? d[1] : 'bz); // if ddr is high, put data on output pin, else hi z
assign io_port[2] = (ddr[2] ? d[2] : 'bz); // if ddr is high, put data on output pin, else hi z
assign io_port[3] = (ddr[3] ? d[3] : 'bz); // if ddr is high, put data on output pin, else hi z
assign io_port[4] = (ddr[4] ? d[4] : 'bz); // if ddr is high, put data on output pin, else hi z
assign io_port[5] = (ddr[5] ? d[5] : 'bz); // if ddr is high, put data on output pin, else hi z
assign io_port[6] = (ddr[6] ? d[6] : 'bz); // if ddr is high, put data on output pin, else hi z
assign io_port[7] = (ddr[7] ? d[7] : 'bz); // if ddr is high, put data on output pin, else hi z
always @*
begin
for (i = 0; i < WIDTH; i = i + 1)
begin
// below is what I want to do
//io_port[i] = (ddr[i] ? d[i] : 'bz); // if ddr is high, put data on output pin, else hi z
q[i] <= (!ddr[i] ? io_port[i] : 0); // if ddr is low, put input on reg pin, else 0
end
end
endmodule
See that horrid 8 line abomination. I know I am just missing the trick to this, but I have tried a few different solutions. generate/for gave errors on conditional logic, putting the assign in the main for block errors, and just putting a for in the beginning of the module errors out as well. I can't seem to find conditional logic generate statements or my googlefu is sufficiently weak tonight.
Help on this point would be appreciated, and I'm happy to put the resulting file up for anyone, it's nothing special. At present, it implements a 6523, but subsetting the bits will turn it into a 6523T (12 bits instead of 24)
Jim