> > Yes, I recently (as in yesterday, I was going to post it today) combined
> > them into one, and so the video signals go to the top level.
> 
> Combined which parts?

gen_head0_signals and test_head0_out. It is now a single module that
talks to a test case.

> As long as it's mostly working, you can turn off the VCD capture and
> just use the PPM file as your diagnostic.  If you find a bug, then
> change the timing numbers to something really small and THEN use a
> waveform viewer.  Not only does signal capture take up space, but it
> slows the simulation.  Also, you can select a subset of signals to
> capture.  You can capture only selected interesting signals.
> 

How is it that you only capture certain signals?

This new version is much smaller, close to the 200MB mark, since I
realized I get 2 pixel/clock now so I only need 1/2 the time length.

> > Again, this should be much nicer later tonight (e.g. no editing needed)!
> > PS. I attached a version with the 1600 width if people want it. Also, I
> > need to add the dual licensing stuff to it - for now there is nothing,
> > but pretend that it has the whole message.
> 
> I look forward to it.  :)

Here it is!
I still haven't done multi-frame capture, but besides that it works
great. There are two oddities, however:
1) The colors are a little messed up. I don't know why, but I have to
read them off at the monitor end out of order to get correct values. I
imagine this means that I have done something wrong somewhere.
2) The last line glitches. I think it might have to do with delay
induced by the lastpixel logic, but I don't really know yet. Whatever
causes it, the line is the first line of a new frame. In addition, there
are two pixels right at the beginning (1 clock because 1 master pixel
and 1 slave pixel) which shouldn't be there. they show up as "x x x\nx x
x\n" in the scanimage.ppm file. Any ideas on how to fix this? Until
then, there is still editing :-( just delete the x x x lines, and that
should product nice images.

Lastly, should I convert the code to work with Simon's module? There was
some copyright confusion with Xilinx code, and I don't want to convert
it and not have the new version used.

I am currently working on working on a driver for ODG using
skeletonfb.c, but if there is more work to be done on this end, I will
be happy to do that instead (after all, there is no point in having a
framebuffer driver to a chip that can't display it's framebuffer!) :-)

Nicholas
//This is a module for simulating a video device for OGP.
//It was written by Nicholas Sinnott-Armstrong in October, 2006.
//In the course of writing this code, I am forever indebted to the following
//people:
//The writers of the Verilog tutorials at ASIC World, which showed me how
//fun, interesting, and useful Verilog can be;
//the writers at fpga4fun for renewing my interest in Verilog;
//Timothy Miller for being such an amazing motivational force and an
//altogether amazing aid;
//and Xilinx, for selling nice FPGAs that make this code worthwhile.
//
//This is a fake video card written for the Open Graphics Project to test
//ODG1 and subsequent video cards. As such, it is covered by their dual
//licence, which is a dual commercial, by Traversal Technology, and GPL
//licence.


//
//It is inspired by this message from Timothy Miller:

//How about simulating a video device?

//When we did TROZ, we developed simulation code that watched video
//signals coming out of the design and pretended to be a monitor.  Each
//frame of raster scan got output to an ASCII-format PPM file (the kind
//with "P3" as the first line) that we could look at later with an image
//viewer.

//Look up the functions $fopen, $fdisplay, $fwrite, and $fclose.

//And learn how to do text strings in Verilog, which is kludgy.

//For a 10-char string, you would do something like:

//reg [0:8*10-1] string;

//...

//    string = "somestringx";


//There are actually a number of things we could use simulation models
//for.  The one for SPI, I think, was okay, but it could be expanded.
//We need one for DDR SDRAM; the one from Samsung won't work with
//icarus, so we either fix it, or we write our own (that does NOT have
//to be as sophisticated).

//Also, if you work on something related to OGD1, then that will really
//help, but really, you can work on other things, and I'll be glad to
//help with those too.

module vidfake(    
// Common data pins
    vid_data,

    // Syncs and clock for analog interface
    dac_hsync,
    dac_vsync,
    dac_de,
    dac_clk,

    // Syncs and clocks for DVI interface
    dvi_m_clk,
    dvi_s_clk,
    dvi_hsync,
    dvi_vsync,
    dvi_de );
parameter WIDTH=800,HEIGHT=600;
//currently just DVI because that is what I have been doing, but it is
// almost the same code for DAC. However, I haven't figured out the master
// and slave DVI transmitter yet, so just use the master, since it sounds 
// like the more important one.
input [29:0] vid_data;
input dac_hsync,dac_vsync,dac_de,dac_clk;
input dvi_m_clk,dvi_s_clk,dvi_hsync,dvi_vsync,dvi_de;

wire [29:0] vid_data;
wire dac_hsync,dac_vsync,dac_de,dac_clk;
wire dvi_m_clk,dvi_s_clk,dvi_hsync,dvi_vsync,dvi_de;

integer file; //the file descriptor
reg tofile; //are we printing or writing to a file the output?
integer ch; //something - channel? 
reg startedframe;
//from http://www-ee.eng.hawaii.edu/~msmith/ASICs/HTML/Book/CH11/CH11.13.htm
//other resources:
//http://www.chris.spear.net/pli/fileio.htm
//http://www.sugawara-systems.com/verilog-2001/fileio.htm

//and for PPM format:
//http://netpbm.sourceforge.net/doc/ppm.html
//http://www.physics.emory.edu/~weeks/graphics/mkppm.html
reg [9:2] r0,g0,b0; //red, green, blue color components
reg [9:2] r1,g1,b1; //red, green, blue color components for slave pixel
initial begin
   file=$fopen("scanimage.ppm","w");
   if (file==0) begin
      $display("error with opening file, printing instead...");
      tofile=1'b0;
   end else begin
      tofile=1'b1;
      ch=file|1;
   end
   //this is going to be read during the first frame eventually, but for now
   // it is easier if it is just hardcoded.
   if (tofile==1'b1) begin
           $fwrite(ch,"P3\n"); //magic code for PPM plain
           $fwrite(ch,"# Test image drawn by DVI tester for OGP\n");
           $fwrite(ch,"%d ",WIDTH);
           $fwrite(ch,"%d\n",HEIGHT);
           $fwrite(ch,"255\n"); //max color value
   end else begin
           $display("P3\n"); //magic code for PPM plain
           $display("# Test image drawn by DVI tester for OGP\n");
           $display("%d ",WIDTH);
           $display("%d\n",HEIGHT);
           $display("255\n"); //max color value
   end
end
always @(posedge dvi_m_clk) begin
        if (dvi_de) begin
                r0[9:2]<=vid_data[29:22];
                g0[9:6]<=vid_data[21:18];
        end
end

always @(negedge dvi_m_clk) begin
        if (dvi_de) begin
                g0[5:2]<=vid_data[29:26];
                b0[9:2]<=vid_data[25:18];
                //store in 8:8:8 RGB format, 24bpp.
                if (tofile==1'b1) begin
                        $fwrite(ch,"%d ",b0);
                        $fwrite(ch,"%d ",r0);
                        $fwrite(ch,"%d\n",g0);
                        //this should make each line longer, but I don't
                        //want to have to deal with that for now.
                end else begin
                        $display("%d ",b0);
                        $display("%d ",r0);
                        $display("%d\n",g0);
                end
        end
end
always @(posedge dvi_s_clk) begin
        if (dvi_de) begin
                r1[9:2]<=vid_data[17:10];
                g1[9:6]<=vid_data[9:6];
        end
end

always @(negedge dvi_s_clk) begin
        if (dvi_de) begin
                g1[5:2]<=vid_data[17:14];
                b1[9:2]<=vid_data[13:6];
                //store in 8:8:8 RGB format, 24bpp.
                if (tofile==1'b1) begin
                        $fwrite(ch,"%d ",b1);
                        $fwrite(ch,"%d ",r1);
                        $fwrite(ch,"%d\n",g1);
                        //this should make each line longer, but I don't
                        //want to have to deal with that for now.
                end else begin
                        $display("%d ",b1);
                        $display("%d ",r1);
                        $display("%d\n",g1);
                end
        end
end
endmodule
//This is a module for controlling DVI output of data on ODG1 and future
//devices written by Nicholas Sinnott-Armstrong in September and October,
//2006.
//In the course of writing this code, I am forever indebted to the following
//people:
//The writers of the Verilog tutorials at ASIC World, which showed me how
//fun, interesting, and useful Verilog can be;
//the writers at fpga4fun for renewing my interest in Verilog;
//Timothy Miller for being such an amazing motivational force and an
//altogether amazing aid;
//and Xilinx, for selling nice FPGAs that make this code worthwhile.
//
//This is a video output module written for the Open Graphics Project to use
//in ODG1 and subsequent video cards. As such, it is covered by their dual
//licence, which is a dual commercial, by Traversal Technology, and GPL
//licence.

module test_head0;
//simple test interface
wire clkout,clk2out,resetout;
reg clock, clock_2x,reset;
initial begin
    clock = 0;
    forever begin
        clock = !clock;
        #2;
    end
end

initial begin
    clock_2x = 0;
    forever begin
        clock_2x = !clock_2x;
        #1;
    end
end

initial begin
//    $dumpfile("testDVI.vcd");
//    $dumpvars;
    reset = 0;
    #100;
    reset = 1;
    
    #1300000;
    $finish;
end

assign clkout=clock;
assign clk2out=clock_2x;
assign resetout=reset;

wire [29:0] data;
wire Ahs,Avs,Ade,Aclk,Dmclk,Dsclk,Dhs,Dvs,Dde; //the output signals.

head0_video_out u0(clkout, clk2out, resetout, data, Ahs, Avs, Ade, Aclk, Dmclk, 
Dsclk, Dhs, Dvs, Dde);

vidfake faker(data,Ahs,Avs,Ade,Aclk,
                Dmclk,Dsclk,Dhs,Dvs,Dde); //This is a fake DVI monitor that 
outputs PPM
endmodule


module head0_video_out(
    clock,
    clock_2x,
    reset,
    
    // Common data pins
    vid_data,

    // Syncs and clock for analog interface
    dac_hsync,
    dac_vsync,
    dac_de,
    dac_clk,

    // Syncs and clocks for DVI interface
    dvi_m_clk,
    dvi_s_clk,
    dvi_hsync,
    dvi_vsync,
    dvi_de
);
input clock, clock_2x, reset;

output [29:0] vid_data;

output dac_hsync, dac_vsync, dac_de, dac_clk;
output dvi_m_clk, dvi_s_clk, dvi_hsync, dvi_vsync, dvi_de;
reg dac_hsync, dac_vsync, dac_de;
reg dvi_hsync, dvi_vsync, dvi_de;



// ----------

// Pixel data -- notice that we process two pixels per clock
reg [9:0] r0, g0, b0;   // even pixel
reg [9:0] r1, g1, b1;   // odd pixel

// And the syncs
reg hsync, vsync, de;
//Timing from "gtf 800 600 60" - 800x600, 60Hz, 38.22Mhz clock
/*parameter     H_ACTIVE =      800,    // pixels
                H_FRONT_PORCH = 32,     // pixels
                H_SYNCH =       80,     // pixels
                H_BACK_PORCH =  112,    // pixels
                H_TOTAL =       1024,   // pixels
                V_ACTIVE =      600,    // lines
                V_FRONT_PORCH = 1,      // lines
                V_SYNCH =       3,      // lines
                V_BACK_PORCH =  18,     // lines
                V_TOTAL =       622;    // lines
// This is for use with single DVI transmitter. Divide in half for two
// transmitters.*/
//Timing from "gtf 800 600 60" - 800x600, 60Hz, 38.22Mhz clock
parameter       H_ACTIVE =      800/2,  // pixels
                H_FRONT_PORCH = 32/2,   // pixels
                H_SYNCH =       80/2,   // pixels
                H_BACK_PORCH =  112/2,  // pixels
                H_TOTAL =       1024/2, // pixels
                V_ACTIVE =      600,    // lines
                V_FRONT_PORCH = 1,      // lines
                V_SYNCH =       3,      // lines
                V_BACK_PORCH =  18,     // lines
                V_TOTAL =       622;    // lines
//Some parameters so that if syncs are different for some reason they can
        //change.
parameter       SYNC_STATE=1'b1,
                PORCH_STATE=1'b0,
                DATA_STATE=2'b00;       

reg [9:0] vert; //current vertical scanline location
reg [11:0] horiz; //current pixel in scanline
reg [1:0] hstate; //horizontal and vertical states
reg [1:0] vstate; //so it is easier to ref them.
reg lastpixel; //This and related code is from a post by Timothy Miller to ogml
               //on Tues, Oct 17, 2006.
always @(posedge clock or negedge reset)
begin
        if (!reset) begin
                vert<=0;
                horiz<=0;
                hstate<=0;
                vstate<=0;
                {hsync,vsync,de}<=0;
                {r0,g0,b0,r1,g1,b1} <= 0; //initialize colors
                $display("%d %d %d %d %d %d",r0,g0,b0,r1,g1,b1);
        end else begin
                lastpixel <= (horiz==H_TOTAL-2);
                if (lastpixel) begin
                        horiz <= 0;
                        hstate <= 0;
                        if (vert==V_TOTAL-1)
                                vert <=0;
                        else
                                vert <= vert+1;
                end else begin
                        horiz <= horiz + 1;
                        case (horiz)
                                H_SYNCH + H_FRONT_PORCH + H_ACTIVE-1:
                                        begin
                                                hstate <= 3;
                                        end
                                H_FRONT_PORCH + H_ACTIVE-1:
                                        begin
                                                hstate <= 2;
                                        end
                                H_ACTIVE-1:
                                        begin
                                                hstate <= 1;
                                        end
                        endcase
                end
        end
end

always @(posedge clock)
begin
        g0<=horiz;
        g1<=vert;
        r0<=0;
        r1<=0;
        b0<=0;
        b1<=0;
end

always @(posedge clock)
begin
        //now all the states are correct:
        //0) Active - White.
        //1) Front Porch.
        //2) Sync signal. 0.
        //3) Back Porch.

        //now all is ready.
        //insert here the code to make colors based
        //on the various values.
        //example: just sync signals.
        if (vstate==2) //sync state
        begin
                vsync<=SYNC_STATE;
                de<=1'b0;
        end
        if (hstate==2) //sync state
        begin
                hsync<=SYNC_STATE;
                de<=1'b0;
        end
        if (hstate==1 || hstate==3) //porch state
        begin
                hsync<=PORCH_STATE;
                de<=1'b0;
        end
        if (vstate==1 || vstate==3) //vertporch state
        begin
                vsync<=PORCH_STATE;
                de<=1'b0;
        end
        if (hstate==0 && vstate==0) //draw state
        begin
                {hsync,vsync}<=DATA_STATE;
                de<=1'b1;
        end
end
always @(posedge clock)
begin
        //Now set up Vert in the same way... 
                case(vert)
                        V_TOTAL-1:
                                begin
                                        if (horiz==H_TOTAL-1)
                                        begin
                                                vert <=0;
                                                vstate <=0;
                                        end
                                        // new frame
                                end
                        V_SYNCH + V_FRONT_PORCH + V_ACTIVE-1:
                                begin
                                        vstate <= 3;
                                end
                        V_FRONT_PORCH + V_ACTIVE-1:
                                begin
                                        vstate <= 2;
                                end
                        V_ACTIVE-1:
                                begin
                                        vstate <= 1;
                                end
                endcase
end


// ----------



// Dual-link DVI
// There are two DVI transmitters.  One takes the even pixels, and
// the other takes the odd pixels.  Each one takes data at double-
// data rate.  On the rising edge, the master transmitter wants
// {r0[7:0], g0[7:4]}, and on the falling edge, {g0[3:0], b0[7:0]}.
// The slave transmitter wants the same for r1, g1, and b1.
wire [11:0] dvi_data_m_0 = {r0[9:2], g0[9:6]};
wire [11:0] dvi_data_m_1 = {g0[5:2], b0[9:2]};
wire [11:0] dvi_data_s_0 = {r1[9:2], g1[9:6]};
wire [11:0] dvi_data_s_1 = {g1[5:2], b1[9:2]};

// Now splice together the bits that go together in time.
// The lower 6 bits correspond to the extra analog precision,
// which are don't-cares for DVI.
wire [29:0] vid_data_dvi0 = {dvi_data_m_0, dvi_data_s_0, 6'b0};
wire [29:0] vid_data_dvi1 = {dvi_data_m_1, dvi_data_s_1, 6'b0};

// Since this is a DDR interface, it is convenient to use a DDR FF
// to provide the clock signal.  IIRC, we want data0 to appear with
// the rising edge of the clock, so we want to produce it on the
// negative edge.
ddrff1 ff0 (.Q(dvi_m_clk), .C0(clock), .C1(~clock), .D0(1'b0),
.D1(1'b1), .OE(1'b1));
ddrff1 ff1 (.Q(dvi_s_clk), .C0(clock), .C1(~clock), .D0(1'b0),
.D1(1'b1), .OE(1'b1));

// Syncs for DVI
always @(posedge clock) begin
    dvi_hsync <= hsync;
    dvi_vsync <= vsync;
    dvi_de <= de;
end


// Analog, 330MHz
// There is a single triple-DAC that takes one 30-bit pixel per clock,
// at the pixel rate.  We can use DDR flipflops for the data (indeed, we must
// because we use the same pins for DVI), but the clock signal has to be twice
// as fast.  This results in a radically different arrangement of bits for
// analog.  Additionally, logically, we have separated out the lower pairs
// of bits for the 10-bit precision.

wire [24:0] dac_data_hi0 = {r0[9:2], g0[9:2], b0[9:2]};
wire [5:0]  dac_data_lo0 = {r0[1:0], g0[1:0], b0[1:0]};
wire [24:0] dac_data_hi1 = {r1[9:2], g1[9:2], b1[9:2]};
wire [5:0]  dac_data_lo1 = {r1[1:0], g1[1:0], b1[1:0]};

// Splice together in order
wire [29:0] vid_data_dac0 = {dac_data_hi0, dac_data_lo0};
wire [29:0] vid_data_dac1 = {dac_data_hi1, dac_data_lo1};

// There is a single clock signal, but at twice the rate, so here we
// use a 2x clock that will be generated from a DCM.
// Did I get the polarity right?
ddrff1 ff2 (.Q(dac_clk), .C0(clock_2x), .C1(~clock_2x), .D0(1'b0),
.D1(1'b1), .OE(1'b1));

// Syncs for Analog
// In actuality, we'll want to replace these with shift registers.
// DVI transmitters take syncs, but with analog, our sync signals go
// directly to the connector, while the video data itself has a few
// cycles of latency through the DAC.  We need to delay the syncs
// to line up with the data.  In OGA, we'll make this delay variable.
always @(posedge clock) begin
    dac_hsync <= hsync;
    dac_vsync <= vsync;
    dac_de <= de;
end



// Now, select the data for DVI or analog and connect to the I/O drivers
wire using_dvi = 1;

wire [29:0] vid_data0 = using_dvi ? vid_data_dvi0 : vid_data_dac0;
wire [29:0] vid_data1 = using_dvi ? vid_data_dvi1 : vid_data_dac1;

ddrff30 ff3 (.Q(vid_data), .C0(clock), .C1(~clock),
    .D0(vid_data0), .D1(vid_data1), .OE(1'b1));

endmodule

module FDDRRSE(Q, C0, C1, CE, D0, D1, R, S);
output Q;
reg Q;
input C0, C1, CE, D0, D1, R, S;
always @(posedge C0) Q <= D0;
always @(posedge C1) Q <= D1;
endmodule

// For convenience, instantiate sets of DDR flipflops.  You can basically
// ignore this.
module ddrff1(Q, C0, C1, D0, D1, OE);
input C0, C1, D0, D1, OE;
output Q;
wire R;
FDDRRSE ff0  (.Q(R), .C0(C0), .C1(C1), .CE(1'b1), .D0(D0), .D1(D1),
.R(1'b0), .S(1'b0));
assign Q = OE ? R : 1'bz;
endmodule

module ddrff4(Q, C0, C1, D0, D1, OE);
input C0, C1, OE;
input [3:0] D0, D1;
output [3:0] Q;
ddrff1 ff0  (.Q(Q[0]), .C0(C0), .C1(C1), .D0(D0[0]), .D1(D1[0]), .OE(OE));
ddrff1 ff1  (.Q(Q[1]), .C0(C0), .C1(C1), .D0(D0[1]), .D1(D1[1]), .OE(OE));
ddrff1 ff2  (.Q(Q[2]), .C0(C0), .C1(C1), .D0(D0[2]), .D1(D1[2]), .OE(OE));
ddrff1 ff3  (.Q(Q[3]), .C0(C0), .C1(C1), .D0(D0[3]), .D1(D1[3]), .OE(OE));
endmodule

module ddrff30(Q, C0, C1, D0, D1, OE);
input C0, C1, OE;
input [29:0] D0, D1;
output [29:0] Q;
ddrff4 ff0 (.Q(Q[ 3: 0]), .C0(C0), .C1(C1), .D0(D0[ 3: 0]), .D1(D1[ 3:
0]), .OE(OE));
ddrff4 ff1 (.Q(Q[ 7: 4]), .C0(C0), .C1(C1), .D0(D0[ 7: 4]), .D1(D1[ 7:
4]), .OE(OE));
ddrff4 ff2 (.Q(Q[11: 8]), .C0(C0), .C1(C1), .D0(D0[11: 8]), .D1(D1[11:
8]), .OE(OE));
ddrff4 ff3 (.Q(Q[15:12]), .C0(C0), .C1(C1), .D0(D0[15:12]),
.D1(D1[15:12]), .OE(OE));
ddrff4 ff4 (.Q(Q[19:16]), .C0(C0), .C1(C1), .D0(D0[19:16]),
.D1(D1[19:16]), .OE(OE));
ddrff4 ff5 (.Q(Q[23:20]), .C0(C0), .C1(C1), .D0(D0[23:20]),
.D1(D1[23:20]), .OE(OE));
ddrff4 ff6 (.Q(Q[27:24]), .C0(C0), .C1(C1), .D0(D0[27:24]),
.D1(D1[27:24]), .OE(OE));
ddrff1 ff7 (.Q(Q[28]), .C0(C0), .C1(C1), .D0(D0[28]), .D1(D1[28]), .OE(OE));
ddrff1 ff8 (.Q(Q[29]), .C0(C0), .C1(C1), .D0(D0[29]), .D1(D1[29]), .OE(OE));
endmodule
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to