全部博文(56)
分类: 嵌入式
2012-06-11 10:09:56
机制和策略的分离的思想
在程序设计中,机制与策略分离的思想可以提高程序的可复用性,可维护性和可调试性使程序更具有高内聚低耦合性。如果说机制是砖,那么策略就是房子,同样的砖可以建不同的房子,我们不能把建砖和建房子混在一起实现,所以,把策略同机制揉成一团有两个负面影响:一来会使策略变得死板,难以适应用户需求的改变,二来也意味着任何策略的改变都极有可能动摇机制。 |
我们来举个例子看一下,这个思想所带来的好处,下面10年的时候写的一个小程序,当时我们接到一个要求在LCD指定位置上贴图的项目,硬件是采用xilinx的xc3s50a芯片,数据源都放在SPI Flash(S25FL064A)中,我的任务便是从这片Flash中读取所要求的数据,送到SDRAM中。 |
当时是分成两部分来完成的,一部分完成SPI Flash时序上的读写,属入机制,另一部分完成SPI Flash指定位置的数据读写,功能实现,属入策略,同一个机制可以适应不同的策略。 |
我们看机制实现:Flash_Controller.v |
//////////////////////////////////////////////////////////////////////////////// // Company: Ultrawise R&D Center // Engineer: Cheney // // Create Date: 09/29/2010 // Design Name: SPI Flash Contorller // Module Name: flash_ctr // Project Name: OSD // Target Devices: xc3s50a-5vq100 // Tool versions: ISE10.1 // // Description: This File is a SPI flash controler. // SPI mode 3( CPOL = 1'b1; CPHA = 1'b1;) // System clock not more than 100M // Dependencies: // // Revision:1.0 // Revision 0.1 - File Created // Additional Comments: // // ----------------------------------------------------------------------------- // Revision History : //------------------------------------------------------------------------------ // Ver | Author | Mod. Date | Changes Made: //------------------------------------------------------------------------------ // 0.1 | Cheney | 9/16/10 | birth // 0.2 | Cheney | 9/17/10 | Release // 0.3 | Cheney | 9/18/10 | Release // 0.4 | Cheney | 9/20/10 | Release // 0.6 | Cheney | 9/24/10 | Release // 0.6.2| Cheney | 9/24/10 | Release // 0.7 | Cheney | 9/26/10 | Release // 1.0 | Cheney | 9/29/10 | Release //------------------------------------------------------------------------------ //////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------ ////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
module Flash_Controller( input SysClk, // System clock input SysRst, // System reset input [31:0] addr, // picture address output reg [7:0] d_out, // Data ouput port output reg PDF, // Data ouput effective flag output reg Dout_Flag, // Data ouput effective flag
input RD_EN, // read enable input Miso, // Serial data output output reg Mosi, // Serial data input output reg SpiClk, // Serial clock output SpiWp_n, // SPI write protect output reg SpiCs_n // SPI chip Select );
reg [7:0] txdata; // Transmit buffer reg [7:0] rxdata; // Receive buffer reg [31:0] addr_temp; // Address buffer reg [7:0] BitCount; // Bit counter reg [3:0] receive_BitCount; // Receive bit counter
// SPI Serial clock flag reg [1:0] SpiClk_flag; // SPI State reg [1:0] Spi_State;
parameter idle = 2'b00; parameter send_cmd = 2'b01; parameter send_addr = 2'b10; parameter receive_data = 2'b11; //SPI Read Data Bytes Command parameter cmd = 8'h0b;
assign SpiWp_n = 1'b1;
/*********************************************************************************************************** SPI state machine Spansion SPI Mode 3(CPOL = 1, CPHA = 1 ) Read Data Bytes command 03H The host system must first select the device by driving SpiCs_n low.The READ command is then written to Mosi, followed by a 3-byte address (A23-A0). Each bit is latched on the rising edge of SCK. The memory array data, at that address, are output serially on Miso at a frequency fSCK, on the falling edge of SCK. *************************************************************************************************************/ always @ ( posedge SysClk)begin if( SysRst )begin // System reset SpiCs_n <= 1'b1; SpiClk <= 1'b1; BitCount <= 'd0; SpiClk_flag <= 'd0; Spi_State <= idle; PDF <= 0; Dout_Flag <= 'd0; receive_BitCount <= 'd7; rxdata <= 'h00; end else begin case( Spi_State )
idle :begin // Idle state SpiCs_n <= 1'b1; SpiClk <= 1'b1; BitCount <= 'd0; SpiClk_flag <= 'd0; PDF <= 0; Dout_Flag <= 'd0; receive_BitCount <= 'd7; if( RD_EN == 'b1 )begin Spi_State[1:0] <= send_cmd; BitCount <= 'd0; SpiClk_flag <= 0; txdata <= cmd; end else begin Spi_State[1:0] <= idle; end end
send_cmd :begin // Send 8 bit command; SpiCs_n <= 1'b0; SpiClk_flag <=SpiClk_flag+1; if(SpiClk_flag == 'd1)begin SpiClk_flag <=0; Mosi <= txdata[7]; txdata <= txdata<<1; SpiClk <= 1'b0; BitCount <= BitCount+1; end else begin SpiClk <= 1'b1; if( BitCount == 8)begin BitCount <= 'd0; Spi_State <= send_addr; addr_temp <= addr; end end end
send_addr :begin // Send 24 bit address; SpiClk_flag <=SpiClk_flag+1; if(SpiClk_flag == 'd1)begin Mosi <= addr_temp[23]; SpiClk_flag <=0; addr_temp <= addr_temp<<1; BitCount <= BitCount+1; SpiClk <= 1'b0; if( BitCount == 'd32)begin BitCount <= 'd0; Spi_State <= receive_data; end end else begin SpiClk <= 1'b1; end end
receive_data :begin //Receive 8 bit data; if(RD_EN==0) begin Spi_State[1:0] <= idle; end SpiClk_flag <= SpiClk_flag+1; if(SpiClk_flag == 'd0)begin SpiClk <= 1'b1; rxdata[ receive_BitCount ] <= Miso; receive_BitCount <= receive_BitCount - 'd1; if( receive_BitCount ==0) begin receive_BitCount <=7; end BitCount <= BitCount+1; if( BitCount == 0)Dout_Flag<='d1; if( BitCount == 8)begin BitCount <= 'd1; PDF <=1; end end else begin SpiClk <= 1'b0; SpiClk_flag <='d0; PDF <=0; if( BitCount == 8 )begin d_out <= rxdata; end end end endcase end end endmodule
|
下面是策略实现:Flash_Top.v |
//////////////////////////////////////////////////////////////////////////////// // Company: Ultrawise R&D Center // Engineer: Cheney // // Create Date: 09/29/2010 // Design Name: SPI Flash Contorl // Module Name: top_flash // Project Name: OSD // Target Devices: xc3s50a-5vq100 // Tool versions: ISE10.1 // Description: System clock not more than 100M // // The Top layer of design; // // Dependencies: // // Revision:1.0 // Revision 0.1 - File Created // Additional Comments: // // ----------------------------------------------------------------------------- // Revision History : //------------------------------------------------------------------------------ // Ver | Author | Mod. Date | Changes Made: //------------------------------------------------------------------------------ // 0.1 | Cheney | 9/16/10 | birth // 0.2 | Cheney | 9/17/10 | Release // 0.3 | Cheney | 9/18/10 | Release // 0.4 | Cheney | 9/20/10 | Release // 0.5 | Cheney | 9/22/10 | Release // 0.6 | Cheney | 9/24/10 | Release // 0.6.2| Cheney | 9/24/10 | Release // 0.7 | Cheney | 9/26/10 | Release // 1.0 | Cheney | 9/29/10 | Release //------------------------------------------------------------------------------ //////////////////////////////////////////////////////////////////////////////// `timescale 1ns / 1ns module Flash_Top( input SysClk, //system clock input SysRst, //system reset output PDF, //data ouput effective flag output [7:0] Data_Out, //data ouput port output reg Pic_SAT, // picture output flag input [31:0] EPI, //EPI[31->6:a-z] letteer EPI[5->0:bpa] /****SPI interface**************/ input Miso, output Mosi, output SpiClk, output SpiCs_n, output SpiWp_n, /*********************************/ input Flash_sdram_start, // output reg Sdram_read_start, output reg Flash_read_finished );
/********picturn address**********/
//OSD picture address parameter OSD_0 = 24'h000000;
parameter OSD_A = 24'h0C2640;
//Backgroud picture address parameter BPA1 = 24'h21dbc0;
integer Pic_Count;
reg RD_EN; reg [23:0] addr; wire Dout_Flag; reg [2:0] Pr_Mode; reg [3:0] delay;
reg [25:0] osd_l_num ; reg [5:0] bpa_num; /***************************************************** OSD modle select AND display mode *****************************************************/ always @ ( posedge SysClk)begin if( SysRst )begin Pic_Count <= 'd0; RD_EN <= 'd0; Pic_SAT <= 'd0; // Sdram_read_start<= 'd0; Flash_read_finished <= 'd0;
Pr_Mode <= 'd0; delay <= 'd0;
end else begin
if(Flash_sdram_start=='d0)begin osd_l_num <=EPI[31:6]; bpa_num <= EPI[5:0]; end
else begin if (Dout_Flag) begin Pic_SAT <= 'd1; // Sdram_read_start<= 'd1; Flash_read_finished <= 'd1; end if( PDF )begin Pic_Count <=Pic_Count + 'd1; end
case (Pr_Mode)
'd0: begin addr <= OSD_0 ; if(Pic_Count >= 'd54720 *13 +'d42432 *2 )begin RD_EN <= 'd0; //Pic_SAT <= 'd0; delay <= delay + 'd1; if(delay >= 'd10)begin // There is enough time for SPI state machine to idle state; Pic_Count <= 'd0; Pr_Mode <='d1; // addr <= OSD_A ; end end else RD_EN <= 'd1; end
'd1:begin
case (osd_l_num[25] ) 'd1: begin if(Pic_Count >= 'd54720 *1 )begin RD_EN <= 'd0; //Pic_SAT <= 'd0; delay <= delay + 'd1; if(delay >= 'd10)begin // There is enough time for SPI state machine to idle state; Pic_Count <= 'd0; osd_l_num <= osd_l_num <<1; // addr <= addr + 'd54720; delay <= 'd0; end end else begin RD_EN <= 'd1; end end 'd0: begin osd_l_num <= osd_l_num <<1; addr <= addr + 'd54720; if(osd_l_num=='d0) begin Pr_Mode <='d2; end end
endcase end
'd2:begin addr <= BPA1 +'d391680 * bpa_num; if(Pic_Count >= 'd391680 *1 )begin RD_EN <= 'd0; //Pic_SAT <= 'd0; delay <= delay + 'd1; if(delay >= 'd10)begin // There is enough time for SPI state machine to idle state; Pic_Count <= 'd0; delay <= 'd0; Pr_Mode <='d3; end end else RD_EN <= 'd1;
end 'd3: begin Pic_SAT <= 'd0; // Sdram_read_start<= 'd0; Flash_read_finished <= 'd0; end default :; endcase
end end end
Flash_Controller Flash_Controller( .SysClk(SysClk), .SysRst(SysRst), .addr({8'h00,addr}), .d_out(Data_Out), .PDF(PDF), .Dout_Flag(Dout_Flag), .RD_EN(RD_EN), .SpiClk(SpiClk), .Mosi(Mosi), .Miso(Miso), .SpiWp_n(SpiWp_n), .SpiCs_n(SpiCs_n) );
endmodule
|