1
0
mirror of synced 2026-01-13 23:36:01 +00:00
lisper.cpus-pdp8/v/programramdac.v
2007-01-02 16:24:48 +00:00

209 lines
5.0 KiB
Verilog

// programramdac.v
// hardcoded values for initialising the RAMDAC
module dac_data(addr, o);
input[2:0] addr;
output o;
reg [7:0] o;
// hard code initial control register programming values
// DAC(76543210)
always @(addr)
case (addr)
3'd0: o <= 8'b10000001; // Cmd reg A, high colour dual edged mode
3'd1: o <= 8'b00000000; // Pallette address reg gets $00
3'd2: o <= 8'b11111111; // Read mask reg gets $FF
3'd3: o <= 8'b00000010; // Pallette address reg gets $02
3'd4: o <= 8'b00000010; // Command reg B gets $02
3'd5: o <= 8'b00000000; // Pallette address reg gets $00
endcase // case(addr)
endmodule
module dac_rs(addr, o);
input[2:0] addr;
output o;
reg [2:0] o;
// RS(210)
always @(addr)
case (addr)
3'd0: o <= 3'b110; // RS gets Command reg A
3'd1: o <= 3'b000; // RS gets Pallette address reg
3'd2: o <= 3'b010; // RS gets Read mask reg
3'd3: o <= 3'b000; // RS gets Pallette address reg
3'd4: o <= 3'b010; // RS gets Command reg B
3'd5: o <= 3'b000; // RS gets Pallette address reg
endcase
endmodule
module programramdac(rstn, clk, start, done, WRn, RDn, RS, data);
input rstn;
input clk;
input start; // start signal
output done;
output WRn; // write line to ramdac
output RDn; // read line ot ramdac
input [2:0] RS; // register select lines to ramdac
inout [7:0] data; // data lines to ramdac
reg done, WRn;
// FSM states for the main mealy FSM
parameter [2:0]
stIdle = 3'd0,
stWrite = 3'd1,
stWrCycle = 3'd2,
stNextWrite = 3'd3;
reg [2:0] presState, nextState;
// initCnt controls write state
reg [2:0] initCnt;
reg increment;
// signals to create a 12.5MHz clock from the 50MHz input clock
wire divclk;
reg [1:0] gray_cnt;
// create signals so the data and RS lines can be used as tristate
// buffers. this is important as they share lines with the ethernet PHY
reg [7:0] prgData;
reg [2:0] prgRS;
reg latchData;
reg latchRS;
wire [7:0] theData;
wire [2:0] theRs;
// data and register select
dac_data arraydac(.addr(initCnt), .o(theData));
dac_rs arrayrs(.addr(initCnt), .o(theRS));
// clock divider by 4 to for a slower clock to avoid timing violations
// uses grey code for minimized logic
always @(posedge clk or rstn)
if (~rstn)
gray_cnt <= 2'b00;
else
case (gray_cnt)
2'b00: gray_cnt <= 2'b01;
2'b01: gray_cnt <= 2'b11;
2'b11: gray_cnt <= 2'b10;
2'b10: gray_cnt <= 2'b00;
default: gray_cnt <= 2'b00;
endcase
// assign the clock that this entity runs off
assign divclk = gray_cnt[1];
// read isn't needed, tie high
assign RDn = 1;
// main clocked process
always @(posedge divclk or rstn)
if (~rstn)
begin
presState <= stIdle;
initCnt <= 0;
end
else
if (divclk == 1)
begin
presState <= nextState;
if (increment)
if (initCnt < 5)
initCnt <= initCnt + 1;
else
initCnt <= 0;
end
// Main FSM process
always @(presState, start, initCnt)
begin
// default signals and outputs for each FSM state
// note that the latch data and rs signals are defaulted to 1,
// so are only 0 in the idle state
WRn <= 1;
increment <= 0;
prgData <= 0;
prgRS <= 3'b001;
latchData <= 1;
latchRS <= 1;
done <= 0;
case (presState)
stIdle:
begin
// wait for start signal from another process
if (start)
begin
nextState <= stWrite;
// setup for the first write to the RAMDAC for use
// by setting the register select lines and
// the data lines
prgRS <= theRS;
prgData <= theData;
end
else
begin
nextState <= stIdle;
latchData <= 0;
latchRS <=0;
end
end
stWrite:
begin
// hold the register select and data lines for
// the write cycle and set the active low write signal
nextState <= stWrCycle;
prgRS <= theRS;
prgData <= theData;
WRn <= 0;
end
stWrCycle:
begin
// continue if all 5 registers have been programmed
if (initCnt == 5)
begin
nextState <= stIdle;
done <= 1;
end
else
// continue writing to the registers
nextState <= stNextWrite;
// hold the data to be sure the hold times aren't violated
prgRS <= theRS;
prgData <= theData;
// increment initCnt to program the next register
increment <= 1;
end
stNextWrite:
begin
nextState <= stWrite;
// setup for the next write cycle
prgRS <= theRS;
prgData <= theData;
end
endcase;
// assign data and RS prgData and prgRS respectively when they
// need to be latched otherwise keep them at high impedance
// to create a tri state buffer
end // always @ (presState, start, initCnt)
assign data = latchData ? prgData : 8'bz;
assign RS = latchRS ? prgRS : 3'bz;
endmodule