📄 lcd_data_decode.v
字号:
reg [7:0] d3_RGB;
reg d1_HD;
reg d2_HD;
reg d3_HD;
reg d1_VD;
reg d2_VD;
reg d3_VD;
reg d1_DEN;
reg d2_DEN;
reg d3_DEN;
always @(posedge clk or negedge reset_n) begin
if (reset_n == 0) begin
// Async reset. In this case, it may seem silly. But trust
// me. It's not.
//
// This is one of those rare, rare cases where your
// design-intent is actually made clearer by putting more
// than one statement on a line.
//
d3_HD <= 0; d2_HD <= 0; d1_HD <= 0;
d3_VD <= 0; d2_VD <= 0; d1_VD <= 0;
d3_DEN <= 0; d2_DEN <= 0; d1_DEN <= 0;
d3_RGB <= 0; d2_RGB <= 0; d1_RGB <= 0;
end
else begin
d3_HD <= d2_HD; d2_HD <= d1_HD; d1_HD <= HD_in;
d3_VD <= d2_VD; d2_VD <= d1_VD; d1_VD <= VD_in;
d3_DEN <= d2_DEN; d2_DEN <= d1_DEN; d1_DEN <= DEN_in;
d3_RGB <= d2_RGB; d2_RGB <= d1_RGB; d1_RGB <= RGB_in;
end
end // always @ (posedge clk or negedge reset_n)
////////////////
// 24-bit output.
//
// Our outputs, of course, are delivered in a register.
//
// Blue comes first in the sequence, so it will be the most-delayed
// version of the 8-bit input-data; green the
// second-most-delayed, and red the least-delayed.
//
// Because we're adding another cycle of delay to the output, we
// have to add the same delay, with the same enable-signal, to
// the sync-signals. If we just obey the simple rule: "Do unto
// the sync-signals as we do unto the red-byte," then we can't lose.
//
reg [7:0] LCD_R;
reg [7:0] LCD_G;
reg [7:0] LCD_B;
reg LCD_HD;
reg LCD_VD;
reg LCD_DEN;
wire output_clk_enable; // Computed later from phase-counter
always @(posedge clk or negedge reset_n) begin
if (reset_n == 0) begin
LCD_R <= 0;
LCD_G <= 0;
LCD_B <= 0;
LCD_HD <= 0;
LCD_VD <= 0;
LCD_DEN <= 0;
end
else begin
if (output_clk_enable) begin
LCD_R <= d1_RGB;
LCD_G <= d2_RGB;
LCD_B <= d3_RGB;
LCD_HD <= d3_HD;
LCD_VD <= d3_VD;
LCD_DEN <= d3_DEN;
end
end // else: !if(reset_n == 0)
end // always @ (posedge clk or negedge reset_n)
////////////////
// Phase-counter.
//
// There are only three phases. And the phase-synchronization
// event is well-defined. So. Here are the easy parts:
//
// * Building a counter that goes: "zero,one,two,zero,one,two..."
// * Synchronizing it every time HD changes state.
//
// Here are the hard parts:
//
// 1) Deciding which of our delayed versions of HD to look at
// 2) Which counter-value we use to determine NCLK: 0, 1, or 2.
// 3) Which counter-value we use to determine out_clk_enable:
//
// Fine. So let's start with something easy: Building a little
// counter. How perfectly conventional.
//
reg [1:0] color_phase_counter;
wire color_phase_counter_sync_clear;
always @ (posedge clk or negedge reset_n) begin
if (reset_n == 0) begin
color_phase_counter <= 0;
end
else begin
if (color_phase_counter_sync_clear) begin
color_phase_counter <= 0;
end
else begin
color_phase_counter = (color_phase_counter == 2) ?
(0 ) :
(color_phase_counter + 1) ;
end
end // else: !if(reset_n == 0)
end // always @ (posedge clk or negedge reset_n)
////////////////
// Defining the counter-phases.
//
// The phase-counter only drives two things: It tells us when to
// enable the output registers, and it tells us when to drive a
// zero onto the NCLK output.
//
// From looking at the timing diagrams (above), it's pretty clear
// that you enable the output-registers *first,* and then drive
// NCLK low on the subsequent clock-cycle. OK. That's easy to
// do:
//
// Style note: I generally do not use `define. I usually
// prefer parameters. But this circuit really is performing a
// fixed-function. In this specific case: I don't think they
// will ever invent a fourth primary color, so it's safe to
// hard-code-in a bunch of assumptions that this thing will
// only ever count to three.
//
// Let's just say that the numbering-and-naming of the phases is
// arbitrary, and that the real relationship between the
// phase-counter and the Sync+B+G+R data is determined by the
// timing of the phase-counter synchronization-event, which we
// compute below.
//
// Now that we've said "the phase-numbering is arbitrary," I can
// defie it arbitrarily, like this:
//
`define PHASE_OUTPUT_CLK_ENABLE 0
`define PHASE_NCLK_LOW 1
assign output_clk_enable = (color_phase_counter == `PHASE_OUTPUT_CLK_ENABLE);
wire pNCLK = ~(color_phase_counter == `PHASE_NCLK_LOW );
////////////////
// NCLK output-register.
// Totally vanilla.
//
reg LCD_NCLK;
always @(posedge clk or negedge reset_n) begin
if (reset_n == 0)
LCD_NCLK <= 0;
else
LCD_NCLK <= pNCLK;
end
////////////////
// Phase-counter synchronization event.
//
// We look for a transition (either 1->0 or 0->1) on HD, and use
// that to drive the synchronous-clear on the phase counter.
//
// But we have three versions of HD available to us: HD with
// three, two, and one clock of delay (remember: we promised not
// to use the RAW input HD for anything in our circuit...that
// would be nuts!).
//
// We can think of our circuit as a four-stage pipeline, with the data &
// sync signals flowing-through. The phase-counter determines
// what inputs & enables to drive into the output-registers, so
// we can think of the phase-counter as sitting in "Stage 3" of
// the pipeline, right before the output.
//
// The synchronous-clear is an input to the phase-counter, whose
// result won't be seen in the phase-counter output until the
// subsequent clock-cycle. So you can think of the
// syncronous-clear being computed in "Stage 2" of the pipeline.
//
// So if the "d2" version of HD has suddenly transitioned "low,"
// then you know that the "B" pixel is in the d2-stage as well.
// If we assert sync-clear, then (on the next clock-cycle) B will
// move into the d3 stage and the color-phase counter will be
// zero. That's happy, because the zero phase-count value will
// enable d3-B into the output-registers at the right time.
//
// So: By that English-verbal argument: We're looking for d2_HD
// being a different state from what it was on the previous
// clock-cycle, like this:
//
assign color_phase_counter_sync_clear = (d2_HD != d3_HD);
endmodule // LCD_DATA_DECODE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -