Always Turn Left

http://code.google.com/codejam/contest/dashboard?c=agxjb2RlamFtLXByb2RyEAsSCGNvbnRlc3RzGIP6AQw#s=p1

 

Problem

You find yourself standing outside of a perfect maze. A maze is defined as "perfect" if it meets the following conditions:

  1. It is a rectangular grid of rooms, R rows by C columns.
  2. There are exactly two openings on the outside of the maze: the entrance and the exit. The entrance is always on the north wall, while the exit could be on any wall.
  3. There is exactly one path between any two rooms in the maze (that is, exactly one path that does not involve backtracking).

You decide to solve the perfect maze using the "always turn left" algorithm, which states that you take the leftmost fork at every opportunity. If you hit a dead end, you turn right twice (180 degrees clockwise) and continue. (If you were to stick out your left arm and touch the wall while following this algorithm, you'd solve the maze without ever breaking contact with the wall.) Once you finish the maze, you decide to go the extra step and solve it again (still always turning left), but starting at the exit and finishing at the entrance.

The path you take through the maze can be described with three characters: 'W' means to walk forward into the next room, 'L' means to turn left (or counterclockwise) 90 degrees, and 'R' means to turn right (or clockwise) 90 degrees. You begin outside the maze, immediately adjacent to the entrance, facing the maze. You finish when you have stepped outside the maze through the exit. For example, if the entrance is on the north and the exit is on the west, your path through the following maze would be WRWWLWWLWWLWLWRRWRWWWRWWRWLW:

If the entrance and exit were reversed such that you began outside the west wall and finished out the north wall, your path would be WWRRWLWLWWLWWLWWRWWRWWLW. Given your two paths through the maze (entrance to exit and exit to entrance), your code should return a description of the maze.

Input

The first line of input gives the number of cases, N. N test cases follow. Each case is a line formatted as

entrance_to_exit exit_to_entrance

All paths will be at least two characters long, consist only of the characters 'W', 'L', and 'R', and begin and end with 'W'.

Output

For each test case, output one line containing "Case #x:" by itself. The next R lines give a description of the R by C maze. There should be C characters in each line, representing which directions it is possible to walk from that room. Refer to the following legend:

Character   Can walk north?   Can walk south?   Can walk west?   Can walk east?  
1YesNoNoNo
2NoYesNoNo
3YesYesNoNo
4NoNoYesNo
5YesNoYesNo
6NoYesYesNo
7YesYesYesNo
8NoNoNoYes
9YesNoNoYes
aNoYesNoYes
bYesYesNoYes
cNoNoYesYes
dYesNoYesYes
eNoYesYesYes
fYesYesYesYes

Limits

1 ≤ N ≤ 100.

Small dataset

2 ≤ len(entrance_to_exit) ≤ 100,
2 ≤ len(exit_to_entrance) ≤ 100.

Large dataset

2 ≤ len(entrance_to_exit) ≤ 10000,
2 ≤ len(exit_to_entrance) ≤ 10000.

 

 

这个题目是走迷宫类算法的一个扩展, 按照左转优先法则走迷宫, 给出从入口到出口,和从出口到入口两条走法,要求还原迷宫.

没有验证能否还原出解, 解是否唯一, 我只是写了个算法, 还原出一个最小解, 就pass了.

基本想法是先创建一个原始迷宫, 迷宫每个点的4个方向状态都是Unknown, 然后按照路径走迷宫, 如果是L, 说明位置当前+0,是unpass,+90是pass, 如果是R, 说明当前位置+0, +90,+180都是unpass, 而+270是pass, 如果是RR(掉头), 说明位置当前+90,+0,+270都是unpass, 如果是w, 说明当前位置+0是pass,+90是unpass.同时下一个位置的+180是pass.

正着走一遍,然后掉头,再走回来, 最后输出每个点的状态就可以了.

 

数据结构用0,1,2,3分别来表示方向, 用&0x3(即%4)来做溢出保护, 减少了转方向的判断.

时间复杂度O(n), 空间复杂度(O(n*n)),主要是一开始不知道整个迷宫有多大,所以开辟了一块n*n的空间来作为最大迷宫,如果可以动态生成,空间复杂度会小很多.

 

代码:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

#define MAX_LENGTH  (10004)
#define TYPE_UNKNOWN (0)
#define TYPE_PASS  (1)
#define TYPE_UNPASS  (2)

typedef struct tagNode
{
 char pPass[4];
 
} NODE, *LPNODE;
//east=0, south=1, west=2, north=3;

class Maze
{
private:
 NODE* m_Maze;
 int m_nWidth;
 int m_nHeight;
 int m_nLeft;
 int m_nRight;
 int m_nTop;
 NODE* m_pCur;
 int m_nCx;
 int m_nCy;
 int m_nDir;
public:
 Maze();
 ~Maze();
 void Clean();
 void TurnLeft();
 void TurnRight();
 void Turn180();
 void Move();
 void MoveOnly();
 void Print();
};

Maze::Maze()
{
 m_Maze = (NODE*)malloc(MAX_LENGTH*MAX_LENGTH*sizeof(NODE));
 Clean();
}

Maze::~Maze()
{
 free(m_Maze);
}

void Maze::Clean()
{
 memset(m_Maze, 0, MAX_LENGTH*MAX_LENGTH*sizeof(NODE));

 m_nWidth = MAX_LENGTH;
 m_nHeight = 1;
 m_nLeft = MAX_LENGTH/2;
 m_nRight = MAX_LENGTH/2;
 m_nCx = MAX_LENGTH/2;
 m_nCy = 0;
 m_nDir=1;
 m_pCur = m_Maze + m_nCx;
}

void Maze::TurnLeft()
{
 m_nDir += 3;
 m_nDir &= 0x3;
 m_pCur->pPass[m_nDir] = TYPE_PASS;
 
}

void Maze::TurnRight()
{
 m_nDir += 1;
 m_nDir &= 0x3;
 m_pCur->pPass[m_nDir] = TYPE_PASS;
 m_pCur->pPass[(m_nDir+3)&0x3] = TYPE_UNPASS;
 m_pCur->pPass[(m_nDir+2)&0x3] = TYPE_UNPASS;
}

void Maze::Turn180()
{
 m_nDir += 2;
 m_nDir &= 0x3;
 m_pCur->pPass[(m_nDir+3)&0x3] = TYPE_UNPASS;
 m_pCur->pPass[(m_nDir+2)&0x3] = TYPE_UNPASS;
 m_pCur->pPass[(m_nDir+1)&0x3] = TYPE_UNPASS;
}

void Maze::Move()
{
 m_pCur->pPass[m_nDir]=TYPE_PASS;
 switch(m_nDir)
 {
  case 0:m_nCx++;m_pCur++;if(m_nRight<m_nCx)m_nRight=m_nCx;break;
  case 1:m_nCy++;m_pCur+=m_nWidth;if(m_nHeight<m_nCy)m_nHeight=m_nCy;break;
  case 2:m_nCx--;m_pCur--;if(m_nLeft>m_nCx)m_nLeft=m_nCx;break;
  case 3:m_nCy--;m_pCur-=m_nWidth;break;
  default:break;
 }
 m_pCur->pPass[(m_nDir+2)&0x3]=TYPE_PASS;
}

void Maze::MoveOnly()
{
 m_pCur->pPass[m_nDir]=TYPE_PASS;
 switch(m_nDir)
 {
  case 0:m_nCx++;m_pCur++;break;
  case 1:m_nCy++;m_pCur+=m_nWidth;break;
  case 2:m_nCx--;m_pCur--;break;
  case 3:m_nCy--;m_pCur-=m_nWidth;break;
  default:break;
 }
 m_pCur->pPass[(m_nDir+2)&0x3]=TYPE_PASS;
}

void Maze::Print()
{
 int x, y;
 
 for(y=1; y<=m_nHeight; y++)
 {
  NODE* pLine = m_Maze + y * m_nWidth + m_nLeft;
  for(x=m_nLeft; x<=m_nRight; x++, pLine++)
  {
   int nVal=0;
   if(pLine->pPass[0]==TYPE_PASS) nVal+=8;
   if(pLine->pPass[1]==TYPE_PASS) nVal+=2;
   if(pLine->pPass[2]==TYPE_PASS) nVal+=4;
   if(pLine->pPass[3]==TYPE_PASS) nVal+=1;
   if(nVal<=9) nVal += '0';
   else nVal = nVal-10+'a';
   printf("%c", nVal);
  }
  printf("/n");
 }
}

int main()
{
 int nRound;
 int i, j;
 FILE* fp;
 char pFir[MAX_LENGTH], pSec[MAX_LENGTH];
 Maze maze;

 fp = fopen("1.txt", "r");
 fscanf(fp, "%d", &nRound);

 for(i=0; i<nRound; i++)
 {
  maze.Clean();

  fscanf(fp, "%s %s", pFir, pSec);
  for(j=0; j<MAX_LENGTH; j++)
  {
   if(pFir[j+1]=='/0') break;
   if(pFir[j]=='W') maze.Move();
   if(pFir[j]=='L') maze.TurnLeft();
   if(pFir[j]=='R')
   {
    if(pFir[j+1]=='R')
    {
     maze.Turn180();
     j++;
    }
    else
    {
     maze.TurnRight();
    }
   }
  }
  maze.MoveOnly();
  maze.Turn180();
  for(j=0; j<MAX_LENGTH; j++)
  {
   if(pSec[j+1]=='/0') break;
   if(pSec[j]=='W') maze.Move();
   if(pSec[j]=='L') maze.TurnLeft();
   if(pSec[j]=='R')
   {
    if(pSec[j+1]=='R')
    {
     maze.Turn180();
     j++;
    }
    else
    {
     maze.TurnRight();
    }
   }
  }
  maze.MoveOnly();
  printf("Case #%d:/n", i+1);
  maze.Print();
 }
 fclose(fp);
 return 0;
}

 

module follow( input sysclk, // 系统时钟 input rst_n, // 复位信号(低电平有效) input ir_left, // 左侧红外传感器(检测黑线为1) input ir_right, // 右侧红外传感器 output reg follow_in1, // 左侧电机正极控制 output reg follow_in2, // 左侧电机负极控制 output reg follow_in3, // 右侧电机正极控制 output reg follow_in4 // 右侧电机负极控制 ); // 状态编码(2位) localparam STOP = 3'b000; localparam FORWARD = 3'b001; localparam LEFT = 3'b010; localparam RIGHT = 3'b011; localparam SEARCH = 3'b100; // 寻线状态 reg [2:0] state,next_state; // 当前状态(2位) reg [1:0] sensor_sync; // 下一状态 reg [23:0] counter; // 24位计数器 (用于消抖) // 传感器同步寄存器(避免亚稳态) reg ir_left_sync, ir_right_sync; always @(posedge sysclk) begin if (!rst_n) begin sensor_sync <= 2'b00; counter <= 24'd0; end else if (counter == 24'd5_000_000) begin // 100ms消抖 @50MHz sensor_sync <= {ir_left, ir_right}; counter <= 24'd0; end else begin counter <= counter + 1; end end always @(posedge sysclk) begin if (!rst_n) begin ir_left_sync <= 1'b0; ir_right_sync <= 1'b0; end else begin ir_left_sync <= ir_left; ir_right_sync <= ir_right; end end // 状态寄存器更新 always @(posedge sysclk or negedge rst_n) begin if (!rst_n) begin state <= STOP; end else begin state <= next_state; end end always @(*) begin case ({ir_left_sync, ir_right_sync}) 2'b11: next_state = FORWARD; 2'b10: next_state = LEFT; 2'b01: next_state = RIGHT; 2'b00: next_state = state; default: next_state = STOP; endcase end always @(posedge sysclk or negedge rst_n) begin if (!rst_n) begin {follow_in1, follow_in2, follow_in3, follow_in4} <= 4'b0000; end else begin case (state) FORWARD: begin // 双轮正转前进 {follow_in1, follow_in2, follow_in3, follow_in4} <= 4'b1010; end LEFT: begin {follow_in1, follow_in2, follow_in3, follow_in4} <= 4'b0010; end RIGHT: begin // 左轮正转,右轮反转(或停转) {follow_in1, follow_in2, follow_in3, follow_in4} <= 4'b1000; end STOP: begin // 所有电机停止 {follow_in1, follow_in2, follow_in3, follow_in4} <= 4'b0000; end default: begin {follow_in1, follow_in2, follow_in3, follow_in4} <= 4'b0000; end endcase end end endmodule 这个代码使用红外模块但是无法实现跟随地上的循迹黑色塑胶带,请在原代码的基础上修改。
06-30
vivado万年历设计,下面代码还少了什么模块,麻烦补齐 module key_filter #(parameter WIDTH = 20'd99) //因为是仿真,所以该值要小一点。如果是下载到实物上,这个值就改为999_999 ( input sys_clk,sys_rest,key_in, output reg key_flag ); reg[19:0] CNT_20MS; always @(posedge sys_clk or negedge sys_rest) begin if(!sys_rest) CNT_20MS<=20'd0; else if(key_in==1'b1) //按键未按下为1 按下为0 CNT_20MS<=20'd0; else if(CNT_20MS==WIDTH) CNT_20MS<=WIDTH; else CNT_20MS<=CNT_20MS+1; end always @(posedge sys_clk or negedge sys_rest) begin if(!sys_rest) key_flag<=1'b0; else if(CNT_20MS==WIDTH-1) key_flag<=1'b1; else key_flag<=1'b0; end endmodule //按键驱动模块 //实现功能:检测按键并转换状态。按键按下为0 //输入信号:系统时钟、复位、翻页按键、数码管闪烁选择按键、加一按键 //输出信号:翻页选择状态、数码管闪烁选择状态、时分秒和年月日和闹钟时分秒的加一脉冲信号 //当按下翻页按键时,转换翻页状态、当按下数码管闪烁选择按键时转换当前数码管闪烁选择状态、当按下加一按键时生成每个部分的专属增一脉冲信号(秒分时....的增一信号都分开) //显示状态有三个(一共有三页)状态转换为:00-->01-->10 //数码管显示状态有四个(一个没选中和三个不同得选择)状态转换:00-->01-->10-->11(00是谁也没选的状态) module key_drive_module(system_clk,reset,key_turn,key_switch,key_add,flag_switch,flag_turn,second_add,minute_add,hour_add,day_add,month_add,year_add,alarm_second_add,alarm_minute_add,alarm_hour_add,select_sign); input key_turn,key_switch,key_add,system_clk,reset; output [1:0] flag_switch,flag_turn; output select_sign; output second_add,minute_add,hour_add,day_add,month_add,year_add,alarm_second_add,alarm_minute_add,alarm_hour_add; reg [3:0] flag_add=0; reg second_add,minute_add,hour_add,day_add,month_add,year_add,alarm_second_add,alarm_minute_add,alarm_hour_add; reg [1:0] flag_turn=0,turn_state=0,turn_next_state=0; //翻页状态机(分别是输出、现态、次态) reg [1:0] flag_switch=0,switch_state=0,switch_next_state=0;//当前选择数码管状态机 assign select_sign=(flag_add==4'b0000); //页面切换的状态机 //次态电路 always@(negedge key_turn or negedge reset) //敏感信号为页面切换按键(按下按键切换状态) 页面切换状态:00-->01-->10 begin if(!reset) turn_next_state=2'b00; else case(turn_state) 2'b00:turn_next_state=2'b01; 2'b01:turn_next_state=2'b10; 2'b10:turn_next_state=2'b00; default:turn_next_state=2'b00; endcase end //次态到现态转换 always@(posedge system_clk or negedge reset) begin if(!reset) turn_state<=2'b00; else turn_state<=turn_next_state; end //输出电路 always@(reset or turn_state) begin if(!reset) flag_turn= 2'b00; else case(turn_state) 2'b00:flag_turn=2'b00; 2'b01:flag_turn=2'b01; 2'b10:flag_turn=2'b10; default:flag_turn=2'b00; endcase end //数码管闪烁选择的状态机 //次态电路 always@(negedge key_switch or negedge reset) //敏感信号为选项切换按键(按下按键切换状态) 页面切换状态:00-->01-->10-->11 begin if(!reset) switch_next_state=2'b00; else case(switch_state) 2'b00:switch_next_state=2'b01; 2'b01:switch_next_state=2'b10; 2'b10:switch_next_state=2'b11; 2'b11:switch_next_state=2'b00; default:switch_next_state=2'b00; endcase end //次态-->现态转换 always@(posedge system_clk or negedge reset) begin if(!reset) switch_state<=2'b00; else switch_state<=switch_next_state; end //输出电路 always@(reset or switch_state) begin if(!reset) flag_switch= 2'b00; else case(switch_state) 2'b00:flag_switch=2'b00; 2'b01:flag_switch=2'b01; 2'b10:flag_switch=2'b10; 2'b11:flag_switch=2'b11; default:switch_next_state=2'b00; endcase end //增一选择项目 always@(turn_state or switch_state or reset) //敏感信号为当前页面状态、数码管闪烁选择状态(当选择项目变动时,增一选择项目也随之变化) begin if(!reset) flag_add=4'b0000;//0000代表空状态(都没选) else case(turn_state)//当前页面 2'b00: //第一页(时分秒) case(switch_state)//当前数码管闪烁选择 2'b00:flag_add=4'b0000; 2'b01:flag_add=4'b0001;//选中秒 2'b10:flag_add=4'b0010;//选中分 2'b11:flag_add=4'b0011;//选中时 endcase 2'b01: //第二页(年月日) case(switch_state) 2'b00:flag_add=4'b0000; 2'b01:flag_add=4'b0101;//选中日 2'b10:flag_add=4'b0110;//选中月 2'b11:flag_add=4'b0111;//选中年 endcase 2'b10: //第三页(闹钟) case(switch_state) 2'b00:flag_add=4'b0000; 2'b01:flag_add=4'b1001;//选中闹钟秒 2'b10:flag_add=4'b1010;//选中闹钟分 2'b11:flag_add=4'b1011;//选中闹钟时 endcase default:flag_add=4'b0000; endcase end //生成增一的专属信号 always@(key_add)//敏感信号为增一按键,当按键按下时,专属增一脉冲为0;当按键抬起时,专属增一脉冲为1; begin case(flag_add) 4'b0001:second_add=key_add; 4'b0010:minute_add=key_add; 4'b0011:hour_add=key_add; 4'b0101:day_add=key_add; 4'b0110:month_add=key_add; 4'b0111:year_add=key_add; 4'b1001:alarm_second_add=key_add; 4'b1010:alarm_minute_add=key_add; 4'b1011:alarm_hour_add=key_add; default:; //其它的都什么也不执行 endcase end endmodule //时钟模块 //实现功能:计时功能及其时钟设置功能 //输入信号:系统时钟、复位按键、时分秒年月日的加一信号 //输出信号:年月日和时分秒、秒脉冲 module clock(system_clk,reset,select_sign,second_add,minute_add,hour_add,day_add,month_add,year_add,second,minute,hour,day,month,year); input system_clk,reset,second_add,minute_add,hour_add,day_add,month_add,year_add; input select_sign; output [5:0] second;//最大59 output [5:0] minute;//最大59 output [4:0] hour;//最大23 output [4:0] day;//最大31 output [3:0] month;//最大12 output [6:0] year;//最大99 reg [31:0]p;//最大24999999 wire pulse_second;//秒脉冲 reg [5:0] second; reg [5:0] second_set; wire pulse_minute; //分脉冲 reg [5:0] minute; reg [5:0] minute_set; wire pulse_hour;//小时脉冲 reg [4:0] hour; reg [4:0] hour_set; wire pulse_day;//日脉冲 reg [4:0] day=5'd8; reg [4:0] day_set; reg [3:0] day_month; reg [6:0] day_year; wire pulse_month;//月脉冲 reg [3:0] month; reg [3:0] month_set; wire pulse_year;//年脉冲 reg [6:0] year; reg [6:0] year_set; always@(posedge system_clk or negedge reset)//敏感信号:系统时钟和复位 begin if(!reset) p<=0; else if(p==49999999) p<=0; else p<=p+1; end assign pulse_second=(p==49999999 && (select_sign==1'b1)); //秒脉冲 //秒部分 always@(posedge system_clk) begin if(!reset) second<=6'd35; else if(pulse_second) //秒脉冲 if(second>=59) second<=0; else second<=second+1; else if(!second_add) //增一信号 second<=second_set; else second<=second; end //分脉冲信号的生成 assign pulse_minute=(second==6'd59 && pulse_second==1'b1); //分脉冲 //秒设置 always@(negedge second_add) begin second_set=second; //先读取当前秒 if(second_set>=59) second_set=0; else second_set=second_set+1; end //分部分 always@(posedge system_clk) begin if(!reset) minute<=6'd24; else if(pulse_minute) if(minute>=59) minute<=0; else minute<=minute+1; else if(!minute_add) minute<=minute_set; else minute<=minute; end //小时脉冲的生成 assign pulse_hour=(minute==6'd59 && pulse_minute==1'b1); //小时脉冲 //分设置 always@(negedge minute_add) begin minute_set=minute; if(minute_set>=59) minute_set=0; else minute_set=minute_set+1; end //小时部分 always@(posedge system_clk) begin if(!reset) hour<=5'd16; else if(pulse_hour) if(hour>=23) hour<=0; else hour<=hour+1; else if(!hour_add) hour<=hour_set; else hour<=hour; end //天脉冲的生成 assign pulse_day=(hour==5'd23 && pulse_hour==1'b1); //小时的设置 always@(negedge hour_add) begin hour_set=hour; if(hour_set>=23) hour_set=0; else hour_set=hour_set+1; end //天部分 always@(posedge system_clk) begin if(!reset) day<=5'd8; else if(pulse_day) //天脉冲 if(month==1 || month==3 ||month==5 || month==7 || month==8 || month==10 || month==12) if(day>=31) day<=1; else day<=day+1; else if(month==4 || month==6 ||month==9 || month==11) if(day>=30) day<=1; else day<=day+1; else if(month==2 && (year%4==0)) if(day>=29) day<=1; else day<=day+1; else if(day>=28) day<=1; else day<=day+1; else if(!day_add) day<=day_set; else day<=day; end //月脉冲的生成 assign pulse_month=((day==5'd28 && month==4'd2 && (year%4!=0) && pulse_day==1'b1) ||(day==5'd29 && month==4'd2 && (year%4==0) && pulse_day==1'b1) ||(day==5'd30 && (month==4'd4 || month==4'd6 ||month==4'd9 || month==4'd11) && pulse_day==1'b1) ||(day==5'd31 && (month==4'd1 || month==4'd3 ||month==4'd5 || month==4'd7 || month==4'd8 || month==4'd10 || month==4'd12) && pulse_day==1'b1)); //天的设置 always@(negedge day_add) begin day_set=day; day_month=month; day_year=year; if(day_month==1 || day_month==3 ||day_month==5 || day_month==7 || day_month==8 || day_month==10 || day_month==12) if(day_set>=31) day_set<=1; else day_set<=day_set+1; else if(day_month==4 || day_month==6 ||day_month==9 || day_month==11) if(day_set>=30) day_set<=1; else day_set<=day_set+1; else if(day_month==2 && (day_year%4==0)) //闰年 if(day_set>=29) day_set<=1; else day_set<=day_set+1; else if(day_set>=28) day_set<=1; else day_set<=day_set+1; end //月部分 always@(posedge system_clk) begin if(!reset) month<=4'd12; else if(pulse_month) if(month>=12) month<=1; else month<=month+1; else if(!month_add) month<=month_set; else month<=month; end //年脉冲的生成 assign pulse_year=(month==4'd12 && pulse_month==1'b1); //月设置 always@(negedge month_add) begin month_set=month; if(month_set>=12) month_set=1; else month_set=month_set+1; end //年部分 always@(posedge system_clk) begin if(!reset) year<=7'd21; else if(pulse_year) if(year>=99) year<=0; else year<=year+1; else if(!year_add) year<=year_set; else year<=year; end //年设置 always@(negedge year_add) begin year_set=year; if(year_set>=99) year_set=0; else year_set=year_set+1; end endmodule //闹钟模块 //实现功能:设置闹钟,闹钟时间到时闹钟响1分钟 //输入信号:拨码开关(使能信号)、时钟模块的时分秒、按键驱动模块的时分秒专属增一脉冲信号 //输出信号:LED灯、蜂鸣器、当前的设置时间(给显示模块来显示) module alarm(sys_clk,reset,second,minute,hour,switch_alarm,alarm_second_add,alarm_minute_add,alarm_hour_add,led,beep,alarm_second,alarm_minute,alarm_hour); input sys_clk,reset,switch_alarm,alarm_second_add,alarm_minute_add,alarm_hour_add; input [5:0] second; input [5:0] minute; input [4:0] hour; output led,beep; output [5:0] alarm_second; output [5:0] alarm_minute; output [4:0] alarm_hour; reg [5:0] alarm_second; reg [5:0] alarm_minute; reg [4:0] alarm_hour; assign led=switch_alarm; //拨码开关开时亮 assign beep=((minute==alarm_minute&&hour==alarm_hour&&switch_alarm==1'b1)||(minute==6'd59 && second==6'd59)); //设置秒 always@(negedge alarm_second_add or negedge reset) begin if(!reset) alarm_second<=6'd30; else if(alarm_second>=59) alarm_second<=0; else alarm_second<=alarm_second+1; end //设置分 always@(negedge alarm_minute_add or negedge reset) begin if(!reset) alarm_minute<=6'd30; else if(alarm_minute>=59) alarm_minute<=0; else alarm_minute<=alarm_minute+1; end //设置时 always@(negedge alarm_hour_add or negedge reset) begin if(!reset) alarm_hour<=6'd12; else if(alarm_hour>=23) alarm_hour<=0; else alarm_hour<=alarm_hour+1; end endmodule module seg( input sys_clk,sys_rest, input [15:0] data, output reg [3:0] sel, output reg [6:0] seg_led ); parameter CLK_NUM=4'd10; parameter MSNUM=14'd5000; reg [3:0] CNT_NUM; reg CLK; reg [12:0] MSCNT; reg MS_flag; reg [3:0] num_display; reg [15:0] num; reg [2:0] sel_num; //选择哪一位数码管被点亮 //wire define wire [3:0] data0 ; // 个位数 wire [3:0] data1 ; // 十位数 wire [3:0] data2 ; // 百位数 wire [3:0] data3 ; // 千位数 //提取显示数值所对应的十进制数的各个位 assign data0 = data[3:0]; // 个位数 assign data1 = data[7:4]; // 十位数 assign data2 = data[11:8]; // 百位数 assign data3 = data[15:12]; // 千位数 always @(posedge sys_clk or negedge sys_rest) begin if(!sys_rest) begin CNT_NUM<=4'd0; CLK<=1'd1; end else if(CNT_NUM<=CLK_NUM/2-1'b1) begin CLK<=~CLK; CNT_NUM<=4'd0; end else begin CNT_NUM<=CNT_NUM+1; CLK<=CLK; end end always @(posedge CLK or negedge sys_rest) begin if(!sys_rest) num<=16'd0; else begin num[15:12] <= data3; //则依次给4位数码管赋值 num[11:8] <= data2; num[ 7:4] <= data1; num[ 3:0] <= data0; end end always @(posedge CLK or negedge sys_rest) begin //产生1ms脉冲 if(!sys_rest) begin MSCNT<=13'd0; MS_flag<=1'b0; end else if(MSCNT==MSNUM-1) begin MSCNT<=13'd0; MS_flag<=1'b1; end else begin MSCNT<=MSCNT+1; MS_flag<=1'b0; end end
06-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值