源自於 https://gist.github.com/jjcarrier/1692155
module FPGA_2_ShiftReg(CLK, BYTE_IN, EN_IN, RDY, RCLK, SRCLK, OE, SER_OUT);//----------------------------CONTROL SIGNALS-----------------------------------input CLK;input [7:0] BYTE_IN; //8-bit input datainput EN_IN; //BYTE_IN ENABLE, indicates the input data is validoutput RDY; //A ready flag indicator, brought low when EN_IN=1 and stays low//until EN_IN=0 and the data has been shifted out on SER_OUT//-----------------------PHYSICAL PIN CONNECTIONS-------------------------------output RCLK; //Register CLK, pushes the FIFO data to the driver outputsoutput SRCLK; //Positive Edge Triggered Shift Register CLKoutput OE; //Output Enable (Active Low)output SER_OUT; //The serial data output//------------------------------------------------------------------------------//NOTE: Tie SRCLR to VCC since we never need to clear//reg [7:0] BYTE_IN = 8'hE7;reg [8:0] shift=0;//reg EN_IN=0;reg RCLK=0;reg SRCLK=0;reg RDY=1;wire OE;//==============================================================================//--------------------------------PARAMETERS------------------------------------//==============================================================================//If we assume CLK=24MHz, then T~=42nS//If VCC=3.3V, SRCLK at worst case is capable of 5MHz and at best 25MHz//Lets assume SRCLK=12MHz, T_SCLK~=84nS//See page 7 of the SN74HC595 datasheet for the parameters below//------------------------------NUMBER OF BITS----------------------------------parameter N=2; //This parameter is used on several registers/parameters below//---------------------PULSE DURATION PARAMETER (PAGE7)-------------------------//This parameter is used to specify in how many clock cycles of CLK must//occur prior to setting or unsetting SRCLK/RCLK HI or LOparameter [N-1:0] pulse_duration = 3; //safety time > 100ns, >=3 CLK cycles//---------------------SETUP TIME PARAMETER (PAGE7)-----------------------------//This parameter is used to control how much time is required to setup the//SER_OUT signal prior to setting SRCLK HI.//Note there is no required hold duration, once the signal is written to SER,//and SRCLK has gone HI, the next signal can be immediately setupparameter [N-1:0] setup_time = 3; //Safety time > 125ns, >=3 CLK cycles//==============================================================================//----------------------------ASSIGN THE SER_OUT--------------------------------//==============================================================================//The SER_OUT port can be thought of as a wire to the MSB of an 8-bit shift regwire SER_OUT;assign SER_OUT = shift[8]; //shift data out using MSBF//==============================================================================//--------------------------CREATE THE SRCLK SIGNAL-----------------------------//==============================================================================//Create the SRCLK signal that will be used to clock-in the serial datareg [N-1:0] clk_cnt=0;reg [1:0] SRCLK_state=0;reg SRCLK_toggle=0; //Instructs the process to toggle SRCLK for a period of timealways @(posedge CLK) begincase(SRCLK_state)0: begin //Wait for SRCLK_toggle=1if(SRCLK_toggle==1)beginSRCLK_state<=SRCLK_state+1;SRCLK<=0; //Make sure SRCLK is lowclk_cnt<=0;endend1: begin //Wait for the defined setup time, prior to setting SRCLK HIif(clk_cnt==setup_time-1)beginSRCLK<=1;clk_cnt<=0;SRCLK_state<=SRCLK_state+1;end else beginclk_cnt<=clk_cnt+1;endend2: begin //Wait for the defined pulse duration, prior to setting SRCLK LOif(clk_cnt==pulse_duration-1)beginSRCLK<=0;clk_cnt<=0;SRCLK_state<=SRCLK_state+1;end else beginclk_cnt<=clk_cnt+1;endend3: begin //Wait for SRCLK_toggle=0if(SRCLK_toggle==0) SRCLK_state<=0;endendcaseend//==============================================================================//--------------------------CREATE THE RCLK SIGNAL------------------------------//==============================================================================//Create the RCLK signal that will be used to clock-out the parallel datareg [N-1:0] clk_cnt2=0;reg [1:0] RCLK_state=0;reg RCLK_toggle=0; //Instructs the process to toggle RCLK for a period of timealways @(posedge CLK) begincase(RCLK_state)0: begin //Wait for RCLK_toggle=1if(RCLK_toggle==1)beginRCLK_state<=RCLK_state+1;RCLK<=0; //Make sure RCLK is lowclk_cnt2<=0;endend1: begin //Wait for the defined setup time, prior to setting RCLK HIif(clk_cnt2==setup_time-1)beginRCLK<=1;clk_cnt2<=0;RCLK_state<=RCLK_state+1;end else beginclk_cnt2<=clk_cnt2+1;endend2: begin //Wait for the defined pulse duration, prior to setting SRCLK LOif(clk_cnt2==pulse_duration-1)beginRCLK<=0;clk_cnt2<=0;RCLK_state<=RCLK_state+1;end else beginclk_cnt2<=clk_cnt2+1;endend3: begin //Wait for RCLK_toggle=0if(RCLK_toggle==0) RCLK_state<=0;endendcaseend//==============================================================================//-------------------CREATE THE FUNCTIONAL SWITCHING LOGIC----------------------//==============================================================================reg [1:0] state=0; //Statemachine variablereg [1:0] substate=0;reg [2:0] cnt=0;reg init_done=0;always @(posedge CLK) begincase(state)0: begin //-----------------------------Populate the FPGA's shift registerif(EN_IN==1)begin //Only start the statemachine when input is enabledshift[7:0]<=BYTE_IN;//shift[8]<=0;cnt<=0;state<=state+1;RDY<=0;SRCLK_toggle<=0;RCLK_toggle<=0;substate<=0;end else beginRDY<=1;cnt<=0;SRCLK_toggle<=0;RCLK_toggle<=0;state<=0;substate<=0;endend1: begin //-----------------------------------------Push the bits out MSBFcase(substate)0: begin //PUSH DATA ON SERshift[8:1]<=shift[7:0];shift[0]<=0;substate<=substate+1;end1: begin //PULSE SRCLKSRCLK_toggle<=1;substate<=substate+1;end2: begin //TURN OFF THE TOGGLE BITif(SRCLK==1)beginSRCLK_toggle<=0;substate<=substate+1;endend3: begin //WHEN SRCLK GOES LOW, CHECK & UPDATE cntif(SRCLK==0)beginif(cnt==7)begin//All bits have been shiftedstate<=state+1;cnt<=0;end else begin//We have more bits to shiftcnt<=cnt+1;endsubstate<=0;endendendcaseend2: begin //--------------------------Update & Activate the parallel output//First Pulse RCLK//Then indicate init_donecase(substate)0: begin //PULSE RCLKRCLK_toggle<=1;substate<=substate+1;end1: begin //TURN OFF THE TOGGLE BITif(RCLK==1)beginRCLK_toggle<=0;substate<=substate+1;endend2: begin //WHEN RCLK GOES LOW, CHECK & UPDATE cntif(RCLK==0)beginstate<=0;substate<=0;init_done<=1;RDY<=1;endendendcaseenddefault: beginstate<=0;substate<=0;init_done<=0;RDY<=1;endendcaseend//==============================================================================//------------------------INITIALIZATION DONE PROCESS---------------------------//==============================================================================//This is when the shift register's outputs are switched from HI-Z to LO-Z.//We will use this as the point in time when we should activate the outputs//after powerup. At powerup the chip will be in HI-Z state since the data will//not be valid. Once the user feeds data into this module, and the module//processes the request, the shift register's output will be enabled//permenantly. The subsequent data that is fed into this module will be updated//once all 8-bits are shifted into position. This is done in the logic process//above.reg EN_OUT=0;always @(posedge CLK) beginif(init_done==1)beginEN_OUT<=1;end else beginEN_OUT<=0;endendassign OE=~EN_OUT; //Invert OE since it is active lowendmodule
沒有留言:
張貼留言